cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 SPI Interface

Posted on March 17, 2009 at 16:50

STM32 SPI Interface

3 REPLIES 3
Posted on May 17, 2011 at 12:54

I have an intriguing problem with the STM32:

I have been enhancing the sample code provided with the STM32F10X-128K-EVAL board with the intention of using some of the modules within a new project. Part of the enhancement is to make the code more readable.

I am using gcc as my compiler and Eclipse as the IDE.

Initially I used #defines to access registers, as in the following example:

#define SPI2_BASE (u32*)0x40003800

#define PeriphArrayReg(Address, Index, Element) *(u32*)(Address##Index##_BASE + offsetof(t##Address, Element))

#define SPI_DR(x) PeriphArrayReg(SPI, x, DR)

In the demo board SPI2 is used to access the LCD display, so a sample of the code is as follows:

SPI_DR(2) = Start_Byte;

The machine code created is as follows, with the processor registers shown when stopped at the highlighted line:

0x08004656 : ldr r3, [pc, #16] (0x8004668 )

0x08004658 : str r0, [r3, #0]

r0 0x70

r1 0x0

r2 0x42218188

r3 0x4000380c

This code works fine and correctly writes to the display.

I then tried further enhancing the code to use pointers to structures:

#define SPI2_BASE (u32*)0x40003800

tSPI* pSPI[4] ={[2] = (tSPI*)SPI2_BASE };

#defineSPI_DR(x) pSPI[x]->DR

The same sample code produces the following machine code, with the processor registers again shown when stopped at the highlighted line:

0x08004662 : ldr r3, [pc, #20] (0x8004678 )

0x08004664 : ldr r3, [r3, #8]

0x08004666 : str r0, [r3, #12]

r0 0x70

r1 0x0

r2 0x0

r3 0x40003800

I believe this should perform exactly the same. Instead of the r3 register pointing directly to the SPI_DR register it points to the start of the SPI structure, but the code writes the contents of the r0 register to (SPI + 12).

However, this code fails to write to the LCD display! I am using the same technique to read from flash on SPI1 and that works OK. I have proved conclusively that this is the cause of the problem by including both #defineSPI_DR(x) variants and commenting out one or the other.

Can anyone explain the anomaly?

Regards

Alan Rouse

jj
Associate II
Posted on May 17, 2011 at 12:54

Enjoyed your well constructed effort - wonder if you have any further test results to report?

Lcd controllers are often strange beasts - as your code works properly (apparently) with SPI Flash I'm betting that you may have a ''set-up'' or timing issue with the Lcd. Have you ''relaxed'' both your SPI speed as well as inter-byte transfer rate?

Finally - keep in mind that STM32 does ''not'' generate an automatic/hardware NSS_CS. NSS_CS has much more evolved functionality in Slave Mode - has been disappointing as Master. (we've squawked here...)

andreas2
Associate II
Posted on May 17, 2011 at 12:54

Even though the second code is sub-optimal because of the unnecessary array indexing, it seems to me it should do exactly the same thing. I suspect as jj.sprague it might be some timing/setup issue or other difference you may have overlooked.

However if you really need an array of SPI interfaces, you should probably declare it const or static const to allow the compiler to access SPI2 directly. But I think it's more intuitive and readable to make it explicit, like SPI2->DR = x, rather than hiding the access in a macro. Besides, I hope you declared the tSPI struct, or all of its members, volatile?