Problems with STM32 SPI and Chip Select - Page 1
Forum section: electronics / beginners

author: JPortici
author_rank: Super Contributor
timestamp: May 14, 2016, 08:36:43 pm
content: Jesus, another attempt at doing something with ARM MCUs. Your usual STM32F103RBT6Trying to configure the SPI module with the procedure according to the datasheet, the module doesn't work. Enabling the module actually changes a couple of bits in the configuration wordUsing the HAL, it gets configured as expected. will have to investigate the code.So, configured the moduleCode:SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);/* Enable SPI1 */SPI_Cmd(SPI1, ENABLE);then there is the main codeCode:while(1) {for(i=0;i<5000000;i++); //Some DelayGPIOA->BSRR = 0x00100000; //PA4 DownSPI1->DR = j; //SPI_I2S_SendData(SPI1,j);while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); //Check if transmit buffer is empty = trasmit complete?GPIOA->BSRR = 0x00000010; //PA4 Highj++;}And this is the result.Channel 1 is PA4 / Chip Select LineChannel 2 and 3 are Mosi and SCKAccording to the datasheet, page 720Quoteso, to know when transmission is finished one has to keep polling the TXE bit and wait for it to go high, right?But of course the result is the one in the photo.-Changing the prescaler value do not change the lenght of the cs pulse-using the bloated hal crap instead of writing directly to the register just delays the startI think i must be missing something obviousBefore you ask, GPIOs are configured correctly. GPIOA and SPI clocks are enabled.

author: janoc
author_rank: Super Contributor
timestamp: May 14, 2016, 09:14:34 pm
content: Quote from: JPortici on May 14, 2016, 08:36:43 pmUm careful. STM32s use a sort of "double buffering" on many peripherals. TXE being high only means you can feed another word to be transmitted, not that the transmission is finished! Data could be still in flight at that moment. The idea is that TXE going high triggers an interrupt/DMA so that the next data for transmission are loaded in the registers in time, maintaining high throughput.If you want to be sure the bytes have actually left the MCU, you need to watch for the BSY flag too. Normally you send each byte/word out when TXE goes high and after the last one wait for BSY to go low.Thenyou can pull the CS line high safely.The procedure how to ensure that you don't mess up the last byte is actually described on page 691, section 25.3.8, "Disabling the SPI".

author: JPortici
author_rank: Super Contributor
timestamp: May 14, 2016, 09:25:42 pm
content: Of course it was something obvious!

author: rstofer
author_rank: Super Contributor
timestamp: May 14, 2016, 09:45:45 pm
content: Right, it's pretty clear that CS' is coming high far too soon.I realize my code is for an LPC2148 but it certainly isn't wrapped around some "helper" library:Code:#include "LPC21xx.h"#include "spi.h"/** P0.4 => SCKconnect to AD7327 SCLK - Pin 20* P0.5 => MISOconnect to AD7327 DOUT - Pin 18* P0.6 => MOSIconnect to AD7327 DIN - Pin 2* P0.7 => SSELconnect to AD7327 CS' - Pin 1*/#define SSEL(1 << 7)#define SPI_SPIE(0x00000080)#define SPI_LSBF(0x00000040)#define SPI_MSTR(0x00000020)#define SPI_CPOL(0x00000010)#define SPI_CPHA(0x00000008)#define SPI_BitEnable (0x00000004)#define SPI_Bits(0x00000000)#define SPI_SPIF(0x00000080)#define SPI_DIVIDER(8)/** Set up SPI0 as a master with CPOL = 1, CPHA = 0 and 16 bit transfers.* Force P0.7 to GPIO, set it for output and set it high*/void SPI0_init(void){PINSEL0 |= 0x00001500;PINSEL0 &= ~0x0000C000;IO0SET = SSEL;IO0DIR |= SSEL;S0SPCR = SPI_MSTR | SPI_CPOL | SPI_BitEnable | SPI_Bits;S0SPCCR = SPI_DIVIDER;}/** Send value to ADC and return value shifted in.*/unsigned short SPI0_Send(const unsigned short value){IO0CLR = SSEL;S0SPDR = value;while (!(S0SPSR & SPI_SPIF));IO0SET = SSEL;return (S0SPDR);}I have played with the STM processors and I really HATE their library. It bloats the code and obscures what is going on. Just my opinion...

author: AwArD_RzD
author_rank: Regular Contributor
timestamp: May 14, 2016, 10:38:42 pm
content: Quote from: rstofer on May 14, 2016, 09:45:45 pmI'm a beginner with ARM and i choose the stm32 for the low price of the discovery board. I had many successful and fun project with pic 8 and 16 bit and i never used any made up library with that. When i started with STM32 1 year ago i had to choose the STD peripheral library or the HAL (cube) from ST. Since ST dropped the support for the std library and the HAL seem the way to go for them. After some time on and off reading the pdf (well 3 pdf to link, what they do, what happening and where this is happening), i concluded after a failed SPI code test that i will never use anything except direct register control. Like you said the code obscures what's happening and when thing don't work you never know if it's your code at fault or the library. I don't remember who said that on the forum but it's like they need 5 million line of code to flash a led. I don't trust that and since i'm a control freak (i love to play with FPGA) i need to know what's happening every clock cycle everywhere and where the 0 and 1 go.The best way is to read the manual do your code (the less other library you use, less thing can go wrong) and check how your code work in debug mode. After that if you need portability you can always compare how thing happen and choose your battle.

author: rstofer
author_rank: Super Contributor
timestamp: May 15, 2016, 01:26:22 am
content: In my opinion, one of the better ARM boards is the 'mbed'.https://developer.mbed.org/Here's why I like the board: First of all, I don't have to install a toolchain. Everything can be done over the Internet from code writing to image creation. The final image is downloaded to the board as though it were a mass storage device as that's the way it connects to the PC (USB). Then hit reset and your code is executed.Second, it has a decent number of peripherals and it also has several libraries for higher level stuff, like Ethernet. It is truly simple to hang a MagJack adjacent to the board and everything you need for sockets programming is provided.It's not a real fireball but it's pretty fast at 96 MHz.It took a lot of ideas from Arduino in terms of ease of use. It's pretty easy to get started with the board and have something working in a short period of time.Now that ARM owns the site and product line, I don't know what to think. I imagine that is a good move from the point of view of users. Certainly they have money and stability.

author: JPortici
author_rank: Super Contributor
timestamp: May 15, 2016, 11:04:53 am
content: Seems to me it took all the bullshit from arduino. No thanks, i'll stick with C and assembly. That level of abtraction is unnecessary for these chipsMy problem was not fully understanding the datasheet, which i still find confusing (ST ones)

author: JPortici
author_rank: Super Contributor
timestamp: May 15, 2016, 11:14:12 am
content: One just need understandable documentation (of course the degree of understandibility varies with the user

author: janoc
author_rank: Super Contributor
timestamp: May 15, 2016, 01:05:06 pm
content: Quote from: rstofer on May 15, 2016, 01:26:22 amSTM32 boards are also supported by mBed. mBed is more a software standard now than any particular board series.Quote from: rstofer on May 15, 2016, 01:26:22 amAFAIK, ARM only runs the website. Not the product line.What I don't like about mBed is fairly poor hw support on many boards - one board has USB supported, another doesn't (HW being there, of course) because they didn't provide the drivers, despite the board being officially supported. One board works with ethernet, another one doesn't for the same reason. The generated code tends to be enormous, making simple things to not fit in flash on some of the smaller boards. Lot of built-in peripherals are not handled at all - such as timers. Lot of more advanced features are not supported, so you have to go down to registers anyway. What is the point of such library? Arduino libraries are a lot more polished from this point of view.And the "not having to install toolchain" part is just nonsense. It is not unzipping an Arduino zip file into a folder but it isn't rocket science neither. Web compiler is cool for a quick hack if you have a supported board, but the whole point of having an offline toolchain is that you are not dependent on whether or not their site works and whether or not they have decided to update things and now you code doesn't work anymore. Also good luck trying to debug if you don't have a local debugger installed.Of course, if you are coming from an Arduino, you will not even realize that you don't have many of these things, because Arduino didn't support them neither.

author: janoc
author_rank: Super Contributor
timestamp: May 15, 2016, 01:09:18 pm
content: Quote from: JPortici on May 15, 2016, 11:04:53 amYeah, the STM32 datasheets are not stellar. The info is there, but sometimes it takes a long time to figure out how it fits together, especially for some of the more complex peripherals. STM32 has insanely powerful peripherals but making sense out of all the configuration and status bits is nontrivial.Also STM32F10x series has some hw bugs and issues (I2C issues are notorious), so make sure to check the erratas too.

author: janoc
author_rank: Super Contributor
timestamp: May 15, 2016, 01:24:01 pm
content: Quote from: rstofer on May 14, 2016, 09:45:45 pmThe problem with the STM32 processors is that their peripherals take a fair bit more to initialize than what you have shown in your code for the NXP MCU. It is sanely designed, so most of the things can be kept at default values for the most common use cases, but still. That's why people use the libraries instead as it is less likely to forget to set something.On the other hand, I have to agree that the quality of those libs leaves a lot be desired and I often end up with programming the registers directly - the datasheet is most often correct and things will work if you follow it, whereas with the library (both STDPeriph and HAL) it is often crapshoot ...

author: JPortici
author_rank: Super Contributor
timestamp: May 15, 2016, 01:24:59 pm
content: Yes. At the day job i develop products with extensive use of pics and dspics.. i have grown fondnin reading the errata long before i have to chose the chipthough i tend to discover new bugs every week or so.Anyway, dspics have much more powerful peripherals than this series of cortex mcus (with a couple of exceptions of course) and the only reason i am using one this time is to learn, to get familliar, to set up a working programming environment and not to lose days in solving trivial problems, such as this one..But it gets so frustrating

author: rstofer
author_rank: Super Contributor
timestamp: May 15, 2016, 02:43:45 pm
content: Quote from: JPortici on May 15, 2016, 11:04:53 amYou still have every opportunity to do just that. My first 'real' project required interrupt driven SPI input at a fairly high rate. Ordinarily, like with the Arduino, you wouldn't mess around with interrupts. It took a few minutes to work it out but, in the end, I used one of the 'hidden' 16k memory blocks as an input fifo and the other as an output fifo. The output was packets over a TCP connection to a LaserJet. I absolutely did not want to have to code the TCP/IP stack. The mbed version is based on lwIP and that is fairly well documented.The part I like about mbed is the additional processor that makes the board look like a mass storage device. That's a really nice way to load code to flash.

author: rstofer
author_rank: Super Contributor
timestamp: May 15, 2016, 03:18:27 pm
content: Quote from: janoc on May 15, 2016, 01:05:06 pmThis has become true over time. In the beginning, there was one board and it was based on the LPC1768. This is the only board I have used. I haven't followed along because there is no need. For me...QuoteI don't know anything about the ARM arrangement. Nothing much has changed except the location of the web sites. I don't know why the code would be overly large, they're using the same GCC compiler and C libraries as everyone one else. In fact, I have downloaded my code (and their libraries) and dropped it into Rowley Crossworks with no changes. The project was a bit too important (to me) to have it dangling out on the web.Users of non-PC platforms may very well like the ability to develop code wherever they happen to be with whatever device they might happen to have with them. Maybe hanging out at Starbucks with a tablet. Perhaps one of those "Eureka" moments! In any case, it is better than building GNUARM from source or trying to get Eclipse set up with GCC.Since we're primarily talking about newbies, not having to install (or worse, build) a toolchain is a very big deal. Just create an account, plug in the USB cable and you're ready to go. It's a pretty big deal!And, yes, on Linux I use Eclipse and GNUARM, on Windows I use Crossworks. Neither of these look anything like the Arduino IDE. I don't know that I have ever done anything with the Arduino. I have a couple of boards and I tried a few experiments just to see but nothing too serious.I played with the STM32F and got buried in their abstraction. I had a ton of experience with bare iron ARMs (mostly LPC2106 and LPC2148) and all of a sudden I was going to have to find and actually read about the library just to try a simple experiment. Not my idea of a good time so back in the drawer it went. Maybe one day when I have more patience.The mbed targets the market very near the Arduino. It isn't necessarily the best board for experienced users but it isn't as light as a Basic Stamp, either. It certainly would never be used in a commercial project but it might be used to do proof-of-concept. Just hang a little custom PCB on the underside and you're good to go. That's how I mounted the magjack. I just built a PCB with a couple of headers to mount the mbed the magjack and with a handful of traces I was running TCP/IP. Pretty easy!For my little mbed project, I wasn't out to solve world hunger. I had one thing in mind: Packetize and transmit over TCP/IP data received over a high speed SPI link. Pretty simple...

author: rstofer
author_rank: Super Contributor
timestamp: May 15, 2016, 03:44:42 pm
content: Regarding mbed code size, attached is a screenshot of the web interface. Over on the right, it lists the total FLASH and RAM for my TCP/IP project. Considering that the project includes a complete TCP/IP stack as well as logic to grab the SPI stream, packetize it and stuff it out through the TCP connection, I don't consider 70 kB to be excessive. Could it be pared down? Certainly! But I would have to hack up a bunch of the library to do it. My objective is to NOT write code.The observant will notice that I have used 45.1 kB of RAM where only 32 kB exists. Quite the feat! It turns out that I am using the two 16 kB 'hidden' blocks of RAM as buffers. The chip actually has 64 kB of RAM.I don't think I can get at the linker output to find out what code is using how much space. If I was in any danger of running out of space, that might be a consideration.

author: rstofer
author_rank: Super Contributor
timestamp: May 15, 2016, 04:44:30 pm
content: Also apparent in the screenshot above is the difference between the mbed IDE and, say, the Arduino IDE.It is a very responsive IDE, much like having a native version. Given a fast enough network connection and a decent PC (or <whatever>), the mbed IDE is totally adequate.I'm not an evangelist for mbed. I like the platform but my primary interest is in FPGAs. The world has moved on from the LPC2148 so one of these days I'll have to do a little catch-up.

author: janoc
author_rank: Super Contributor
timestamp: May 17, 2016, 05:16:46 pm
content: By all means, if you like mBed and use one of the few boards that are well supported, use it.I have tried to use it with STM32 Nucleo boards and they were not supported at all for several months at first, despite shipping with the "mBed supported!" logo and once they got supported, many peripherals are not. Like USB on STM32F042 or F103 (not sure which one anymore).Re code size - I have tried to do a very simple thing, initialization of I2C and getting data from a peripheral. The code ended up more than 2x in size and not fitting into my target MCU when compiled using mBed and their libs than when I have used something like libopencm3. Heck, even the version using ChibiOS was smaller - and that included an entire RTOS! The problem is their dependence on the uber-bloated HAL libraries from ST for the STM32 code, so even if everything else is equal, their generated code is always going to be larger.When I have mentioned Arduino, I did not mean the IDE. The Arduino "IDE" is so basic that almost anything is better than that. What I meant was lack of basic things like debugger support, semihosting, access to map files to see what is taking the most space, etc. Someone coming from an Arduino will not miss those things, because they have never had them and probably are not even aware that such thing does exist. However, for a more experienced developer those things are usually indispensable time savers.Heck, even the programming by dragging and dropping the built file - that is a cool feature for a newbie not having a debugger/programmer (even though all STM32 boards come with STLink built-in and JTAG/SWD dongles cost few bucks on eBay ..), but over time it gets really annoying when you have to rebuild the code many times while debugging.If I have a normal programmer connected to anofflineIDE, I just push a button and the code is flashed and ready to debug. With mBed it requires at the very least downloading and saving the file, opening an Explorer window, dragging the file there, praying that it actually flashes (the STM Nucleo boards tend to flash once and then you need to unplug and replug them before it works again otherwise it silently fails. Yay!) and only then you can start testing the code. It is not much, but all the extra steps waste time and it accumulates ...Now, I know that one can export the mBed project and take it to an offline IDE, but I have never really managed to get that to work all that well. Moreover, the mBed libs are not open source, I believe, so you get only a binary blob that may or may not work and then you are screwed.

author: Chris Mr
author_rank: Regular Contributor
timestamp: May 19, 2016, 03:53:12 pm
content: STM32 SPI needs to check the busy bit after the TXE bit goes high.There is a shift register in an SPI port which is shifted to send the data out. This shift register is loaded from a buffer register. When the Buffer register has been read TXE goes high to give you time to put another value in the buffer.When you get to the end of a transmission you don't want the TXE any more, instead you need to check the busy bit in the status register. When that goes low you can raise LE.In other words, the TXE must be high, then check that busy is low, then stop.Hope that helps!

author: janoc
author_rank: Super Contributor
timestamp: May 19, 2016, 09:56:48 pm
content: Explained in the reply #1 above already.

author: rstofer
author_rank: Super Contributor
timestamp: May 20, 2016, 01:22:00 am
content: Quote from: janoc on May 17, 2016, 05:16:46 pmAs I said earlier, I only have experience with the LPC1768 variant and I can certainly see how STM's HAL could really bloat the code. Even when I played with the STM, I avoided the HAL like the plague.This is not the case for the LPC1768 variant.QuoteBut the Arduino was targeted at folks in the humanities department, not over in engineering. Users at that level are one step up from the Basic STAMP and wouldn't understand a linker script if it was printed in BOLD. Nor should they need to. They're not solving world hunger, just dealing with animatronics or whatever.QuoteYou make it sound a lot worse than it is. Once Explorer is set up to drop the file, don't close it. A simple click and the file is ready to run. I tend to use printf() a lot more than JTAG. I spent all the time single-stepping that I ever want to spend when I worked on 8080s and 8085s. What a PITA!But I did learn that I wouldn't have to debug code if I didn't put bugs in it in the first place.QuoteThe libs for the 1768 variant are indeed open source with the usual copyright that says, basically, it's free, do what you want. I'm not certain which of the multitude of licenses it is copied from but from my point of view, it's moot. I don't write code for money.When the project is exported, the library source code comes right along. At the moment, I can't find where I built the project locally but I know I did it and I can look at the source tree and see all the library code.There is certainly nothing magic about the mbed. There are a lot of development boards with some kind of programming feature. Then too, many of the chips have serial port programming capability. No debug features but printf() still works. JTAG is probably the best scheme but there needs to be a pretty good wrapper around GDB. In many cases, the IDE provides the wrapper. That is certainly the case for Crossworks.When I was messing around with ARMs a few years back, I built everything on Linux from the command line. The GNU toolchain provided all of the output files and nothing was hidden. Today, some of the IDEs bury such important files as linker scripts and use their own ideas about memory allocation - not a good situation. I want to know how memory is laid out. Even the commercial packages try to isolate the programmer from the hardware. Pity!ETA: It is worth pointing out that using the GNU toolchain directly brings along a STEEP learning curve beyond just writing code. There is the linker script to create and the Makefile and the requirement to actually understand 'make'. All of this is hidden by the modern IDE and certainly by the web IDE for mbed as well as the Arduino. Getting started, from scratch, with bare iron and GCC takes a ton of effort.

author: Daniyal
author_rank: Contributor
timestamp: May 20, 2016, 06:21:38 am
content: @JPortici not sure if you have resolved the issue, I had similar problem when I used ST's library, my suggestion will be only use those library as template for your own driver (not that it is a great template but it works most of the time).if you look inside of the SPI_I2S_GetFlagStatus() function it will temporarily disable the SPI for whatever reason... just hard code it to check register will fix that problem.

author: JPortici
author_rank: Super Contributor
timestamp: May 20, 2016, 10:47:10 am
content: Of course i didjust after reply #1On the to-do list there is a pdf containing all the registers, bits and explanations in a compact form, a datasheet a-la rest of the world (i think i'll just be lazy and insert the additional pages from the reference manual inside the part's datasheet

author: Yansi
author_rank: Super Contributor
timestamp: May 20, 2016, 05:03:31 pm
content: MBED is a heap of garbage for dummies in the first place ... and am not trying to offesnd anyone. Just stating...

author: janoc
author_rank: Super Contributor
timestamp: May 20, 2016, 07:26:06 pm
content: Quote from: rstofer on May 20, 2016, 01:22:00 amThere is no "wrapper" around GDB needed. What you need is the debugger stub, which is often provided by OpenOCD, even for some of the commercial IDEs or STLink (STM32 specific). The IDE just starts it and hides it.Quote from: rstofer on May 20, 2016, 01:22:00 amWell, and which toolchain doesn't take the effort? You will see it the moment when something goes south with your code - e.g. the compiler miscompiles something or you need some more advanced feature - like putting certain code at a certain address (e.g. because a peripheral is unable to access the entire address space - had that on PIC). Good luck doing that if you didn't take time to learn the gory details.BTW, most of the commercial ARM IDEs are actually using GNU toolchain as a compiler, with one or two exceptions. Heck, your Crossworks is either GCC or LLVM/Clang based. The only thing you get with it is the pretty GUI - which is nothing else than a customized version of Eclipse ...Basically you are paying big money for convenience of not having to learn how to set up the toolset yourself, not for any really unique features not available elsewhere. There is nothing wrong with that, engineer's time is expensive, but let's be realistic about what the real benefits of these tools are.

author: Chris Mr
author_rank: Regular Contributor
timestamp: May 22, 2016, 02:54:59 pm
content: Quote from: janoc on May 19, 2016, 09:56:48 pmmust remember to get these glasses changed