Sunday, September 05, 2010
   
TEXT_SIZE

STM32 Controller: SPI (Serial Peripheral Interface)

The primary pin out on the STM32small board for its SPI bus (SPI_2), is for use with the MicroSD card.  However, to ensure the board isn't limited to this function and has alternative capabilties with this peripheral should the MicroSD card not be required in an application, it has also been pinned out to the generic Port B header set.

Alternative Use Example

One alternative to using the SPI for accessing the MicroSD, is to use it to drive a shift register - thus allowing either an easy way to drive additional LED's, or to expand the amount of I/O lines the board can play with.

As such an example, here you can see the board during design verification stages of this peripheral, driving an ST STP16CP05 constant current LED driver, which is basically a shift register device that is capable of driving LED's at a fixed constant current up to 100mA.

STM32 Driving a Shift Register

You can see the boards 3.3V Power LED (Green), its heart beat LED (Bright Orange), at the far right back the dim small orange LED is actually the boarts UART TX line transmitting some data.   Finally in the foreground of the picture you can see a singe red bar LED being lit via the STP16CP05 chip next to it.   A little hard to make out, but on the far side of the STP16CP05 chip, the green wire is MOSI, blue is CLK and yellow is Chip Select (NSS) - which in a shift registers case is basically the Latch Pin.

Now for a very important warning about the STM32 (SPI, NSS pin)

The datasheet is truely misleading with respect to the NSS (chip select) pin on its SPI peripherals, it sells itself as providing "hardware control" of the NSS pin.   Typically on any chip I've ever known, hardware control of the NSS line means that you push data into the shift-out register of the SPI peripheral - and the hardware of the module handles the NSS line by pulling it low when transmition starts and pulling it high again when transmission has ended.

On the STM32 this is NOT the case.

"Hardware Control" simply means that the hardware will pull the line low for you when you first start to use the peripheral - it will not go high again ever (unless you do something in s/w to make it do so).

For some SPI applications this is no big deal, but for a shift register, this is a real problem because the latch pin needs to see the latch pin low when clocking data into it and transiton to high when you want the outputs to change.....thus is the NSS pin never goes high, the shift register never latches its data (so you get no output!).

This is truely rubbish and users of this chip be warned......because it means to drive NSS manually you'll either have to have an interrupt firing when the TX buffer is empty, or poll the TX BUFFER empty state or wait until all data has gone out in the send function.   All of which will burn valuable software clock cycles.

The code used to prototype the peripheral

This is the quick bit of code we used to take charge of the NSS pin, it's not ideal (note the comment), but it will work and for some applications may do the trick - for others the only way you might be able to get the throughput is to handle the NSS via interrupt.   ST might not see their NSS handling as a bug.....but it is, this pin should be properly hardware controlled (or it should be in the Errata as not being so people at least know clearly what they're getting)

void sendSPIbyte(unsigned int dataOut)
{
GPIO_ResetBits(SPI_MASTER_GPIO, SPI_MASTER_PIN_NSS);

SPI_I2S_SendData(SPI2, dataOut);

/* This is a truly horrid way of doing this as              */
/* as we're now stalling the task until transmit has */
/* completed                                                                    */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
{}

GPIO_SetBits(SPI_MASTER_GPIO, SPI_MASTER_PIN_NSS);

return;
}

Initialisation of the SPI module is equally pretty straight foward.

Enabling the appropriate clocks and I/O lines it's simply a matter of setting up the structure and calling ST's standard library function.

 

/* SPI_MASTER configuration ------------------------------------------------------*/
SPI_InitStructure.SPI_Direction              = SPI_Direction_1Line_Tx;
SPI_InitStructure.SPI_Mode                   = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize               = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL                   = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA                   = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS                     = SPI_NSS_Soft;    /* NSS Software Controlled */
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit                 = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial       = 7;
SPI_Init(SPI_MASTER, &SPI_InitStructure);

/* Take NSS line high by default */
GPIO_SetBits(SPI_MASTER_GPIO, SPI_MASTER_PIN_NSS);

/* Enable SPI_MASTER */
SPI_Cmd(SPI_MASTER, ENABLE);

 

Note:  in the above we put NSS under software control, this is because we need to be able to control the line to go high and low - as noted earlier, in hardware controlled "mode" it simply goes low and that's it.

 

Here's what we get on the logic analyzer when we drive the system this way and send the data "0x0FFF" on to the SPI bus.

 

SM32 - SPI Shift Register Data out

 

The positives to this SPI peripheral

As I sort of hope comes across from the code above, getting it actually up and running is very easy allowing for the fact the bulk of the work is simply handed off to ST's Peripheral Library code (but I'm ok with this because they give you the source code - so if you have time/need for it to be faster or better, you can tweak it later).

Other then that there's not a whole lot more to say about it - the NSS issue is a very tedious problem which ST really should sort out and give it proper hardware control (or make it clearer in their datasheets - the timing diagrams clearly show NSS going high and the concept of "hardware control" is very misleading at best, it is nothing like how typical chips handle "hardware control" of the NSS line).

 

All that aside the peripheral is working and its another part of the design that needs no extra work on the Mk2 design which is good news.