Showing results for 
Search instead for 
Did you mean: 

How and when is a I2C slave supposed to tell the master "bad request"?

Senior II

Implementing a I2C in slave mode, I found in the reference manual,

26.7.2 Control register 2 (I2C_CR2):

Bit 15 NACK: NACK generation (slave mode)

The bit is set by software, cleared by hardware when the NACK is sent, or when a STOP

condition or an Address matched is received, or when PE=0.

0: an ACK is sent after current received byte.

1: a NACK is sent after current received byte


This sounds to me like you're supposed to set NACK only when you just received a byte and e.g. got the RXNE IRQ.

From reading descriptions about I2C protocol elsewhere, I got the idea that if a master sends a bad request, like accessing a non-existant register or writing to a readonly register, a slave may signal that with a NACK.

Now I wonder where in the sequence of I2C bus activites (or, interrupts that I get) to place this NACK.

After I got the following incomplete I2C transaction sequence: {start, Waddr, Wdata(registerNum), restart, Raddr}, the MCU will be in the interrupt with the ADDR flag set.

As that might not count as "receiving a byte", this would be the wrong place to set the NACK bit?

I can't reject the request yet with NACK when the register number is received (as a data byte), because the bit for whether a register is to be read or written is only known with the Raddr (Address with read-bit=1) event at the end of this broken sequence.

So I would set NACK bit on the first byte sent, but wouldn't this also possibly just mean "there are no more bytes" / end of transmission?

The current state of my implementation:

Receiving existing registers' contents from the slave by the master works.

Handling not-allowed requests does not work:

Currently, I set the NACK bit in the interrupt routine when I get the Raddr, do *not* enable TX IRQ like I would for legal requests, and set my state machine to IDLE again.

But then I never get another interrupt, and I see that BUSY as well as TXIE are set in the ISR register.

BUSY is still on because the master did not generate a stop conditionor anything else after the Raddr of the described event sequence above, I guess.

So I wonder how this is supposed to be done.

I guess I could disable and enable the peripheral to clear the busy bit in that scenario, but I doubt that's "the way" 😉

The master end of things here is a Linux program using the usermode I2C driver that comes with the kernel.

At the point of the end of that sequence above, there is a read error on the master, so I guess form that end, the fact that the command was not allowed has been noted.


This appears to be an oversight in ST's I2C peripheral implementation. Were you able to find a work-around?