MiMRXT1010 Eval LPUART RX and TX interrupts enabled

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MiMRXT1010 Eval LPUART RX and TX interrupts enabled

1,618 Views
enorton1379
Contributor II

Hi All,

 

I am using the MiMRXT1010 eval board and trying to use the LPUART RX and TX interrupts. For some reason it isn't working. I have tried many different ideas to try to get it working to no avail. I got the eval interrupt project to work but the RX is interrupt only not the TX which is in a while loop. Here is what I have done so far:

Here is my Init code:

const lpuart_config_t LPUART1_config = {
.baudRate_Bps = 115200UL,
.parityMode = kLPUART_ParityDisabled,
.dataBitsCount = kLPUART_EightDataBits,
.isMsb = false,
.stopBitCount = kLPUART_OneStopBit,
.txFifoWatermark = 0U,
.rxFifoWatermark = 1U,
.enableRxRTS = false,
.enableTxCTS = false,
.txCtsSource = kLPUART_CtsSourcePin,
.txCtsConfig = kLPUART_CtsSampleAtStart,
.rxIdleType = kLPUART_IdleTypeStartBit,
.rxIdleConfig = kLPUART_IdleCharacter1,
.enableTx = true,
.enableRx = true
};

static void LPUART1_init(void) {
LPUART_Init(LPUART1_PERIPHERAL, &LPUART1_config, LPUART1_CLOCK_SOURCE);
LPUART_EnableInterrupts(LPUART1_PERIPHERAL, kLPUART_TxDataRegEmptyInterruptEnable | kLPUART_RxDataRegFullInterruptEnable);
/* Enable interrupt LPUART1_IRQn request in the NVIC. */
EnableIRQ(LPUART1_SERIAL_RX_TX_IRQN);
}

 

Here is the serial code that uses the RX and TX interrupts:

// Writes one byte to the TX serial buffer. Called by main program.
void serial_write(uint8_t data)
{
// Calculate next head
uint16_t next_head = serial_tx_buffer_head + 1;
if (next_head == TX_RING_BUFFER) { next_head = 0; }
// Wait until there is space in the buffer
while (next_head == serial_tx_buffer_tail) {
// TODO: Restructure st_prep_buffer() calls to be executed here during a long print.
if (sys_rt_exec_state & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop.
}
// Store data and advance head
serial_tx_buffer[serial_tx_buffer_head] = data;
serial_tx_buffer_head = next_head;

// Enable Data Register Empty Interrupt to make sure tx-streaming is running
LPUART_EnableInterrupts(LPUART1_PERIPHERAL, kLPUART_TxDataRegEmptyInterruptEnable);
}

 

// UART Interrupt handler
void LPUART1_IRQHandler(void)
{
uint8_t data = 0xFF;
uint16_t next_head;

if ((kLPUART_RxDataRegFullFlag) & LPUART_GetStatusFlags(LPUART1_PERIPHERAL)) // Check RX interrupt flag
{
data = LPUART_ReadByte(LPUART1_PERIPHERAL);

// Pick off realtime command characters directly from the serial stream. These characters are
// not passed into the main buffer, but these set system state flag bits for realtime execution.
switch (data)
{
case CMD_RESET: mc_reset(); break; // Call motion control reset routine.
case CMD_STATUS_REPORT: system_set_exec_state_flag(EXEC_STATUS_REPORT); break; // Set as true
case CMD_CYCLE_START: system_set_exec_state_flag(EXEC_CYCLE_START); break; // Set as true
case CMD_FEED_HOLD: system_set_exec_state_flag(EXEC_FEED_HOLD); break; // Set as true
default :
if (data > 0x7F) // Real-time control characters are extended ACSII only.
{
switch(data)
{
case CMD_SAFETY_DOOR: system_set_exec_state_flag(EXEC_SAFETY_DOOR); break; // Set as true
case CMD_JOG_CANCEL:
if (sys.state & STATE_JOG) { // Block all other states from invoking motion cancel.
system_set_exec_state_flag(EXEC_MOTION_CANCEL);
}
break;
#ifdef DEBUG
case CMD_DEBUG_REPORT: {__disable_irq(); bit_true(sys_rt_exec_debug,EXEC_DEBUG_REPORT); __enable_irq();} break;
#endif
case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break;
case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break;
case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break;
case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break;
case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break;
case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break;
case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break;
case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break;
case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break;
case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break;
case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break;
case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break;
case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break;
case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break;
case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break;
#ifdef ENABLE_M7
case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break;
#endif
}

// Throw away any unfound extended-ASCII character by not passing it to the serial buffer.
} else { // Write character to buffer
next_head = serial_rx_buffer_head + 1;
if (next_head == RX_RING_BUFFER) { next_head = 0; }

// Write data to buffer unless it is full.
if (next_head != serial_rx_buffer_tail) {
serial_rx_buffer[serial_rx_buffer_head] = data;
serial_rx_buffer_head = next_head;
}
}
}
}


if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1_PERIPHERAL)) // Check TX interrupt flag
{
uint16_t tail = serial_tx_buffer_tail; // Temporary serial_tx_buffer_tail (to optimize for volatile)

// Send a byte from the buffer
if (serial_tx_buffer[tail] != 0xFF) { // Filter out 0xFF from transmit stream
LPUART_WriteByte(LPUART1_PERIPHERAL, serial_tx_buffer[tail]);
}

// Update tail position
tail++;
if (tail == TX_RING_BUFFER) { tail = 0; }

serial_tx_buffer_tail = tail;

// Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer
if (tail == serial_tx_buffer_head)
{
LPUART_DisableInterrupts(LPUART1_PERIPHERAL, kLPUART_TxDataRegEmptyInterruptEnable); // Disable Tx Data Empty Interrupt
}
}
}

 

As you can see, I need both RX and TX interrupts in my use case. What am I doing wrong and what can I do to fix this?

 

Thanks,

Eric Norton

Labels (1)
0 Kudos
8 Replies

1,589 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Eric,

I think you are using MCUXpresso SDK for RT1010 LPUART driver. Please refer <lpuart_interrupt_transfer> example project.

We do not recommend customer to change the LPUART interrupt service routine.

Please refer example project to use Callback function to set flag status.

Mike

 

1,581 Views
enorton1379
Contributor II

Hi Mike,

 I managed to figure out how to use the LPUART with interrupts. This was preventing the LPUART from functioning properly:

#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
/* Init FSL debug console. */
BOARD_InitDebugConsole();
#endif

I spent hours trying to figure out why it wasn't working. Also, rxfifowatermark needed to be set to zero for the receive to work correctly.

On to the new issue. I was able to get the project up and running sort of... For some reason when I go to run the job in LightBurn (I created a custom Grbl motion controller) the processor resets or basically goes back to main. How do find out in the debug session what is causing the reset? I have been looking all over the place in MCUxpresso on how to find the exception catching to see if there is an event that is causing the reset. Is there another way to find out what is causing the chip to reset or is there a watchdog running by default? I am using the RT1010 evaluation board.

Just to let you know I am using code that works for a cortex M4F processor, so I know it all works it's just that there must be something I am not seeing from a cortex M7 point of view.

Any ideas please let me know as soon as you can.

Thanks,

Eric

0 Kudos

1,576 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Eric,

You can check the SRC Reset status register (SRC_SRSR) value.

The SRC reset status register will capture all the reset sources that have occurred.

Wish it helps.

Mike

1,573 Views
enorton1379
Contributor II

Hi Mike,

 This might sound stupid, but I am a newbie to cortex M7 and NXP in general. I work with Nuvoton products mostly, so all of this is very new to me.

Where and how can I monitor SRC_SRSR register? I see the "Registers" for the core, but I don't see SRC_SRSR. I need a little help please :-D.

Is there anything I need to be mindful of when converting a project from a M4F to M7 device? I saw that it will work but wondering what is really required from a project standpoint?

Please let me know.

Thanks,

Eric

 

0 Kudos

1,546 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Eric,

Please refer RT1010 <power_mode_switch_bm> demo of MCUXpresso SDK package.

There with below code to print "SRC_SRSR" register value:

PRINTF("\r\nCPU wakeup source 0x%x...\r\n", SRC->SRSR);

You can refer and use this code to check SRC_SRSR register value.

Wish it helps.

Mike

1,519 Views
enorton1379
Contributor II

Hi Mike,

I think I figured out what is going on. I have this transmit function:

 

// Writes one byte to the TX serial buffer. Called by main program.

void serial_write(uint8_t data)

{

  // Calculate next head

  uint16_t next_head = serial_tx_buffer_head + 1;

  if (next_head == TX_RING_BUFFER) { next_head = 0; }

  // Wait until there is space in the buffer

  while (next_head == serial_tx_buffer_tail) {

       // TODO: Restructure st_prep_buffer() calls to be executed here during a long print.

       if (sys_rt_exec_state & EXEC_RESET) { return; } // Only check for abort to avoid an endless loop.

  }

  // Store data and advance head

  serial_tx_buffer[serial_tx_buffer_head] = data;

  serial_tx_buffer_head = next_head;

 

  // Enable Data Register Empty Interrupt to make sure tx-streaming is running

  LPUART_EnableInterrupts(LPUART1_PERIPHERAL, kLPUART_TxDataRegEmptyInterruptEnable);

}

As you can see above in bold and enlarged, is LPUART_EnableInterrupts call correct to turn ON the TxDataRegEmpty Interrupt?

 

Is there another way to do this?

 

 

Here is the TX interrupt handler:

if (kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART1_PERIPHERAL)) // Check TX interrupt flag

{

       uint16_t tail = serial_tx_buffer_tail; // Temporary serial_tx_buffer_tail (to optimize for volatile)

 

       // Send a byte from the buffer

       if (serial_tx_buffer[tail] != 0xFF) {  // Filter out 0xFF from transmit stream

              LPUART_WriteByte(LPUART1_PERIPHERAL, serial_tx_buffer[tail]);

       }

 

       // Update tail position

       tail++;

       if (tail == TX_RING_BUFFER) { tail = 0; }

 

       serial_tx_buffer_tail = tail;

       // Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer

       if (tail == serial_tx_buffer_head)

       {

LPUART_DisableInterrupts(LPUART1_PERIPHERAL,kLPUART_TxDataRegEmptyInterruptEnable); // Disable Tx Data Empty Interrupt

       }

}

As you can see above, I am trying to turn OFF the TxDataRegEmpty interrupt. I need to be able to control the interrupt to conclude the transfer and not sure if this is correct?

I’m getting garbled data like this:

enorton1379_0-1667365682582.png

In order for this to work correctly I need complete control of the TX interrupts. The documentation and the demo examples don’t show how to handle this particular situation and need help asap if possible. This I believe is the main reason why the whole project isn’t working and causing the crashes I’m experiencing.

Please let me know at your earliest what I can do to remedy this situation.

Thanks,

Eric

0 Kudos

1,532 Views
enorton1379
Contributor II

Hi Mike,

 Thank you for letting me know. I found a way to display it.

 

I am still having trouble with the design and cannot figure out what is going on. Is there a software reset like a watchdog or memory reset or anything else the chip does if there is a condition it doesn't like? 

The code I am porting over works great on a cortex-M4 but having trouble with it on the cortex-M7. I can get it to communicate with LightBurn and it can see the settings in the program and the motors move in jog mode but when I try running it just falls apart and fails. I was thinking it could be a reset or ram issue but may be wrong. Could it be the FPU? Could there be something in the FPU causing a reset of some sort? It seems like when I try to run it jumps back to main which to me indicates a reset of some sort.

Any ideas would be greatly appreciated

Thanks,

Eric

0 Kudos

1,513 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Eric,

Please refer SDK example, there has WDOG_DISABLE codes at SystemInit() function of <system_MIMXRT1011.c> file.

Please make sure your project also disable the WDOG during system initialization.

Hui_Ma_0-1667381658620.png

Mike

0 Kudos