Page 24 of 35

Re: I2C implementation for STM32

Posted: Mon Dec 05, 2011 1:20 pm
by barthess
Forgot something. Example of I2C configuration from my mcucong.h

Code: Select all

#define STM32_I2C_USE_I2C1                  FALSE
#define STM32_I2C_USE_I2C2                  TRUE
#define STM32_I2C_USE_I2C3                  FALSE
#define STM32_I2C_I2C1_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 0)
#define STM32_I2C_I2C1_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_I2C2_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2C_I2C2_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 7)
#define STM32_I2C_I2C3_RX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 2)
#define STM32_I2C_I2C3_TX_DMA_STREAM        STM32_DMA_STREAM_ID(1, 4)
#define STM32_I2C_I2C1_IRQ_PRIORITY         6
#define STM32_I2C_I2C2_IRQ_PRIORITY         6
#define STM32_I2C_I2C3_IRQ_PRIORITY         6
#define STM32_I2C_I2C1_DMA_PRIORITY         1
#define STM32_I2C_I2C2_DMA_PRIORITY         1
#define STM32_I2C_I2C3_DMA_PRIORITY         1
#define STM32_I2C_I2C1_DMA_ERROR_HOOK()     chSysHalt()
#define STM32_I2C_I2C2_DMA_ERROR_HOOK()     chSysHalt()
#define STM32_I2C_I2C3_DMA_ERROR_HOOK()     chSysHalt()

Re: I2C implementation for STM32

Posted: Mon Dec 05, 2011 6:33 pm
by barthess
Rev. 3553
Added support of I2C1 and I2C3. They may contain errors because I does not have possibility to test they.

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 11:28 am
by matis
Thanks for adding support for I2C1 :)

When I try to compile the OS I get errors on the i2c_lld.h file; It tells me that "invalid DMA stream associated to USART1 RX", "invalid DMA stream associated to USART1 TX" and for I2C2 too.
I copied the mcuconf.h like you stated above, but then it tells me STM32_I2C_I2C1_RX_DMA_STREAM is redefined.
My F103 doesn't have STM32_ADVANCED_DMA so I therefore the STM32_I2C_I2C1_RX_DMA_STREAM TX and I2C2 are static and doesn't need to be defined in my project-specific mcuconf.h ; So that gets me rid of the redefinition warning.

Unfortunately, the fixed non-advance DMA STM32_I2C_I2C1_RX_DMA_STREAM seems to be invalid by default, where the comment around tells me different.

Is this an f103 issue or a little bug in the i2c_lld files? When you need more info, please let me know!

Edit The testhal/STM32F1xx/I2C on the other hand builds fine.

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 2:46 pm
by barthess
matis wrote:When I try to compile the OS I get errors on the i2c_lld.h file; It tells me that "invalid DMA stream associated to USART1 RX", "invalid DMA stream associated to USART1 TX" and for I2C2 too.

Yea, there was lots of copypaste errors. Try to check out fresh code (rev. 3560). It also contain updated testhal\STM32F1xx\I2C
Thankfully to clean and abstract Giovanni's DMA code driver works without changes both on stm32f103 and stm32f407 (other untested, but I hope works too).
Any feedbacks and error reports are welcome.

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 3:56 pm
by matis
barthess,

I updated to rev 3560, but the problem still seems to be there. I still get the error: #error "invalid DMA stream associated to USART1 RX" in /os/hal/platforms/STM32/i2c_lld.h:200 and for the TX and I2C2.
I also have CAN, SPI and SERIAL enabled in the halconf and mcuconf.

Is there anything I should check that is different from the 2.3.4 tag, because that version builds fine?

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 4:29 pm
by Giovanni
Probably the problem is in the hal_lld_xxxxxxx.h files, those have additional attributes related to the DMA association, see the SPI attributes for example.

Giovanni

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 4:37 pm
by matis
I think I found a I2C bug in the original 2.3.4 I2C error handling.
When read through write to a non-exisiting I2C node, my system crashed into a "lockup after double fault".

When stepping through the code, I ended up at chevents.c (/os/kernel/src/) on line 244 (elp = esp->es_next;) comming fron the i2c_serve_error_interrupt()

elp becomes NULL, but the elp->el_listner and elp->el_mask are valid pointers.

When stepping into the chEvtSignalFlagsI() the chDbgCheck doesn't assert, but within the /* Test on the AND/OR conditions wait states.*/ the system crashes.

All the tp->* seems to be valid but when I try to fold open the variable tp, OpenOCD gives me the following error:

Code: Select all

target halted due to breakpoint, current mode: Thread 
xPSR: 0x01000000 pc: 0x08006ba0 msp: 0x20000400
Error: JTAG-DP STICKY ERROR
Error: MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x4f491c4c
Error: JTAG-DP STICKY ERROR
Error: MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x4f491c4c
Warn : Block read error address 0x4f491c48, count 0x2


This is the content of tp at the moment of crash:

Code: Select all

tp   0x08006ba1   
   p_next   0x844c20b6   
   p_prev   0x4f8809f3   
   p_prio   2214855408   
   p_ctx   {...}   
   p_newer   0x038f6ff3   
   p_older   0x1bfe54f0   
   p_name   0x4f491c48   
   p_stklimit   0xff3255f0   
   p_state   247   
   p_flags   214   
   p_refs   255   
   p_time   1330190152   
   p_u   {...}   
   p_waiting   {...}   
   p_msgqueue   {...}   
   p_msg   82904160   
   p_epending   82904324   
   p_mtxlist   0x9c4b1605   
   p_realprio   366212674   
   p_mpool   0x4f491648


Can anyone reproduce this problem?

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 4:40 pm
by matis
Giovanni wrote:Probably the problem is in the hal_lld_xxxxxxx.h files, those have additional attributes related to the DMA association, see the SPI attributes for example.

Giovanni

I don't have an altered hal_lld_STM32F1xx I use the one provided with the i2c_dev branch.

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 7:27 pm
by barthess
matis
Fixed. Check out rev. 3561.
If you want to handle situations of communicating with non-exisiting I2C node use error callback, for example:

Code: Select all

static void i2c_tmp75_error_cb(I2CDriver *i2cp, const I2CSlaveConfig *i2cscfg){
  (void)i2cscfg;
  if (i2cp->errors & I2CD_ACK_FAILURE){
    while(TRUE); // wrong address
  }
}


Giovanni
I observe some strange behavior of DMA in exceptional situations.
1. I configure DMA channel from transaction starter code:

Code: Select all

  mode = STM32_DMA_CR_DIR_P2M;
  dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
  dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
  dmaStreamSetMode(i2cp->dmarx, ((i2cp->dmamode) | mode));

but not set DMAEN bit (set it only if ACK from slave received).
2. Begin transaction. If slave not acknowlege code jumps to error interrupt handler. There I first of all disable DMA:

Code: Select all

  chSysLockFromIsr();
  dmaStreamClearInterrupt(i2cp->dmatx);
  dmaStreamClearInterrupt(i2cp->dmarx);
  dmaStreamDisable(i2cp->dmatx);
  dmaStreamDisable(i2cp->dmarx);
  chSysUnlockFromIsr();

3. Do some error conditioning and exit from error handler.
All looks good, BUT code anyway jumps to DMA transmission end handler. What I do wrong?

All guys
Please say on what MCU you observe errors, because code and behavior not 100% identical for F4 and F1 series.

Re: I2C implementation for STM32

Posted: Tue Dec 06, 2011 8:03 pm
by Giovanni
Hi,

It is strange, try to disable the stream first and THEN do the clearing, it an interrupt is triggered between the clearing and the disable it would remain pending. It looks like a subtle race condition.

Giovanni