_lwsem_post problem on 32Bit SPI slave ISR

cancel
Showing results for 
Search instead for 
Did you mean: 

_lwsem_post problem on 32Bit SPI slave ISR

Jump to solution
771 Views
cavebiker
Contributor V

HELP! :smileysad:

  • Running a K20dx256 using CW10.3 / MQX4.0
  • I have a 32 bit SPI slave generating an interrupt when the RX buffer is not empty (RFDF bit in SPI2_SR)
  • Everything works fine until I _lwsem_post in the SPI ISR then _lwsem_wait in a task. When I do this I get a 'ivINT_Hard_Fault'. No fun...
  • When I replace the ISR with a simple loop that reads the RFDF bit in SPI2_SR, the _lwsem_post & _lwsem_wait work fine. This makes me think it is the way I handle the SPI RFDF interrupt. But the interrupts work fine without the lw semaphore. ???
  • I built my own 32Bit SPI slave driver because MQX and PE don't support 32Bit slave interrupts. This works great without the lwSem stuff, but I need a semaphore.

If anyone has a clue or idea as to what my problem is, please fire away.

Thanks in advance.

Cheers,

Tom

0 Kudos
1 Solution
155 Views
cavebiker
Contributor V

lwevent_ works. So I'm over it, but I would still like to know what up with _lwsem_.

Cheers,

Tom

View solution in original post

0 Kudos
9 Replies
155 Views
joséantoniomart
Contributor III

Hi Tom,

I was suffering a similar problem when using semaphores, and also I have found that using lwevent fixed it (also some timeouts and breakpoints put in "correct places"). I don't have the full explanation (mainly to the cases when it worked), but as you can read  on last comments in Re: Posting semaphore from SPI IRQ crashes app it has to be taken into account that semaphores are used to synchronize tasks, while events can also be used to synchronize an ISR and a task.

Only as an idea: maybe were you in the same case as me, this is, a semaphore used to synchronize an ISR and a task and not several different tasks?

Regards,

José Antonio Martínez.

0 Kudos
155 Views
cavebiker
Contributor V
  • Putting a breakpoint just before the _lwsem_wait gets rid of the problem.
  • Putting a _time_delay(100) just before the _lwsem_wait gets rid of the problem.
  • Putting a _time_delay(20) just before the _lwsem_wait does Not gets rid of the problem.

Has anyone seen this type of weirdness?

Cheers!

0 Kudos
156 Views
cavebiker
Contributor V

lwevent_ works. So I'm over it, but I would still like to know what up with _lwsem_.

Cheers,

Tom

View solution in original post

0 Kudos
155 Views
lisa_tx
Contributor III

Hi Tom,

I have K60F120M tower demo board. I use SPI1 as slave. I have tried both 16-bit word and 32-bit word data. I have no problem to use lwsem to notify main task. My problem is after first four words, the received data repeat the fourth data word. SPI has 4 word FIFO. I suspect the problem I have is related to FIFO set/clear.

Lisa

0 Kudos
155 Views
cavebiker
Contributor V

Hey Lisa,

you may be correct about the FIFO clear. In my 32-bit SPI ISR I clear the FIFO counter after I read in the 32 bits. so I'm back looking at the 1st FIFO, which should be the next to fill up.

          SPI2_SR |= SPI_SR_RFDF_MASK | SPI_SR_RFOF_MASK ;  //Clear SPI2 slave interrupt

          SPI2_MCR  |= (1UL <<  SPI_MCR_CLR_RXF_SHIFT);             //Clear RXFIFO counter

So I get two interrupts to get 32 bits, filling up FIFO #1 & #2. Then I clear FIFO counter as above.

I hope this helps.

Cheers,

Tom

0 Kudos
155 Views
lisa_tx
Contributor III

Hi Tom,

Thank you for help!

I have compared SPIx_SR and SPIx_MCR configuration in my spi1_isr(), I didn't clear SPI_SR_RFOF bit before. After reading your post, I have added it to spi1_isr(). Nothing has changed. This is the data received:

spi1_data = 0x6423

spi1_data = 0x849f

spi1_data = 0x1351

spi1_data = 0x1351

spi1_data = 0x1351

...

Note that since the third word received, its content never change. That is the problem I have. In this example, I use 16-bit word.

Below is my current isr function:

void spi1_rec_isr(void)

{

     NVICICPR0 |= 1 <<27;

     SPI1_SR |= SPI_SR_RFDF_MASK | SPI_SR_RFOF_MASK;

     spi1_rx_data = SPI1_POPR;

     SPI1_RSER = 0;

     SPI1_MCR |= SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK | SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK;

     _lwsem_post(&spi1_isr1_lwsem);

}

Could you see the problem? Do you mind show your isr function?

Thanks again.

Lisa

0 Kudos
155 Views
cavebiker
Contributor V

Hey Lisa,

What are you setting SPI1_RSER to signaling the interrupt? this is what I do:

SPI2_RSER = (1UL << SPI_RSER_RFDF_RE_SHIFT);     // SPI2 interrupt when SPI2 RX FIFO is not empty

Maybe you are clearing too much with SPI1_MRC

Here is my isr stuff: Good luck :smileyhappy:

{                                                   // Build 32-bits.

   SpiMsW = (uint_16)(SPI2_POPR & 0xFFFF);    // get SPI data MS_word.

   SpiLsW = (uint_16)(SPI2_POPR & 0xFFFF);    // get SPI data LS_word.

                                 

   SPI2_MCR  |= (1UL <<  SPI_MCR_CLR_RXF_SHIFT); // clear RXFIFO counter

   SpiQlxWord = (((SpiMsW << 16) & 0xFFFF0000) | (SpiLsW & 0x00FFFF));

   CardSpiState.rawSpiInWord = SpiQlxWord;   // Save SPI word in private structure

   _time_get_ticks(&ticks);                  // Get OS ticks

   CardSpiState.timeIn = ticks.HW_TICKS;     // Save ticks time stamp with SPI data                      

   // post the lwevent to signal new SPI message is in      

   if (_lwevent_set(&lweventSPI,0x01) != MQX_OK)                  

         _task_block();    // TODO: set a error condition instead if this.

       

    SPI2_SR |= SPI_SR_RFDF_MASK | SPI_SR_RFOF_MASK ;  //Clear SPI2 slave interrupt

    SPI2_MCR  |= (1UL <<  SPI_MCR_CLR_RXF_SHIFT);     //Clear RXFIFO counter

}

Cheers,

Tom

0 Kudos
155 Views
lisa_tx
Contributor III

Hi Tom,

Thank you for sharing your code!

I have noticed that you clear SPI2_MCR bit RXF twice. May I ask why?

I haven't got mine working yet.

Bye for now.

Lisa

0 Kudos
155 Views
cavebiker
Contributor V

I have noticed that you clear SPI2_MCR bit RXF twice. May I ask why?

Ha ha, I saw that also when I was sending the code. I am sure it is not needed to be done twice.


Hope you get it working.

Cheers,

Tom

0 Kudos