irq_lock() not working on nRF5340

I'm working on adapting ST's RFAL NFC library for ST25R3916B/X-NUCLEO-NFC08A1 on an nRF5340/DK in order to emulate an NFC tag, and have run into an inconsistency I'm hoping for help on. When I run the RFAL, the vast majority of SPI transactions run without any problems. At minimum two points, I get the below error:

The RFAL requires that a mechanism to lock interrupts be provided; this is alongside manual CS control so that multiple SPI transactions to be chained (see below for example code). st25r3916comStart() disables interrupts and sets CS active (low); st25r3916comStop sets CS inactive (high) and reenables interrupts. My abstractions of those functions just call irq_lock and store the key, then irq_unlock() with the same key, in order, as expected. However, I'm seeing SPI behavior where when, during a set of transactions (after irq_lock() has been called) the ISR is still executed. Please see the below capture + table for the behavior, described in the following steps:

  1. The 5340 sends a 0x42 to read register 02.
  2. An IRQ is sent, unrelated to the 0x42.
  3. In the ISR, the 5340 sends a 0x5A to read the interrupt registers. Instead of a 0x00 from the ST25 as usual, it sends 0x83 because from the ST25's perspective, it's still responding to the 0x42.
  4. The 5340 sends four 0xFF frames to read the four IRQ registers, and gets the IRQ (TXE in this case).
  5. The IRQ goes low. Control returns to the main thread. CS goes high because the response is complete.

During step 3, the SPI peripheral attempts to put the 0x83 into a nullptr, causing a memory access exception (I think). What I don't understand is why the next four 0xFFs were sent, as the host should have already crashed.

My GPIO IRQ init is below as well, it initializes without any problems. This is the IRQ pin associated with the SPI instance.

This is not the irq_lock() behavior I expected. CONFIG_USERSPACE is not set, so this is a supervisor thread. Please let me know what I should adjust to get the expected behavior.

st25r3916comStart();

st25r3916comTxByte( ST25R3916_FIFO_READ, true, false );

st25r3916comRepeatStart();

st25r3916comRx( buf, length );

st25r3916comStop();

Parents Reply
  • LltWc said:
    So far as I can tell, that comes from IRQ handling, which shouldn't be occurring.

    Could it be that you are putting the thread that called irq_lock() to sleep?

    See the docs here:

    https://docs.zephyrproject.org/latest/kernel/services/interrupts.html#preventing-interruptions

    The IRQ lock is thread-specific. If thread A locks out interrupts then performs an operation that puts itself to sleep (e.g. sleeping for N milliseconds), the thread’s IRQ lock no longer applies once thread A is swapped out and the next ready thread B starts to run.

    This means that interrupts can be processed while thread B is running unless thread B has also locked out interrupts using its own IRQ lock. (Whether interrupts can be processed while the kernel is switching between two threads that are using the IRQ lock is architecture-specific.)

    "

Children
  • That's interesting, I had missed that. The library is not Nordic-specific, so it doesn't have multithreading in itself, but I do have logging enabled, which I know is its own thread.

    I did just disable logging and hook the logic analyzer back up, and I see the same issue. So as long as setting CONFIG_LOG=n stops the logging thread from being created, the irq_lock() still isn't stopping interrupts.

Related