Context: I have an nRF52 micro dev board and I'm trying to communicate with a specific device over i2c; where
nRF52 is the master and
device is the slave.
My problem: I'm wondering if this particular device (i.e. i2c slave) requires a certain number of retries before it ACKs my start sequences.
My solution: Let me implement my own interface for the on-board i2c (twim) peripheral as the current twim interface implementation in nrf-hal-common does not have an option to add retries.
Where it doesn't make sense:
- My board triggers the i2c transmit sequence correctly when I use the default
Twim interfacethat's included in
nrf-hal-common. This is verified by my logic analyzer's output.
- However, when I use the exact same interface defined in (nrf-hal-common) as a module in my crate (i.e. not import it from nrf-hal-common),
the i2c start sequence does not trigger.
- After compiling and debugging both versions, I see all
i2c register writesprior to the start sequence trigger are in order, in both cases.
Register writes for the 'default Twim interface' included in nrf-hal-common
=> 0x324 <atecc608a::__cortex_m_rt_main+520>: movs r0, #96 ; 0x60 0x326 <atecc608a::__cortex_m_rt_main+522>: str.w r0, [r10] // i2c ADDRESS write 0x32a <atecc608a::__cortex_m_rt_main+526>: str.w r4, [r10, #-68] // i2c twim PTR register write 0x32e <atecc608a::__cortex_m_rt_main+530>: str.w r9, [r10, #-64] // i2c twim MAXCOUNT register write 0x332 <atecc608a::__cortex_m_rt_main+534>: str.w r9, [r6, #-252] // i2c transmit trigger register write 0x336 <atecc608a::__cortex_m_rt_main+538>: ldr r0, [r6, #92] ; 0x5c
Register writes for the 'my version of the Twim interface'
=> 0x1a0 <nRFiic::__cortex_m_rt_main+150>: movs r3, #96 ; 0x60 0x1a2 <nRFiic::__cortex_m_rt_main+152>: str r3, [r0, #124] ; 0x7c // i2c ADDRESS write 0x1a4 <nRFiic::__cortex_m_rt_main+154>: str r2, [r0, #56] ; 0x38 // i2c twim PTR register write 0x1a6 <nRFiic::__cortex_m_rt_main+156>: movs r2, #1 0x1a8 <nRFiic::__cortex_m_rt_main+158>: str r2, [r0, #60] ; 0x3c // i2c twim MAXCOUNT register write 0x1aa <nRFiic::__cortex_m_rt_main+160>: str.w r2, [r1, #-252] // i2c transmit trigger register write 0x1ae <nRFiic::__cortex_m_rt_main+164>: ldr r2, [r1, #92] ; 0x5c
As all register writes and reads are 'intrinsics', I don't see a problem with this except that the default implementation does full word (or 4 byte) register writes while my version does not. Semantically speaking, they both achieve the same result. I have verified this with VSCode's
- Any idea why this is happening?
- How does one implement an interface for a given peripheral? Am I missing something?
- Is there a simpler way to just extend the existing nrf-hal-common interface implementation in my project?