Hello, this question applies to all Hercules processors, in particular the RM57 and RM46.
I am trying to read and write to a device on the I2C bus that runs at a very slow 1 kbps data rate. There is a bit of handshaking involved, and sometimes that device will be powered off and will "Nack" as a result. Since the device is so slow, using polling is not an option, and I need to use interrupt-based communications.
The way I'm currently approaching the issue is having a timer to manage the state machine that does the handshaking. This timer interrupt is a state machine that runs at a certain rate, say 100 Hz, which cycles through the following states:
(1)write an address pointer with 1 byte of data (a device address pointer, say memory location 0x27)
(2)read from that address y bytes of data and wait for end of transmission.
(3) check for unresponsive devices and NACKs as necessary.
Here's what I've done so far, which seems to work.
(1) set up interrupts that trigger as TX and RX interrupts (ICRRDY and ICXRDY)
(2) set up an RTI at, say 100 Hz
State Machine:
(0) i2cinit() then move to state 1
(1) wait x cycles in a cycle wait state then move to step 2 once wait cycle is complete.
(2) check for bus busy, reset i2c (i2cinit() ) if bus busy not cleared in x cycles, otherwise set up i2c as master transmitter and send a start, one address,one byte, and a stop condition
(3) wait y cycles in a cycle wait state until bus busy cleared (transmission is complete), go to step 0 if bus busy not cleared, or 4 if cleared
(4) set up for a read of z bytes, send start and address, and begin the interrupt process of reading z bytes, go to step 5.
(5) wait c cycles in a cycle wait state until bus busy cleared (receipt is complete) and no improper NACKs and read resulting data, go to step 2 if everything went okay, otherwise go to step 0 (i2c init) if bus busy doesn't clear in c cycles.
Here are my questions:
(1) This method seems awfully convoluted, but the only way I can see doing hardware handshaking with a slow device over i2c in a completely non-blocking way. Any other suggestions on how to accomplish this without polling or DMA? Is this a reasonable solution?
(2) Do I have enough interrupts (ICRRDY and ICXRDY) set up? I did not set up ARDY or NACK for interrupts. NACKs are checked manually in the state machine e.g. (if( (i2cREG1->STR & (uint32)I2C_NACK) go to i2c reset state)
(3) I'm confused on what things I need to check for in order to make sure i2cwrite and i2cread finish completely. For example, is bus busy bit the easiest and best way to check for completed read and write cycles?
(4) Aside from calling i2cinit() everytime the bus goes down, is there an easier way to get the i2c bus reset back to a ready state?
Best,
Josh