Hello Nordic Semiconductor
I am developing a small application on the nRF52840 development kit where I need to transfer I2S signals in/out of the MCU. I have set up an I2S_IRQHandler() that gets triggered whenever EVENT_TXPTRUPD gets set. However, I cannot clear it again, which I am supposed to do in the interrupt handler. Basically, this turns my interrupt handler into an endless loop, never returning to the main loop after the event.
I believe this is a bug. I found this thread as well, which I believe is the same problem:
So, I created a small project that can reproduce the problem. I used Ozone - The J-Link Debugger to debug the problem. However, I could not find the EVENTS_TXPTRUPD register inside the register viewer, so I watched a variable "tmp" instead.
I have included a source file that can reproduce the problem below, as well as some screenshots, where I go through a few breakpoints. Watch the variable "tmp" in the "Global Data" window in the upper right corner.
My SDK and toolchain versions are nRF5_SDK_17.1.0_ddde560 and gcc-arm-none-eabi-9-2020-q2-update respectively.
I am not sure which revision of the nRF52840 DK I am using, but there is a sticker saying "PCA10056, 2.0.2, 2021.50, 683128720". Please let me know if you need further information.
Thank you in advance :-)
#include "boards.h"
// Temporary variable to store register value
volatile uint32_t tmp;
// RX and TX buffers for I2S
volatile int16_t i2s_rx_buf[128];
volatile int16_t i2s_tx_buf[128];
int main(void)
{
tmp = 0;
// Set I2S in master mode and the clocks to ~ 48 kHz sample rate
NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_Master;
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV21;
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_32X;
// Set the format to 16-bit stereo
NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_Stereo;
NRF_I2S->CONFIG.FORMAT = I2S_CONFIG_FORMAT_FORMAT_I2S;
NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_Left;
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16Bit;
// Buffer setup
NRF_I2S->RXTXD.MAXCNT = 64;
NRF_I2S->RXD.PTR = (uint32_t)i2s_rx_buf;
NRF_I2S->TXD.PTR = (uint32_t)i2s_tx_buf;
// Pin setup
NRF_I2S->PSEL.MCK = (1<<5) | 1; // Connect MCK to P1.01
NRF_I2S->PSEL.SCK = (1<<5) | 2; // Connect SCK to P1.02
NRF_I2S->PSEL.LRCK = (1<<5) | 3; // Connect LRCK to P1.03
NRF_I2S->PSEL.SDIN = (1<<5) | 4; // Connect SDIN to P1.04
NRF_I2S->PSEL.SDOUT = (1<<5) | 5; // Connect SDOUT to P1.05
// Configure interrupts
NRF_I2S->INTEN = I2S_INTEN_TXPTRUPD_Enabled;
NVIC_EnableIRQ(I2S_IRQn);
// Enable and start
NRF_I2S->CONFIG.RXEN = I2S_CONFIG_RXEN_RXEN_Enabled;
NRF_I2S->CONFIG.TXEN = I2S_CONFIG_TXEN_TXEN_Enabled;
NRF_I2S->CONFIG.MCKEN = I2S_CONFIG_MCKEN_MCKEN_Enabled;
NRF_I2S->ENABLE = 1;
NRF_I2S->TASKS_START = 1;
// Main loop
while (1);
}
void I2S_IRQHandler()
{
// Clear the event (but store the value before and after for debugging)
tmp = NRF_I2S->EVENTS_TXPTRUPD; // Set breakpoint here
NRF_I2S->EVENTS_TXPTRUPD = 0;
tmp = NRF_I2S->EVENTS_TXPTRUPD; // Set another break point here
tmp; // and a third breakpoint here
}



