cancel
Showing results for 
Search instead for 
Did you mean: 

How to generate UART RX INTERRUPT WITH SPC58EC-DISP

Orazio
Associate II

Hello All,

I am working on UART on SPC58EC-disp Discovery board importing and using example source code "SPC58ECxx_RLA SERIAL DMA Test Application for Discovery" in SPC5Studio.

I can transmit the data but unable to receive the data by interrupt method to avoid blocking.

In the original project, I have only changed, in the main.c file,  the two highlighted row as follow:

#include "components.h"

#include "serial_lld_cfg.h"

void sddmatxcb(SerialDriver *sdp) {

 (void)sdp;

 pal_lld_togglepad(PORT_F, PF_LED1);

}

void sddmarxcb(SerialDriver *sdp) {

 (void)sdp;

 pal_lld_togglepad(PORT_F, PF_LED2);

}

int main(void) {

 uint8_t message[]= "Hello World!\r\n";

 /* Enable Interrupts */

 irqIsrEnable();

 sd_lld_start(&SD1, &serial_config_sddmacfg);

 /* Application main loop.*/

 for ( ; ; ) {

  (void)sd_lld_write(&SD1,message,(uint16_t)(sizeof(message)/sizeof(message[0])));

  osalThreadDelayMilliseconds(1500);

  //pal_lld_togglepad(PORT_F, PF_LED2);

 }

}

Doing Debug firmware with UDE STK 5.0, and putting a breakpoint in "sddmarxcb" callback function, i observe that never entry in this function. Please guide me with Rx interrupt initialization so that I can receive the data without blocking.

Thank You,

Orazio

This discussion has been locked for participation. If you have a question, please start a new topic in order to ask your question
1 ACCEPTED SOLUTION

Accepted Solutions
Erwan YVIN
ST Employee

Hello ,

Sorry for the late answer ;)

Good to see that your have solved your issue.

Adapt the driver is a good choice.

For the big project relative to collect some data coming from UART. (Near-space balloon, Automotive project and so on ..)

we are using :

  • Chibios / FreeRTOS threads to save CPU
  • some functions serial_input.c / .h with Runtime Components (cf Screenshot)

0693W000008GRgIQAW.png 

Best Regards

Erwan

View solution in original post

6 REPLIES 6
Orazio
Associate II

I would like to add more details.

Debugging fw with UDE STK 5.0 and putting a breakpoint in "spc5_linflex.c" file and exactly in IRQ_HANDLER(SPC5_LINFLEX0_ERR_HANDLER) function

I observe that arrive in this function . So it means that when i send a byte in rx channel, it rise an error interrupt managed by SPC5_LINFLEX0_ERR_HANDLER.

But i don't understand the cause. Can some one help me ?

IRQ_HANDLER(SPC5_LINFLEX0_ERR_HANDLER) {

 IRQ_PROLOGUE();

 LinflexD1.err_lincallback(LinflexD1.device);

 IRQ_EPILOGUE();

}

 
Orazio
Associate II

I changed the code, as indicated in the attached file. Now the uart is able to receive the data and to enter the "sddmarxcb" callback function but only once.

Any suggestions ?

Thanks

#include "components.h"

#include "serial_lld_cfg.h"

#include <string.h>

uint8_t typedChar[1] = " ";

void sddmatxcb(SerialDriver *sdp) {

 (void)sdp;

 pal_lld_togglepad(PORT_F, PF_LED1);

}

void sddmarxcb(SerialDriver *sdp) {

 (void)sdp;

 pal_lld_togglepad(PORT_F, PF_LED2);

 (void)sd_lld_read(&SD1, typedChar, 1);

}

int main(void) {

 char message[64];

 componentsInit();

 /* Enable Interrupts */

 irqIsrEnable();

 /*

  * Activates the serial driver 1 using the driver default configuration.

  */

 sd_lld_start(&SD1, &serial_config_sddmacfg);

  

 (void)sd_lld_read(&SD1, typedChar, 1);

  

 /* Application main loop.*/

 for ( ; ; ) {

strncpy (message, "Type a character - Last char typed was :", sizeof("Type a character - Last char typed was :"));//uint8_t message[]= "Hello World!\r\n";

  strcat(message, (char *)typedChar);

  strcat(message, "\r\n");

  (void)sd_lld_write(&SD1, (uint8_t *) message,(uint16_t)(sizeof(message)/sizeof(message[0])));

  osalThreadDelayMilliseconds(1500);  

 }

}

In this post, someone describe the same issue.

https://community.st.com/s/question/0D53W000005pnUKSAY/how-can-i-programming-uart-interruptsdlldread

Please Erwan YVIN can you explaine how to adapt the driver, so to have interrupts run whenever I receive data?

  1. **
  2. * @brief Serial read without DMA
  3. *
  4. * @param[in] sdp pointer to a @p SerialDriver object
  5. * @param[out] buffer data buffer receiver
  6. * @param[out] len number of bytes received
  7. *
  8. * @return The number of bytes effectively read.
  9. *
  10. * @notapi
  11. */

static uint16_t sd_rx(SerialDriver* sdp, uint8_t* buffer, uint16_t len)

Orazio
Associate II

Hi to all. Thanks a lot for the support received.

I have solved my issue, using a workaround. I would share the solution for two reasons. First one oriented to have a feedback from you about the actions applied by me to adapt the driver. Second one oriented to share a solution for otherone afflicted by the same issue.

The work around consist in adapt spc5xx_serve_rxi interrupt function in the serial_lld.c file as follow

/**
 
 * @brief  Common RXI IRQ handler.
 
 *
 
 * @param[in] sdp    pointer to a @p SerialDriver object
 
 */
 
static void spc5xx_serve_rxi_interrupt(uint32_t isdp) {
 
 SerialDriver *sdp = (SerialDriver *) isdp;
 
 uint16_t sr = sdp->linflexlp->UARTSR.R;
 
 
 
 sdp->linflexlp->UARTSR.R = (uint16_t)(SPC5_UARTSR_NF | SPC5_UARTSR_DRF | SPC5_UARTSR_PE0);
 
 
 
 if ((sr & SPC5_UARTSR_DRF) == SPC5_UARTSR_DRF) {
 
  if(sdp->config->api_mode != SPC5_LIN_API_MODE_BUFFERED_IO) {
 
   *sdp->rx_buf = (uint8_t)sdp->linflexlp->BDRM.B.DATA4;
 
   //sdp->rx_buf++; // opistara 2021-02-17
 
   sdp->linflexlp->UARTSR.R = (uint16_t)SPC5_UARTSR_RMB;
 
   //sdp->rx_len--; // opistara 2021-02-17
 
   sdp->rx_len = 0; // opistara 2021-02-17
 
 
 
   if (sdp->rx_len == 0UL) {
 
    //sdp->linflexlp->UARTCR.B.RXEN = 0; // opistara 2021-02-17
 
    //sdp->linflexlp->LINIER.B.DRIE = 0; /* Interrupts disabled. */  // opistara 2021-02-17
 
    if (sdp->linflexlp->UARTCR.B.TXEN == 0UL) {
 
     sdp->linflexlp->LINIER.R &= ~((uint16_t)(SPC5_LIN_INTERRUPTS));
 
    }
 
    
 
    /* Call the related callback.*/
 
    if (sdp->config->rx_end_cb != NULL){
 
     sdp->config->rx_end_cb(sdp);
 
    }
 
    
 
    SPC5_LIN_RX_DONE(sdp);
 
   }
 
  } else {
 
   *sdp->rx_write_ptr = (uint8_t)sdp->linflexlp->BDRM.B.DATA4;
 
   sdp->rx_write_ptr++;
 
   if (sdp->rx_write_ptr == sdp->rx_end_ptr) {
 
    sdp->rx_write_ptr = sdp->rx_buffered_io;
 
   }
 
   if (sdp->rx_write_ptr == sdp->rx_read_ptr) {
 
    sdp->rx_read_ptr++;
 
    if (sdp->rx_read_ptr == sdp->rx_end_ptr) {
 
     sdp->rx_read_ptr = sdp->rx_buffered_io;
 
    }
 
   }
 
  }
 
 }
 
}
 

I attach both main.c and serial_ldd.c file.

/****************************************************************************
*
* Copyright © 2018-2019 STMicroelectronics - All Rights Reserved
*
* License terms: STMicroelectronics Proprietary in accordance with licensing
* terms SLA0089 at www.st.com.
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* EVALUATION ONLY – NOT FOR USE IN PRODUCTION
*****************************************************************************/
 
/* Inclusion of the main header files of all the imported components in the
   order specified in the application wizard. The file is generated
   automatically.*/
#include "components.h"
 
#include "serial_lld_cfg.h"
#include <string.h>
 
uint8_t typedChar[1] = " ";
char message[64];
char text[50];
 
 
void sddmatxcb(SerialDriver *sdp) {
  (void)sdp;
  pal_lld_togglepad(PORT_F, PF_LED1);
}
 
 
 
void sddmarxcb(SerialDriver *sdp) {
  (void)sdp;
  pal_lld_togglepad(PORT_F, PF_LED2);
  if (typedChar[0] == 33) strncpy (text, "", sizeof("")); //ascii code for ! is 33
  else strcat(text, (char *)typedChar);
}
 
 
 
 
/*
 * Application entry point.
 */
int main(void) {
 
 
  /* Initialization of all the imported components in the order specified in
     the application wizard. The function is generated automatically.*/
  componentsInit();
 
  /* Enable Interrupts */
  irqIsrEnable();
 
  /*
   * Activates the serial driver 1 using the driver default configuration.
   */
  sd_lld_start(&SD5, &serial_config_sddmacfg);
  (void)sd_lld_read(&SD5, typedChar, 1);
 
 
 
  /* Application main loop.*/
  for ( ; ; ) {
	strncpy (message, "\r\nType a char (! to clear Text) - Last char typed was:", sizeof("\r\nType a char (! to clear Text) - Last char typed was:"));//uint8_t message[]= "Hello World!\r\n";
    strcat(message, (char *)typedChar);
    strcat(message, "\r\nText: ");
 
    (void)sd_lld_write(&SD5, (uint8_t *) message, (uint16_t) strlen(message) );
 
    osalThreadDelayMilliseconds(100);
 
    (void)sd_lld_write(&SD5, (uint8_t *) text, (uint16_t) strlen(text) );
 
    osalThreadDelayMilliseconds(1500);
  }
}

I will check your feedback regarding the workaround adopted.

Thank you very much.

Erwan YVIN
ST Employee

Hello ,

Sorry for the late answer ;)

Good to see that your have solved your issue.

Adapt the driver is a good choice.

For the big project relative to collect some data coming from UART. (Near-space balloon, Automotive project and so on ..)

we are using :

  • Chibios / FreeRTOS threads to save CPU
  • some functions serial_input.c / .h with Runtime Components (cf Screenshot)

0693W000008GRgIQAW.png 

Best Regards

Erwan