Author Topic: libopencm3, stm32l100rc discovery and SPI issues  (Read 3335 times)

0 Members and 1 Guest are viewing this topic.

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
libopencm3, stm32l100rc discovery and SPI issues
« on: September 17, 2019, 08:23:51 am »

Hello,


I seem to have a peculiar issue with the SPI peripheral on stm32L100. For information, I am using a STM32l100RC discovery board. I am trying to interface a SPI Flash module, specifically the W25Q64.


I am working off from the beginning STM32, libopencm3 freertos book by warren gay. I am not using the example code per say, just trying to get my hands dirty by using parts of his code to test that the device actually works and I am able to read/write to it. I am just using the barebones spi flash routines he has provided in the repo here


https://github.com/ve3wwg/stm32f103c8t6


I am trying to read the JEDEC ID of the flash module. The flash module is supposed to return
the manufacturer ID, memory type and capacity in that order, specifically the bytes EF, 40, 17 hex. I did verify that the modules work by trying them out with a arduino uno.


I tried to read the ID using the stm32l100rc discovery board and found that I am not able to get to the section where the command for reading the JEDEC ID is sent on the bus.
The code just is stuck in the w25_wait section.
Here is the screenshot of the same
The code is just stuck in the wait routine.


Here is the relevant code


Code: [Select]

 #include "libopencm3/stm32/rcc.h"
 #include "libopencm3/stm32/gpio.h"
 #include "libopencm3/stm32/usart.h"
 #include "libopencm3/stm32/spi.h"
 #include "delay.h"


 #define W25_CMD_MANUF_DEVICE   0x90
 #define W25_CMD_JEDEC_ID   0x9F
 #define W25_CMD_WRITE_EN   0x06
 #define W25_CMD_WRITE_DI   0x04
 #define W25_CMD_READ_SR1   0x05
 #define W25_CMD_READ_SR2   0x35
 #define W25_CMD_CHIP_ERASE   0xC7
 #define W25_CMD_READ_DATA   0x03
 #define W25_CMD_FAST_READ   0x0B
 #define W25_CMD_WRITE_DATA   0x02
 #define W25_CMD_READ_UID   0x4B
 #define W25_CMD_PWR_ON      0xAB
 #define W25_CMD_PWR_OFF      0xB9
 #define W25_CMD_ERA_SECTOR   0x20
 #define W25_CMD_ERA_32K      0x52
 #define W25_CMD_ERA_64K      0xD8


 #define DUMMY         0x00


 #define W25_SR1_BUSY      0x01
 #define W25_SR1_WEL      0x02


static const char *cap[3] = {
   "W25X16",   // 14
   "W25X32",   // 15
   "W25X64"   // 16
};   


static uint8_t
w25_read_sr1(uint32_t spi) {
   uint8_t sr1;


   spi_enable(spi);
   spi_xfer(spi,W25_CMD_READ_SR1);
   sr1 = spi_xfer(spi,DUMMY);
   spi_disable(spi);
   return sr1;
}


static uint8_t
w25_read_sr2(uint32_t spi) {
   uint8_t sr1;


   spi_enable(spi);
   spi_xfer(spi,W25_CMD_READ_SR2);
   sr1 = spi_xfer(spi,DUMMY);
   spi_disable(spi);
   return sr1;
}


static void
w25_wait(uint32_t spi) {
   uint8_t res= w25_read_sr1(spi);


   while ( (res & W25_SR1_BUSY) )
   {
      delay_ms(50);
      res = w25_read_sr1(spi);
   }
}


static uint16_t
w25_manuf_device(uint32_t spi) {
   uint16_t info;


   w25_wait(spi);
   spi_enable(spi);
   spi_xfer(spi,W25_CMD_MANUF_DEVICE);   // Byte 1
   spi_xfer(spi,DUMMY);         // Dummy1 (2)
   spi_xfer(spi,DUMMY);         // Dummy2 (3)
   spi_xfer(spi,0x00);         // Byte 4
   info = spi_xfer(spi,DUMMY) << 8;   // Byte 5
   info |= spi_xfer(spi,DUMMY);      // Byte 6
   spi_disable(spi);
   return info;
}


static uint32_t
w25_JEDEC_ID(uint32_t spi) {
   uint32_t info;


   w25_wait(spi);
   spi_enable(spi);
   spi_xfer(spi,W25_CMD_JEDEC_ID);
   info = spi_xfer(spi,DUMMY);       // Manuf.
   info = (info << | spi_xfer(spi,DUMMY);// Memory Type
   info = (info << | spi_xfer(spi,DUMMY);// Capacity
   spi_disable(spi);


   return info;
}


static void
w25_read_uid(uint32_t spi,void *buf,uint16_t bytes) {
   uint8_t *udata = (uint8_t*)buf;


   if ( bytes > 8 )
      bytes = 8;
   else if ( bytes <= 0 )
      return;


   w25_wait(spi);
   spi_enable(spi);
   spi_xfer(spi,W25_CMD_READ_UID);
   for ( uint8_t ux=0; ux<4; ++ux )
      spi_xfer(spi,DUMMY);
   for ( uint8_t ux=0; ux<bytes; ++ux )
      udata[ux] = spi_xfer(spi,DUMMY);
   spi_disable(spi);
}




int main(void) {
//Always set the clock for the ports and peripherals first


//Select HSICLK with PLL as sysclock source
// Sysclock frequency is 16 Mhz


   rcc_clock_setup_hsi(&rcc_clock_config[RCC_CLOCK_VRANGE1_HSI_RAW_16MHZ]);


//Enable GPIOC Peripheral clock
   rcc_periph_clock_enable(RCC_GPIOC);
//Output mode, no pull ups or pull down
   gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8 | GPIO9);
//Set GPIO8 and clear GPIO9 to see toggle
   gpio_set(GPIOC, GPIO8);
   gpio_clear(GPIOC, GPIO9);


//Sequence of steps for SPI transactions
//Enable the clocks for the pin ports and peripheral for SPI
//Setup pins for the alternate functions
//PA4 = SPI1_NSS, PA5 = SPI1_SCK, PA6 = SPI1_MISO, PA7 = SPI1_MOSI
//reset the SPI peripheral
//initialize the SPI peripheral with the peripheral, clock, clock polarity,
//clock phase, data frame format, frame format
//set nss management to software otherwise SPI peripheral wont work
//enable the SPI peripheral
//send or read data using spi_send or spi_read functions


   rcc_periph_clock_enable(RCC_GPIOA);
   rcc_periph_clock_enable(RCC_SPI1);
   gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO4 | GPIO5 | GPIO7);
   gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6);
   gpio_set_af(GPIOA, GPIO_AF5, GPIO4 | GPIO5 | GPIO7);
   gpio_set_af(GPIOA, GPIO_AF5, GPIO6);
   spi_reset(SPI1);
   spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_64, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);


   spi_disable_software_slave_management(SPI1);
   spi_enable_ss_output(SPI1);
   while (1)
   {
      gpio_toggle(GPIOC, GPIO8 | GPIO9);
      uint8_t index = 0;
      spi_enable(SPI1);
      w25_wait(SPI1);
      spi_xfer(SPI1, 0x9F);
       uint8_t result1 = spi_xfer(SPI1, 0x00);
      uint8_t result2 = spi_xfer(SPI1, 0x00);
      uint8_t result3 = spi_xfer(SPI1, 0x00);
      spi_disable(SPI1);
      delay_ms(500);
   }


   return 0;
}





I apologize for the length of the code.
As I ve said earlier, the code is simply stuck in the w25_wait routine. it never progressess beyond.


I tried debugging further and it looks like that the condition
Code: [Select]
(res & W25_SR1_BUSY)
in the w25_wait function always returns true. This is because the previous function invocation of
Code: [Select]
uint8_t res= w25_read_sr1(spi);
in the line above always returns 1.
And this is the relevant snipper for the w25_read_sr1

Code: [Select]
w25_read_sr1(uint32_t spi) {
   uint8_t sr1;


   spi_enable(spi);
   spi_xfer(spi,W25_CMD_READ_SR1);
   sr1 = spi_xfer(spi,DUMMY);
   spi_disable(spi);
   return sr1;
}

But the logic analyzer capture shows that the data being returned is 0x00 not 0x01.


I would be extremely grateful if someone more knowledgeable can help me identify the issue.


I am more inclined to believe it is because I goofed up something in the initialization and/or the handling. But it is more or less a adapted version of the book's example code from the bluepill to the stm32l100rc.


Thank you in advance.!! :-)


Tl:DR : The spi wait function for the stm32 is returning 0x01 when it should be returning a 0x00 inspite of a logic analyzer capture showing that 0x00 is being read by the stm32.


PS: The 1st image in the attachments is the spi transaction from the arduino uno, the subsequent ones are from the stm32l100rc discovery board
« Last Edit: September 17, 2019, 08:27:06 am by krish2487 »
If god made us in his image,
and we are this stupid
then....
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #1 on: September 18, 2019, 07:45:32 am »
bump!!


Does any helpful samaritan have any experience with libopencm3 and can help me with this??


Thanks in advance!!!
If god made us in his image,
and we are this stupid
then....
 

Offline nugglix

  • Regular Contributor
  • *
  • Posts: 209
  • Country: de
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #2 on: September 18, 2019, 08:55:04 am »
Refer to the function referenced below and start to debug your code w/ this knowledge.
And, please, use the STM32 programming and reference manuals.

This function contains a lot of hints what *might* have gone wrong:
http://libopencm3.org/docs/latest/stm32l1/html/spi__common__all_8c_source.html#l00151
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #3 on: September 18, 2019, 09:06:37 am »
Thanks!! :-)
I ll have a look.
I can only try this after I get home today.


and yes, I do use the reference manuals. It is entirely possible, and mostly probable, I was debugging it wrong. I.e I diagnosed the issue wrong..
If god made us in his image,
and we are this stupid
then....
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #4 on: September 18, 2019, 08:20:16 pm »
Ok. I have had some time to see if the spi_clean_disable() can fix the issue.
Turns out modifying the w25_read_sr1() function to so
Code: [Select]
w25_read_sr1(uint32_t spi) {
    uint8_t sr1 = 0;

    spi_enable(spi);
    spi_xfer(spi,W25_CMD_READ_SR1);
    sr1 = spi_xfer(spi,DUMMY);
    // spi_disable(spi);
    spi_clean_disable(spi);
    return sr1;
}
or even to

Code: [Select]
w25_read_sr1(uint32_t spi) {
    uint8_t sr1 = 0;

    spi_enable(spi);
    // spi_xfer(spi,W25_CMD_READ_SR1);
    // sr1 = spi_xfer(spi,DUMMY);
    spi_send(spi, 0x05);
    sr1 = spi_read(spi);
    spi_send(spi, 0x00);
    sr1 = spi_read(spi);
    // spi_disable(spi);
    spi_clean_disable(spi);
    return sr1;
}
conducts the spi transaction only once.. and nothing after..So... Any further suggestions folks!!
I am at my wits ends here... I have been staring at the libopencm3 framework / datasheets / errata / reference manual for so long in the past few days nothing is making sense anymore... It could be a very obvious and simple problem.. but for the love of everything holy, I cant see it... :-(
If god made us in his image,
and we are this stupid
then....
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1668
  • Country: us
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #5 on: September 18, 2019, 10:26:51 pm »
At this point you should consider writing your own SPI code at the bare metal level. SPI is one of the easiest peripherals to do this with. All of the details are in the reference manual for the STM32 you're using. Give it a try--it's much more satisfying spending a few days writing your own code rather than spending the time debugging someone else's library code.
Complexity is the number-one enemy of high-quality code.
 

Offline TK

  • Super Contributor
  • ***
  • Posts: 1722
  • Country: us
  • I am a Systems Analyst who plays with Electronics
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #6 on: September 18, 2019, 10:55:34 pm »
You can also try with STM32CUBEMX and verify your setup is working.  It generates all the code for SPI for you, it even includes sample code to call from your main() function and test.
 

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #7 on: September 19, 2019, 04:07:18 am »
At this point you should consider writing your own SPI code at the bare metal level. SPI is one of the easiest peripherals to do this with. All of the details are in the reference manual for the STM32 you're using. Give it a try--it's much more satisfying spending a few days writing your own code rather than spending the time debugging someone else's library code.

Exactly and one earns real understanding from the exercise.

Even writing your own bit banging SPI code is easy and there are tons of examples on the web.
 
The following users thanked this post: nugglix

Offline nugglix

  • Regular Contributor
  • *
  • Posts: 209
  • Country: de
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #8 on: September 19, 2019, 07:07:09 am »
Or count the disable vs. enable calls in the whole mess.

Actually the code doesn't look like something coming from a decent programmer.
So I suggest the TO should improve his understanding of the basics.

The implementation of SPI only using the reference and programming manuals would help to understand how it works.
At the moment it looks like poking around in the dark.
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #9 on: September 19, 2019, 07:35:44 am »
@Sal ammoniac and @ techman-001
that is always an option. I am trying to learn libopencm3 and stm32. so I figured I might as well put in the effort to debug any mistakes I might make. I asked if anyone else might have some experience with the specific framework. If all else fails, that is what I suppose I ll do.. :-)


@TK
I toyed with that idea as well, I might give it a shot over the weekend just for a comparision to see if I can get a barebones SPI code functioning on the cubemx platform.


@nugglix
perfectly valid observations. The chip select toggle is exactly the number of disable vs enable calls. :-) .
If you look at the code, it is not trying to do anything except read the ID. It can be as messy and disorganised as possible. It can be the most barebones, ugly code for all I care if I can understand it and others can understand and help me debug it. refactoring it can happen later.
I m, as I ve said before, trying to interface with a SPI flash chip. Till I get my basics right.. it is going to be poking in the dark. Isnt it the case with all of us while learning.


PS: I still dont understand what is it that you are trying to hint towards. :-). From your posts I gather you do have some insights into how to debug and identify the issue. It seem like you hinting at the direction I need to take rather than outright state the answer. :-) . I must be exceptionally dumb to miss the hints.. If it not too much trouble. Can you explain what is it that you are expecting me to do..


@everyone
I know, the reference manual gives a clearer picture for me to write the driver from scratch. I am trying to get familiar with STM32 as a processor. I would not try and reinvent the wheel by writing the peripheral drivers from scratch. I would prefer to keep one variable fixed, like the framework, and work with the chip.

« Last Edit: September 19, 2019, 07:38:45 am by krish2487 »
If god made us in his image,
and we are this stupid
then....
 

Offline nugglix

  • Regular Contributor
  • *
  • Posts: 209
  • Country: de
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #10 on: September 19, 2019, 07:56:26 am »
@nugglix
perfectly valid observations. The chip select toggle is exactly the number of disable vs enable calls. :-) .
If you look at the code, it is not trying to do anything except read the ID. It can be as messy and disorganised as possible. It can be the most barebones, ugly code for all I care if I can understand it and others can understand and help me debug it. refactoring it can happen later.
I m, as I ve said before, trying to interface with a SPI flash chip. Till I get my basics right.. it is going to be poking in the dark. Isnt it the case with all of us while learning.


PS: I still dont understand what is it that you are trying to hint towards. :-). From your posts I gather you do have some insights into how to debug and identify the issue. It seem like you hinting at the direction I need to take rather than outright state the answer. :-) . I must be exceptionally dumb to miss the hints.. If it not too much trouble. Can you explain what is it that you are expecting me to do..

a) CS is not spi_enable/disable. I think I've seen unbalanced/misplaced spi_enable/disable calls. Check what SPI enable/disable does w/ the hardware. In the end, get rid of all these calls. Either use SPI or not. This enable/disable orgy doesn't help.

b) There is no excuse for horrible code. Especially when others have to wade through this code.

Try to reduce the code to show the problem.
This is the most important step in solving a problem: formulate it exactly!

Btw, this helps to avoid embarrassing questions.
You simply find most of the bugs while shrinking your code.    ;)


And mind one of my favorite quotes ever:
"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?"
 -- Brian Kernighan

 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #11 on: September 19, 2019, 08:13:55 am »


Thanks.. :-)
From your suggestions I am able to take away two pieces of advice .
1. Find out exactly what spi_enable / disable does and see if I can manually set the registers myself.
2. Reduce the "borrowed" code and try to reduce the number of lines to do the same job..


Good points. I will try that tonight!! :-) I admit, I cheated and tried to use the book's code without understanding thorooughly what they do.. I might as well now, take the effort to manually read the registers and see where I go to, even using the libopencm3 framework.'


Quote from: nugglix on Today at 07:56:26 am

>
If god made us in his image,
and we are this stupid
then....
 

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #12 on: September 19, 2019, 11:13:19 am »
@Sal ammoniac and @ techman-001
that is always an option. I am trying to learn libopencm3 and stm32. so I figured I might as well put in the effort to debug any mistakes I might make. I asked if anyone else might have some experience with the specific framework. If all else fails, that is what I suppose I ll do.. :-)

Apologies I know you are using CM3 with C, but I can't resist showing how easy it is (in Forth) to do a bit banged SPI. No libraries needed. The code below is from my old working project and shows the most important SPI parts, CLOCK and DATA.

The bit banged example will give a useful understanding of SPI when you try to configure the STM32 SPI peripheral which doesn't look trivial to me. Just a Cortex-m0 SPI-1 contains 9 registers with a total of 52 bitfields.

I wrote my first SPI example application, driving a Nokia 5110 LCD display and after I had finished I wondered why I'd ever bother to use the STM32F0 SPI peripheral (in this case) as it's so incredibly easy to bit bang.

Serialize the SPI DATA and create a CLOCK and you're 90% done. All that's left is Chip Enable, Reset and command/data signals for the individual SPI device.

 : clockdata            ( Creates clock and data bits from a data byte )
    if
      data-high
    else
      data-low
    then
      clk-high
      clk-low
  ;

  : >serialize            ( Serializes a byte, Most Significant Bit First )
    dup  128 and clockdata
    dup   64 and clockdata
    dup   32 and clockdata
    dup   16 and clockdata
    dup    8 and clockdata
    dup    4 and clockdata
    dup    2 and clockdata
           1 and clockdata
  ;

  : >CMD                  ( Adds preamble and postamble signals to a command byte  )
    CE->LOW                         
    DC->LOW                         
    >serialize
    CE->HIGH
  ;

 ">CMD" takes a data byte as the sole parameter and then generates the CE, DC and CE signals for the LCD. It then calls ">serialize".

">serialize" takes the same data byte as the sole parameter and deconstructs it in chunks which are handed to "clockdata" as they're computed.

"Clockdata" then constructs the DATA and ClOCK signals for the LCD SPI.
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #13 on: September 19, 2019, 11:24:03 am »


No apologies needed! :-)
I am glad and thankful that many fine folks are offering advice and suggestions. :-)
I am comfortable with C and it seemed natural to learn a framework within the same language. It was either cubemx or libopencm3.
Libopencm3 was more intuitive and easy to understand for a noob, like me. The example given does seem very very easy to implement in forth.
It would also mean I would need to learn forth. :-P


Of course, translating the same concepts to C and bitbanging seems equally easy. As ive said, I am just trying to learn the processor and its peripherals..
Of course, the final goal is to use the SPI peripheral and the flash chip, use a filesystem like littleFS or SPIFFS for storing some text data.
So I just started out.. one step at a time.. trying to read and control the flash memory.. and quite a journey it has been so far.. :-D


Quote from: techman-001 on Today at 11:13:19 am


>Quote from: krish2487 on Today at 07:35:44 am
@Sal ammoniac and @ techman-001
that is always an option. I am trying to learn libopencm3 and stm32. so I figured I might as well put in the effort to debug any mistakes I might make. I asked if anyone else might have some experience with the specific framework. If all else fails, that is what I suppose I ll do.. :-)



Apologies I know you are using CM3 with C, but I can't resist showing how easy it is (in Forth) to do a bit banged SPI. No libraries needed. The code below is from my old working project and shows the most important SPI parts, CLOCK and DATA.

The bit banged example will give a useful understanding of SPI when you try to configure the STM32 SPI peripheral which doesn't look trivial to me. Just a Cortex-m0 SPI-1 contains 9 registers with a total of 52 bitfields.

I wrote my first SPI example application, driving a Nokia 5110 LCD display and after I had finished I wondered why I'd ever bother to use the STM32F0 SPI peripheral (in this case) as it's so incredibly easy to bit bang.

Serialize the SPI DATA and create a CLOCK and you're 90% done. All that's left is Chip Enable, Reset and command/data signals for the individual SPI device.

 : clockdata            ( Creates clock and data bits from a data byte )
    if
      data-high
    else
      data-low
    then
      clk-high
      clk-low
  ;

  : >serialize            ( Serializes a byte, Most Significant Bit First )
    dup  128 and clockdata
    dup   64 and clockdata
    dup   32 and clockdata
    dup   16 and clockdata
    dup    8 and clockdata
    dup    4 and clockdata
    dup    2 and clockdata
           1 and clockdata
  ;

  : >CMD                  ( Adds preamble and postamble signals to a command byte  )
    CE->LOW                         
    DC->LOW                         
    >serialize
    CE->HIGH
  ;

 ">CMD" takes a data byte as the sole parameter and then generates the CE, DC and CE signals for the LCD. It then calls ">serialize".

">serialize" takes the same data byte as the sole parameter and deconstructs it in chunks which are handed to "clockdata" as they're computed.

"Clockdata" then constructs the DATA and ClOCK signals for the LCD SPI.


If god made us in his image,
and we are this stupid
then....
 

Offline techman-001

  • Frequent Contributor
  • **
  • !
  • Posts: 748
  • Country: au
  • Electronics technician for the last 50 years
    • Mecrisp Stellaris Unofficial UserDoc
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #14 on: September 19, 2019, 12:18:05 pm »
No apologies needed! :-)
I am glad and thankful that many fine folks are offering advice and suggestions. :-)
I am comfortable with C and it seemed natural to learn a framework within the same language. It was either cubemx or libopencm3.
Libopencm3 was more intuitive and easy to understand for a noob, like me. The example given does seem very very easy to implement in forth.
It would also mean I would need to learn forth. :-P

Opps, I should have mentioned I only gave the Forth example, as that's all I have. I've never written a SPI bitbanger in C or else I'd have given that code instead.

My intent was just to demonstrate the ease of SPI bit banging, not try and convert you to Forth.

Personally I like libopencm3 and Gcc for C on STM32.
 

Offline nugglix

  • Regular Contributor
  • *
  • Posts: 209
  • Country: de
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #15 on: September 20, 2019, 05:33:13 pm »
I hope the TO shares the findings of the debugging.

Would be a novel approach to this kind of threads -- actually see if the TO had success.   :box:
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #16 on: September 21, 2019, 07:40:36 am »
Well,
I apologize for the delay in posting back here. I ve had quite a busy day in trying to understand what I was doing wrong.
And it turns out, something absurdly simple.I have had the opportunity to read the book I mentioned earlier, and in the end, in the troubleshooting section, the author specifically mentions about gpio and alternate functions.It turns out I was configuring the SPI peripheral incompletely.I had forgotten to set the output mode options in the setup which threw the spanner in the works.
This is the code with the changes highlighted
Code: [Select]
rcc_periph_clock_enable(RCC_GPIOA);    rcc_periph_clock_enable(RCC_SPI1);
    gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO4 | GPIO5 | GPIO7);
    gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_40MHZ, GPIO4 | GPIO5 | GPIO7);
    gpio_set_af(GPIOA, GPIO_AF5, GPIO4 | GPIO5 | GPIO7);

    gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6);
    gpio_set_af(GPIOA, GPIO_AF5, GPIO6);

    spi_reset(SPI1);
    spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_128, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
And consequently, the test code works fine, I am able to read the JEDEC ID, manufacturer ID and the unique ID just fine.
I should have read the manuals more thoroughly and saved myself quite some hair pulling.:-)

Though, from what I read in the errata, it could have very well been  a silicon bug workaround that is coming into play here. from section 2.4.6 in the errata sheet
Code: [Select]
Corrupted last bit of data and/or CRC, received in Master mode withdelayed SCK feedback

Description
In receive transaction, in both I2S and SPI Master modes, the last bit of the transacted frame is not captured when the signal provided by internal feedback loop from the SCK pin exceeds a critical delay. The lastly transacted bit of the stored data then keeps the value from the pattern received previously. As a consequence, the last receive data bit may be wrong and/or the CRCERR flag can be unduly asserted in the SPI mode if any data under check sum and/or just the CRC pattern is wrongly captured.

 In SPI mode, data are synchronous with the APB clock. A delay of up to two APB clock periods can thus be tolerated for the internal feedback delay. The I2S mode is more sensitive than the SPI mode since the SCK clock is not synchronized with the APB clock. In this case, the margin of the internal feedback delay is lower than one APB clock period.

 The main factors contributing to the delay increase are low VDD level, high temperature, high SCK pin capacitive load and low SCK I/O output speed. The SPI communication speed has no impact.WorkaroundThe following workaround can be adopted, jointly or individually:•Decrease the APB clock speed.•Configure the IO pad of the SCK pin to be faster.
I have tried experimenting with the peripheral clock prescaler and the output speed and found that in some cases, it outright does not work, and in some combinations it just returns garbage data.Where the SPI clock tends to be higher-ish the data being returned is garbage.. as I ve mentioned in the original post... the transactions take place.. but garbage data is read..Anyway, thank you for the help folks!! :-) I hope this can help some one else later from making the same mistake.. You have been extremely helpful and patient with me and my dumbness.. :-P
« Last Edit: September 21, 2019, 07:45:08 am by krish2487 »
If god made us in his image,
and we are this stupid
then....
 
The following users thanked this post: thm_w

Offline nugglix

  • Regular Contributor
  • *
  • Posts: 209
  • Country: de
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #17 on: September 21, 2019, 07:49:16 am »
Congrats!

Nice to see that it worked out in the end.

So one to remember: always check device initialization.

Good luck for the remainder of the project!
 

Online krish2487Topic starter

  • Frequent Contributor
  • **
  • Posts: 500
  • Country: dk
Re: libopencm3, stm32l100rc discovery and SPI issues
« Reply #18 on: September 21, 2019, 07:52:50 am »
Thanks.. :-)

As i ve said, you guys have been extremely help and patient with me. I cannot stress this enough.
And yes, I shall double check my initialization code henceforth!!
Oops, formatting seems to be messed up in the earlier post.
This is the line that made the difference.
Code: [Select]
gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_40MHZ, GPIO4 | GPIO5 | GPIO7);
If god made us in his image,
and we are this stupid
then....
 
The following users thanked this post: nuclearcat


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf