I2C with STM32L476 Discovery responds with ACK Fail
Posted: Mon Jul 08, 2019 4:18 am
I wonder if you can help me. I have been spinning my wheels for the past few days trying to get the CODEC in STM32L476-Discovery board to respond, and always I get ACK FAIL error (or 4 I2C_ISR_NACKF in interrupt). I have code reviewed the internals of ChibiOS' I2C HAL driver and it looks solid. But I don't know what is the problem. It should be noted that:
- If I program bare metal (via I2C polling), it works.
- If I program via STM32L4 HAL driver using interrupts, it works.
- I've tested ChibiOS with I2C with DMA and without DMA (via interrupts), still I could not get it to work.
- I get the same result irrespective if I use ChibiOS 19.1 or 18.2
- Same result even if I comment out all board initialization in board.c and I initialize the pins manually, still the same result
- I tried several variations for the clocks configurations, turned on all debugging, pull up and open drain for the I2C pins, still it didn't work.
- the same program works for STM342F4 Discovery from the get go
I looked hard for any examples for STM32L4 with I2C, and I found nothing. Can you please point me some where where there is an I2C example for the STM32L4XX? I am at a lose here.
Many thanks
I will appreciate any help. I am at a lose here. Here is my program, it is VERY simple. Nothing fancy
[nfo]#include "ch.h"
#include "hal.h"
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
(void)arg;
chRegSetThreadName("blinker");
while (true) {
palClearLine(LINE_LED_GREEN);
chThdSleepMilliseconds(550);
palSetLine(LINE_LED_GREEN);
chThdSleepMilliseconds(500);
}
}
#define CODEC_ADDRESS 0x4A
static I2CConfig i2cfg_1 = {
STM32_TIMINGR_PRESC(15U) |
STM32_TIMINGR_SCLDEL(4) | STM32_TIMINGR_SDADEL(2U) |
STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),//0xf0420f15
0,//I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI,
0
};
int main(void) {
msg_t result = 0;
uint8_t txbuf[2];
uint8_t rxbuf[2];
i2cflags_t flagsError = 0;
halInit();
chSysInit();
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP); //SCL = PB6 -> I2CD1
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP);
result = 0;
flagsError = 0;
i2cStart(&I2CD1, &i2cfg_1);
//Get CODEC device ID, 0xE0 is expected
txbuf[0]=0x01; txbuf[1]=0x00;
result=i2cMasterTransmitTimeout(&I2CD1, CODEC_ADDRESS, txbuf, 1 ,rxbuf, 1, 1000);
if ( !result)
result=i2cMasterReceiveTimeout(&I2CD1, CODEC_ADDRESS, rxbuf, 1 ,1000);
if ( result != 0 ){
flagsError=i2cGetErrors(&I2CD1);
palToggleLine(LINE_LED_RED);
}
//sdStart(&SD2, NULL);
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
while (true) {
if (palReadLine(LINE_JOY_CENTER)) {
//chprintf(chp, "***LINE_JOY_CENTER Pressed\r\n");
}
chThdSleepMilliseconds(500);
}
}[/nfo]
- If I program bare metal (via I2C polling), it works.
- If I program via STM32L4 HAL driver using interrupts, it works.
- I've tested ChibiOS with I2C with DMA and without DMA (via interrupts), still I could not get it to work.
- I get the same result irrespective if I use ChibiOS 19.1 or 18.2
- Same result even if I comment out all board initialization in board.c and I initialize the pins manually, still the same result
- I tried several variations for the clocks configurations, turned on all debugging, pull up and open drain for the I2C pins, still it didn't work.
- the same program works for STM342F4 Discovery from the get go
I looked hard for any examples for STM32L4 with I2C, and I found nothing. Can you please point me some where where there is an I2C example for the STM32L4XX? I am at a lose here.
Many thanks
I will appreciate any help. I am at a lose here. Here is my program, it is VERY simple. Nothing fancy
[nfo]#include "ch.h"
#include "hal.h"
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
(void)arg;
chRegSetThreadName("blinker");
while (true) {
palClearLine(LINE_LED_GREEN);
chThdSleepMilliseconds(550);
palSetLine(LINE_LED_GREEN);
chThdSleepMilliseconds(500);
}
}
#define CODEC_ADDRESS 0x4A
static I2CConfig i2cfg_1 = {
STM32_TIMINGR_PRESC(15U) |
STM32_TIMINGR_SCLDEL(4) | STM32_TIMINGR_SDADEL(2U) |
STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U),//0xf0420f15
0,//I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI,
0
};
int main(void) {
msg_t result = 0;
uint8_t txbuf[2];
uint8_t rxbuf[2];
i2cflags_t flagsError = 0;
halInit();
chSysInit();
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP); //SCL = PB6 -> I2CD1
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP);
result = 0;
flagsError = 0;
i2cStart(&I2CD1, &i2cfg_1);
//Get CODEC device ID, 0xE0 is expected
txbuf[0]=0x01; txbuf[1]=0x00;
result=i2cMasterTransmitTimeout(&I2CD1, CODEC_ADDRESS, txbuf, 1 ,rxbuf, 1, 1000);
if ( !result)
result=i2cMasterReceiveTimeout(&I2CD1, CODEC_ADDRESS, rxbuf, 1 ,1000);
if ( result != 0 ){
flagsError=i2cGetErrors(&I2CD1);
palToggleLine(LINE_LED_RED);
}
//sdStart(&SD2, NULL);
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
while (true) {
if (palReadLine(LINE_JOY_CENTER)) {
//chprintf(chp, "***LINE_JOY_CENTER Pressed\r\n");
}
chThdSleepMilliseconds(500);
}
}[/nfo]