Wednesday, December 23, 2015

MSP432 LaunchPad review

The new MSP432 LaunchPad is very cool. Here it is in all its glory. We got our hands on a pre-production unit in red, but it looks like the production units are all black.

The MSP432 Processor

It is a 32-bit 48MHz Cortex-M4F processor with the MSP430 peripherals. Performance stated of 1.18f DMIPS/Mhz. At 48MHz it uses 7.6mA if using the LDO, 4.6mA if using the DC/DC converter. I'll explain more about that below. So it's pretty good.

  • Memory - 256kB of flash, 16kB of INFO Memory, 64kB of SRAM (including 8kB of Backup Memory - we're not in the MSP430 land anymore), and 32KB of ROM preloaded with MSPWare Driver Libraries.
  • Voltage Range: 1.62V to 3.7V
  • Current consumption: Less than 1uA while running with RTC, Active is 90uA/MHz
  • Clocking: the flexible clocking that we know and love - internal DCO up to 48MHz, support for 32kHz xtal, a few different internal oscillators.
  • DMA - if you use DMA in a micro controller please comment below. I've always wondered who actually uses it.
  • Timers - 4x 16-bit timers, 2x 32-bit timers. Fewer than I would have thought.
  • Serial - 4x eUSCI_B modules with I2C/SPI and 4x eUSCI_A modules with UART/SPI/IrDA. Does anyone still use IrDA?
  • GPIO - All IOs can generate an Interrupt, like Tiva (yay!), all can drive up to 6mA, and 4 of them can drive up to 20mA. 24 of the pins support pin mapping - a very cool feature.
  • Analog - 14-bit 1MSPS ADC (ooh, that's cool) with (finally!) an internal voltage reference that doesn't suck (10ppm / degree C stability) and 2 comparators.
  • Hardware Accelerators for AES and CRC
  • Package - LQFP100, 80NFBGA, 60VQFN. The LQFP is pretty large, 14mm square. Same size as the TM4C129X in the debugger section of the Launchpad but with bigger pitch - should make soldering easier.
  • Built-In DC/DC converter or LDO option. This is new, never seen this on a processor before. The processor core operates at a lower voltage than the supply voltage. This voltage can be supplied by an LDO or DC/DC switching regulator. Most processors use an LDO. The MSP432 has an internal DC/DC regulator - you just need to attach an external inductor and a couple capacitors.  Using the DC/DC regulator reduces operating and sleep current consumption by about 40%.

The LaunchPad

The board is designed quite well. Like all Launchpads, it has an onboard debugger. Lets hope that it's more reliable than the MSP430G2 Launchpad debugger - that's the buggiest debugger I've ever used. The debugger on the '432 Launchpad can be electrically disconnected from the processor section via headers. That's very cool too. The headers that connect the two are well labeled:

  • Power: GND, 3V3, 5V
  • Serial: RTS, CTS, RXD, TXD

There is a "Launchpad-XL" pin configuration (the 40 pin version with 35 GPIOs used on the '5529 LaunchPad) so it should support all the new BoosterPacks. Unfortunately they didn't say whether it would support the SensorHub - that would be a cool combination. They also pulled out the unused pin to a separate unpopulated header. There's 26 pins on that header.  So there's a total of 35 + 26 = 61 GPIOs available.

Peripherals - Similar to the TM4C123 LaunchPad, this board has 2x buttons + reset button, 1 red LED, and one RGB LED. I like the Launchpad style of not hogging up pins with peripherals that I don't need. The LED signals can be electrically disconnected from the processor using jumpers. The LED signals aren't available on any of the headers so it's questionable why someone would want to disconnect them. There are also a 32KHz crystal and a MHz crystal.

Thursday, May 21, 2015

BLE application development : Custom Hardware

This is the third post of a series on how to develop an application with Bluetooth Low Energy (BLE). If you haven't already, go back to the first post in the series for information on how to get started. I'm working on a light bulb where the intensity and color temperature can be set via BLE. The application does a ton of stuff, and I'm grafting BLE support into the rest of the application. For projects like this, the Anaren module approach is great.

A Hardware Abstraction Layer is a programming pattern whereby you encapsulate all the functions that talk to the bare hardware into one file. This makes it easier to port the application to different hardware platforms.

To complete this step, you'll need:
a) have completed the previous two steps
b) finished most of your schema with FirstApp, and made stubs for the callbacks
c) the schematic
d) hopefully a reference design close to your application. I'm using Tiva.

Because this is my first project using the Anaren BLE module, I routed all my module connections to the same signals as those used on the Anaren example that uses the TI TM4C123GXL LaunchPad and BoosterPack. This makes porting a little easier.

I recommend getting your schema and callback functions written while in the Em-Builder environment. Changing the schema after you move stuff over is a pain.

I like to start with the Hardware Abstraction Layer because that's the lowest level, and once it is done the rest should be fairly straightforward. Start by creating a new directory called Hal. In it create two blank files, Hal.h and Hal.c. First, copy and paste over the contents of the FirstApp Hal.h file. Save it and compile. Be sure that you don't have errors. My general approach is to go step by step, copying over stuff and compiling as we go. That way we can solve problems early instead of getting to the end and discovering a huge pile of problems to wade through.

Porting Hal.c

I have Hal.c open in Em-Builder, and an empty file in my IDE named Hal.c. I've already copied over Hal.h. Now, to port Hal.c we're going to go step by step: start from the top of the file, copying over a little, modifying it as appropriate, and compiling.


First, copy over all the includes. The original Hal.c had two files:
#include "lm4f120h5qr_pin_map.h"
#include "inc/lm4f120h5qr.h"
... that can be replaced with the simpler driverlib one:
#include "driverlib/pin_map.h"
Now it should work better.


There are a couple of #defines that are rather perplexing. To clarify:
EAP_RX_ACK_PIN - this is an input to the module, and an output from the MCU
EAP_TX_ACK_PIN - this is an output from the module, and an input to the MCU
Next you'll see the LED stuff. I ported over the LED_PIN and CONNECTED_LED stuff but I commented out the BLUE_LED stuff. I also left out the BUTTON_PIN and DEBUG1_PIN and DEBUG2_PIN stuff. One thing that isn't self-explanatory: the #define MSEC_CYCLES is the number of cycles in a MSEC, so if your clock frequency is 50MHz, this would be equal to 50000.


I did not port over the debug functions Hal_debugOn, Hal_debugOff, Hal_debugPulse.

The Hal_Init() function is a big chunk of code, and should be done very carefully. Since I already have a hal_init function for the rest of the application, I renamed this BLE_Hal_init() so that it's clearer. I commented out a lot of the initialization stuff, but be sure to leave in the code that initializes the EAP TX & RX pins:
   /* These are the module's special flow-control functions */


Also include the UART1 initialization, or whatever UART initialization you need. Be sure that it's configured properly.

The last line of their Hal_init function won't allow us to compile. Temporarily comment it out; we'll come back to that later.
//FIXME: update this once the rest is working
//handlerTab[DISPATCH_HANDLER_ID] = Em_Message_dispatch;
The FIXME tag will get automatically added to our list of tasks. This can be seen by adding the Tasks view. To do so navigate to: View : Other : General : Tasks and it should appear next to your problems tab.

With that you should be able to compile the entire Hal.c file.

Event Handling

We're handling event handling a little differently. The Hal.c file has a function:
void Hal_idleLoop(void)
But we're doing it differently, so temporarily we skip over this.

LED Functions

Port the Hal_ledOn, off, read, toggle functions next. If you set up your #defines then you should just be able to copy/paste these functions.

Timer Function

The next function is a little funky:
void Hal_tickStart(uint16_t msecs, void (*handler)(void))
The two parameters are:
  • msecs - the number of milliseconds before the timer expires
  • handler - the function that will be called when the timer expires.
This works in conjunction with Hal_timerIsr(void) which is called by the timer when it expires. The first line in the function:
handlerTab[TICK_HANDLER_ID] = handler;
adds an entry to the event handler table that should be called when the timer expiry event is processed. For now I'm commenting it out so that I can complete the port of the rest of the file.

SRT-HAL Interface

I think the "SRT" refers to the module. I had to do a little bit of googling to find that it means "Schema Runtime" which is as self-explanatory as "SRT". Or not. At any rate, these functions are the ones that handle the serial communication. Here you can see the funky communications protocol that the module uses. When I copied these functions over, the compiler didn't like that the Em_Hal_reset function used Em_Hal_unlock before it was declared, so I moved Em_Hal_unlock above the Em_Hal_reset function. Then Em_Hal_startSend didn't like how Em_Message_startTx was used because I haven't yet included the other Emmoco files.

Interrupt Service Routines

The ISRs are short and to the point which is nice. I did not copy over the Hal_buttonIsr function since I have my own. The rest of these functions form the real meat and potatoes of the module interface. This includes the serial receive ISR as well as the ISR for the handshake from the module, Hal_txAckIsr. When I added these, it became clear that I needed to import the Emmoco files now.

Adding the Emmoco Files

Now that we have a compiling Hal file, lets import the Emmoco files. I simply copied over the Em directory from my FirstApp to my project directory. The first thing that I did was add in the line at the top of my Hal.c file:
#include "Em_Message.h"
and tried to compile. Unfortunately it didn't work; the error
cannot open source file "Em_Message.h"
was displayed. Temporarily I fixed this by changing that line to:
#include "../Em/Em_Message.h"
But this is a hack.

Fixing the Interrupt Service Routines

When I ported the ISRs, there were a number of errors; some from the event handling, and one from an old Stellaris function that was used:
This has been replaced with:

Should be able to compile now

Following the steps outlined above (and commenting out the few pieces of code) you should be able to compile now.

Copy over the Application Logic

Now, in your main.c file (or whatever file holds your application), add the folowing line:
#include "Em/FirstApp.h"
And compile again. You shouldn't have any errors.

Over in Em-Browser, open your FirstApp-Prog.c file. We will be copying over some variables and functions from here. First, copy over the variables that are used:
static FirstApp_psuTemperatureC_t psuTempC = 10;
static FirstApp_pcbTemperatureC_t pcbTempC = 10;
static FirstApp_level_t intensity = 10;
static FirstApp_colorTemperature_t colorTemperature = 5600;
static FirstApp_command_t powerState = FirstApp_TURN_OFF;

Also, be sure to copy over the connectHandler and disconnectHandler functions; it turns out that the schema requires them.

Fix the Issues from Before

 Previously we commented out some code. Now, go back in and uncomment each part, and be sure it compiles. Add the start() method - the last three lines of your main application should be something like below:
/* The Hal_init() function for BLE stuff */
/* Initialize the BLE module */

/* The event handler that never exits */

Add Interrupt Vectors

The Tiva line of microcontrollers uses a very cool interrupt vector table to tell the processor which function to call for a given interrupt. Open the startup code file that you're using (mine is startup_ccs.c) and add the following interrupt functions, replacing IntDefaultHandler with the name of the function.
    Hal_txAckIsr,                           // GPIO Port A
    Hal_rxIsr,                              // UART1 Rx and Tx
    Hal_timerIsr,                           // Timer 0 subtimer A


After I was able to compile the code it didn't work. So, to troubleshooting we go. First, double check your schematic connections, as far as what is an input and what is an output. Next hook up a logic analyzer and observe, and compare to the reference traces:
When I started, I wasn't seeing the RX_ACK pulses after each byte received from the module. Doing a bit of troubleshooting, I found that the uart receive interrupt was not properly configured.

Wednesday, March 4, 2015

Fiducials in Altium

In Printed Circuit Board design, Fiducial marks are used to align the pick and place machine with the PCB. A fiducial requires a circular area free of silkscreen and solderpaste, and in the middle of that area is a smaller circle exposing the top metal of the PCB.

Creating these in Altium with keepouts can be problematic because it will create a keepout on both layers when typically you only want the keepout on the same layer as the fiducial.

I recently saw a great solution for this: do it with a clearance rule. Create a Clearance design rule named "FiducialClearance" (or whatever you want to name it) that specifies the 26mil clearance needed and is limited to just your fiducials. Create a new rule with the following:
Obviously, replace 'Fiducial-40mil' with the name of your fiducial footprint.

Finally change the priority of the "FiducialClearance" rule so that Priority=1.