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