2
votes

Platform - ARM9

I have a third party device connected via I2C to the ARM9. My problem is the I2C read/write is getting in a twist. It appears the IRQ line is asserted but never de-asserted when there is data to read. The read fails as the third-party device NACKs the address packet. So any subsequent write fails.

I am wondering if my interrupt handling in ok. In the ISR that services the IRQ, I disable interrupts, unregister the interrupt handler and then signal to the task to go read from the I2C bus. Finally, I re-enable the interrupts.

When the task services the signal posted above, I attempt to read data from the I2C bus but this fails. Finally, I always reregister the ISR after ever read attempt. There is no interrupt disabling/enabling that takes place during handling of the read signal.

My question is do I need to disable interrupts when reading/writing to the I2C bus?

Programming language of choice is c using propriety RTOS.

3
If the IRQ is never deasserted, are you sure that you're reading enough and/or the right data from the device to cause it to deassert the IRQ? - bstpierre
The device documentation specifies that it always puts X data onto the bus so I only try to read that X bytes. More so, I am using the I2C to update the firmware to the device ok. It is only a certain point that the device suddenly stops deasserting the IRQ line - dubnde
I am beginning to think it may a race condition as it works until at this point when there is a burst of data exchange between the device and the processor where my task is running. Prior to this point in time, I can send commands and get responses without a problem. - dubnde

3 Answers

3
votes

An important thing is whether your RTOS/system is ready to support nested exceptions. Unless there is a good reason to do so, things are simpler if you avoid nested exceptions and disable all interrupts when entering an ISR and re-enabling when leaving.

If you want to allow other higher-priority interrupts to occur while you are serving the I2C interrupt, then disable only the I2C interrupt. It is rather unusual to unregister an interrupt handler when entering an ISR. This may lead to unexpected behaviour, when there is no registered handler, the interrupt itself is enabled and an interrupt occurs. So instead of unregistering the handler, simple disable the I2C interrupt (Perhaps you are already doing so, but as I see it, registering a handler and enabling an interrupt are two different things).

A good strategy to solve your problem will be to try to communicate with the device without interrupts. Try to read/write from it in a serial fashion, doesn't matter if everything blocks - it is just testing. This is much easier to debug and after you are successful you can move to the interrupts version.

1
votes

Most interrupts need to be acknowledged or cleared. You mention enabling/disabling, registering/unregistering and handling the interrupt. Just check that the interrupt is being acknowledged and/or cleared/reset. Often this involves writing the interrupt number or bit back to the interrupt pending register. Check the specific ARM manual or your RTOS manual.

0
votes

Whether you need to enable/disable interrupts for your target platform is dependant on your specific hardware/RTOS implementation. Unfortunately, every ARM microcontroller vendor (STMicro, Freescale, Oki, etc) has the ability implement their I2C hardware differently and may have different requirements in how to clear the IRQ.

I'd recommend you find a copy of the hardware datasheet (and/or post the specific hardware part-number here so we can help pour over the vendor documentation, with you).