I2C with STM32L476 Discovery responds with ACK Fail

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
Post Reply
User avatar
Abusous2000
Posts: 15
Joined: Fri Jul 05, 2019 1:26 am
Has thanked: 7 times
Been thanked: 3 times

I2C with STM32L476 Discovery responds with ACK Fail

Post by Abusous2000 »

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]
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Giovanni »

Hi,

What address are you using? in ChibiOS the "address" is just the 7 bits address field without the R/W bit. Divide the address byte value by two.

Giovanni
User avatar
Abusous2000
Posts: 15
Joined: Fri Jul 05, 2019 1:26 am
Has thanked: 7 times
Been thanked: 3 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Abusous2000 »

Giovanni wrote:What address are you using?
Giovanni

Thanks for the quick reply Giovanni. I passed to ChibiOS the address 0x4A by dividing the CODED address of 0x94 by two. Most importantly the same code works but for STM32F4 Discovery which has the same CS43L22 CODEC, I just changed the SDA to port B9.
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Giovanni »

Hi,

Some things to check:

1) F4 and L4 use a different I2C (I2Cv1 vs I2Cv2) so your configuration structure is different, make sure you got a valid configuration for I2Cv2.
2) GPIO settings, check that the correct alternate modes are selected and that I2C pins are only configured on ONE GPIO pin.
3) External pull up resistors.

Giovanni
User avatar
Abusous2000
Posts: 15
Joined: Fri Jul 05, 2019 1:26 am
Has thanked: 7 times
Been thanked: 3 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Abusous2000 »

Giovanni wrote:Hi Giovanni,
1) F4 and L4 use a different I2C (I2Cv1 vs I2Cv2) so your configuration structure is different, make sure you got a valid configuration for I2Cv2.
2) GPIO settings, check that the correct alternate modes are selected and that I2C pins are only configured on ONE GPIO pin.
Giovanni

YES I am aware it, otherwise the code wouldn't even compile. As follows, the 1st is for the I2Cv2 Config Structure
[nfo]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,
0
};[/nfo]
this is for the I2C pins
[nfo]palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP);// tried open drain too
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_FAST | PAL_STM32_PUPDR_PULLUP);[/nfo]
and I connected PB6 and PB7 each to an external 4.7k resistor on one end, and the other end of each resister to connected to 3.3V
It SHOULD BE NOTED that if code bare metal I2C (or STM32L4 HAL driver) via Polling or Interrupts, it works with or without external pull up resistors. I am at a loss here. If you have any working example for ChibiOS with STM32L476 Discovery, I would appreciate it.
Many thanks in advance, I am big fan of ChibiOS
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Giovanni »

I don't have examples with L4 but it should be the same of other devices using I2Cv2.

Both pins must be open drain. I think you should observe signals with a logic analyzer to understand what's the problem.

Giovanni
User avatar
Abusous2000
Posts: 15
Joined: Fri Jul 05, 2019 1:26 am
Has thanked: 7 times
Been thanked: 3 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Abusous2000 »

Thanks again Giovanni. YES, I tested with Open Drain for the pins, and still no luck. Below is my result from the logic analyzer, the 1st with ChibiOS, and the second from bare metal I2C driver (it looks fine)
I will keep working on it, and if I have any luck, I will post what I found.
Many thanks Giovanni for your help
Attachments
From logic analyzer output with ChibiOS 19.1 as you see the slave address isn't even written correctly
From logic analyzer output with ChibiOS 19.1 as you see the slave address isn't even written correctly
From logic analyzer output with bare metal I2C driver, looks fine
From logic analyzer output with bare metal I2C driver, looks fine
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Giovanni »

The address is sent as zero, strange, I wonder what could cause that. Of course there is no ACK and the transaction stops there.

Anyway, you need to set those pins open drain, it is not an option, I2C works that way.

Giovanni
User avatar
Abusous2000
Posts: 15
Joined: Fri Jul 05, 2019 1:26 am
Has thanked: 7 times
Been thanked: 3 times

Re: I2C with STM32L476 Discovery responds with ACK Fail

Post by Abusous2000 »

I just retested but with open drain, that did the trick. I am bad Giovanni.

Many thx that did the trick man.
Post Reply