Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

how to recognize interupt handler roots on register level of efr32fg14

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello, i have the following example code of interrupt handling for efr32fg14 with its reference manual and data sheet shown bellow.
I cant in this code the mechanism which says,"whenever interrupt rises call this "USART0_RX_IRQHandler" function.
The closest thing i found is NVIC_EnableIRQ(USART0_RX_IRQn); but its not calling USART0_RX_IRQHandler.
How does the controller knows to call specifically USART0_RX_IRQHandler when interrupt flag rises?
Thanks.


Code:
/***************************************************************************//**
* @file main_xg1_xg12_xg13_xg14.c
* @brief This project reads input on the UART RX port and echoes it back to the
* TX port one line at a time. It does not use the VCOM or stdio. See readme.txt
* for details.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*******************************************************************************
* # Evaluation Quality
* This code has been minimally tested to ensure that it builds and is suitable
* as a demonstration for evaluation purposes only. This code will be maintained
* at the sole discretion of Silicon Labs.
******************************************************************************/

#include "em_device.h"
#include "em_chip.h"
#include "em_emu.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"

#include "bsp.h"

// Size of the buffer for received data
#define BUFLEN  80

// Receive data buffer
uint8_t buffer[BUFLEN];

// Current position ins buffer
uint32_t inpos = 0;
uint32_t outpos = 0;

// True while receiving data (waiting for CR or BUFLEN characters)
bool receive = true;

/**************************************************************************//**
* @brief
*    GPIO initialization
*****************************************************************************/
void initGpio(void)
{
  CMU_ClockEnable(cmuClock_GPIO, true);

  // Configure VCOM transmit pin to board controller as an output
  GPIO_PinModeSet(BSP_BCC_TXPORT, BSP_BCC_TXPIN, gpioModePushPull, 1);

  // Configure VCOM reeive pin from board controller as an input
  GPIO_PinModeSet(BSP_BCC_RXPORT, BSP_BCC_RXPIN, gpioModeInput, 0);

  // Enable VCOM connection to board controller
  GPIO_PinModeSet(BSP_BCC_ENABLE_PORT, BSP_BCC_ENABLE_PIN, gpioModePushPull, 1);
}

/**************************************************************************//**
* @brief
*    USART0 initialization (VCOM on xG1/xG12/xG13 boards)
*****************************************************************************/
void initUsart0(void)
{
  CMU_ClockEnable(cmuClock_USART0, true);

  // Default asynchronous initializer (115.2 Kbps, 8N1, no flow control)
  USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;

  // Configure and enable USART0
  USART_InitAsync(USART0, &init);

  // Enable NVIC USART sources
  NVIC_ClearPendingIRQ(USART0_RX_IRQn);
  NVIC_EnableIRQ(USART0_RX_IRQn);
  NVIC_ClearPendingIRQ(USART0_TX_IRQn);
  NVIC_EnableIRQ(USART0_TX_IRQn);

  // Enable RX and TX for USART0 VCOM connection
  USART0->ROUTELOC0 = BSP_BCC_RX_LOCATION | BSP_BCC_TX_LOCATION;
  USART0->ROUTEPEN |= USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
}

/**************************************************************************//**
* @brief
*    The USART0 receive interrupt saves incoming characters.
*****************************************************************************/
void USART0_RX_IRQHandler(void)
{
  // Get the character just received
  buffer[inpos] = USART0->RXDATA;

  // Exit loop on new line or buffer full
  if ((buffer[inpos] != '\r') && (inpos < BUFLEN))
    inpos++;
  else
    receive = false;   // Stop receiving on CR

  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_RXDATAV);
}

/**************************************************************************//**
* @brief
*    The USART0 transmit interrupt outputs characters.
*****************************************************************************/
void USART0_TX_IRQHandler(void)
{
  // Send a previously received character
  if (outpos < inpos)
    USART0->TXDATA = buffer[outpos++];
  else
  /*
   * Need to disable the transmit buffer level interrupt in this IRQ
   * handler when done or it will immediately trigger again upon exit
   * even though there is no data left to send.
   */
  {
    receive = true;   // Go back into receive when all is sent
    USART_IntDisable(USART0, USART_IEN_TXBL);
  }
  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_TXBL);
}

/**************************************************************************//**
* @brief
*    Main function
*****************************************************************************/
int main(void)
{
  uint32_t i;

  // Chip errata
  CHIP_Init();

  // Initialize GPIO and USART0
  initGpio();
  initUsart0();

  while (1)
  {
    // Zero out buffer
    for (i = 0; i < BUFLEN; i++)
      buffer[i] = 0;

    // Enable receive data valid interrupt
    USART_IntEnable(USART0, USART_IEN_RXDATAV);

    // Wait in EM1 while receiving to reduce current draw
    while (receive)
      EMU_EnterEM1();

    // Disable receive data valid interrupt
    USART_IntDisable(USART0, USART_IEN_RXDATAV);

    // Enable transmit buffer level interrupt
    USART_IntEnable(USART0, USART_IEN_TXBL);

    // Wait in EM1 while transmitting to reduce current draw
    while (!receive)
      EMU_EnterEM1();

    // Reset buffer indices
    inpos = outpos = 0;
  }
}
 

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
18,391
Helped
4,104
Reputation
8,208
Reaction score
4,037
Trophy points
113
Activity points
121,080
Hi,

there is not a single interrupt, there are many.
One is the: Interrupt that is raised from UART0 when new character is recieved.

Now it depends on your IDE, compiler, libraries...

I assume that "USART0_RX_IRQHandler" is the fixed keyword for the compiler to know which function to call in case of a UART0 Rx interrupt.
(Thus you don´t find this keyword in microcontroller documentation. More information can be found in the em_usart.h, em_usart.c and it´s documentation)

So you don´t need to do anything (besides correct spelling of the keyword). No need for an extra "call"...
..if interrupts are enabled the microcontroller will process the function when an according interrupt occurs.

Klaus
--- Updated ---

Added:
out of curiosity I´ve just done an internet search on "USART0_RX_IRQHandler".
The first results are SILABS USART tutorials and SILABS forum topics.

I wonder why you don´t do such a simple search on your own...

Klaus
 
Last edited:

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello Klauss ,i have done research about it and i came to the conclution that its about the name of the function.
There are functions names like NVIC_ClearPendingIRQ , NVIC_EnableIRQ , USART0_RX_IRQHandler. i cant see the dynamics of those names.how they work together?
Is there some total manual for the dinamics of those names?
Thanks.
 
Last edited:

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
18,391
Helped
4,104
Reputation
8,208
Reaction score
4,037
Trophy points
113
Activity points
121,080
Hi,

the problem is with these NVIC_EnableIRQ(USART0_RX_IRQn) functions i just thought there is some "Core" explanation i could see beyong the registers.
I don´t know exactly what you mean...
But you may have a look at the .lst file to see the assembler code that the compiler generates from your source code.

Klaus
 

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello Klauss, i understand that its the dynamics of this names
NVIC_ClearPendingIRQ , NVIC_EnableIRQ , USART0_RX_IRQHandler.
i cant see the dynamics of them .how they work together?
Is there some manual regarding all of them, so i could see the logic behind using them together?
THanks.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,644
Helped
14,072
Reputation
28,401
Reaction score
12,739
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,823
In case you are using SimplicityStudio, you can find the interrupt vectors set up by the start-up code in the project configuration under __Vectors.

1603367442126.png
 
  • Like
Reactions: yefj

    yefj

    points: 2
    Helpful Answer Positive Rating

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello Fvm, Yes i am using simplisity studio.
Is there some manual regarding them?
Thanks.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,644
Helped
14,072
Reputation
28,401
Reaction score
12,739
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,823
A lot of online and web help, rather too much than too few documents.

Your question is referring to basic ARM Cortex stuff, not specific to Silabs or SimplicityStudio. You should understand how interrupt vectors are used in ARM Cortex, what is CMSIS. See e.g. https://docs.silabs.com/cmsis/latest/
 

    yefj

    points: 2
    Helpful Answer Positive Rating

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello FvM, I want to learn NVIC interrupt based on simplisity studio arm cortex 4 efr32fg14 proccessor.

In the link you gave bellow it very brief i cant see the NVIC_ClearPendingIRQ , NVIC_EnableIRQ , USART0_RX_IRQHandler in there.
Could you please navigate me to a more specific place where i could see them in the manual?
So i could know from where to start and connect the dots to these function names.
Thanks.

--- Updated ---

I have found some more precise documents.
Thanks.
 
Last edited:

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello FvM,based on the ARM CORTEX manual shown bellow page 277 and ISR naming shown bellow.
We need to Enable the interrupt and to set its priority
So we need to use USART RX interrupt which is USART0_RX_IRQn



Thanks.





1603459409573.png

1603459659289.png
 
Last edited:

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,644
Helped
14,072
Reputation
28,401
Reaction score
12,739
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,823
Typically you don't need to adjust the interrupt priorities, just use the default settings.

I suggest to look through the exercises and devkit examples shipped with every SimplicityStudio installation. They focus on the appropriate steps to make things working.

A general point, interrupt controller is an ARM Cortex core function, which isn't described in detail in the processor reference manuals.

NVIC_EnableIRQ() isn't but a C macro.
C:
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
  NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
}
Referring to
C:
/**
  \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).
 */
typedef struct
{
  __IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */
        uint32_t RESERVED0[24U];
  __IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */
        uint32_t RSERVED1[24U];
  __IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */
        uint32_t RESERVED2[24U];
  __IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */
        uint32_t RESERVED3[24U];
  __IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */
        uint32_t RESERVED4[56U];
  __IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
        uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
}  NVIC_Type;

/* Memory mapping of Cortex-M4 Hardware */
#define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address */
#define ITM_BASE            (0xE0000000UL)                            /*!< ITM Base Address */
#define DWT_BASE            (0xE0001000UL)                            /*!< DWT Base Address */
#define TPI_BASE            (0xE0040000UL)                            /*!< TPI Base Address */
#define CoreDebug_BASE      (0xE000EDF0UL)                            /*!< Core Debug Base Address */
#define SysTick_BASE        (SCS_BASE +  0x0010UL)                    /*!< SysTick Base Address */
#define NVIC_BASE           (SCS_BASE +  0x0100UL)                    /*!< NVIC Base Address */
#define SCB_BASE            (SCS_BASE +  0x0D00UL)                    /*!< System Control Block Base Address */

#define SCnSCB              ((SCnSCB_Type    *)     SCS_BASE      )   /*!< System control Register not in SCB */
#define SCB                 ((SCB_Type       *)     SCB_BASE      )   /*!< SCB configuration struct */
#define SysTick             ((SysTick_Type   *)     SysTick_BASE  )   /*!< SysTick configuration struct */
#define NVIC                ((NVIC_Type      *)     NVIC_BASE     )   /*!< NVIC configuration struct */
#define ITM                 ((ITM_Type       *)     ITM_BASE      )   /*!< ITM configuration struct */
#define DWT                 ((DWT_Type       *)     DWT_BASE      )   /*!< DWT configuration struct */
#define TPI                 ((TPI_Type       *)     TPI_BASE      )   /*!< TPI configuration struct */
#define CoreDebug           ((CoreDebug_Type *)     CoreDebug_BASE)   /*!< Core Debug configuration struct */
 

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello FvM, in the example code bellow we have NVIC_ClearPendingIRQ(USART0_TX_IRQn);
which from page 220 in the manual enables USART_TX interrupt.
But later on in teh code we have
Code:
    // Enable transmit buffer level interrupt

    USART_IntEnable(USART0, USART_IEN_TXBL);
Which means enable the enable the TXBL flag.
So it seems we are anabling the same thing twice,
What is the difference between the two enables,why do we need to enable twice?

1603470443341.png
1603471294879.png
Code:
#include "em_device.h"
#include "em_chip.h"
#include "em_emu.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"

#include "bsp.h"

// Size of the buffer for received data
#define BUFLEN  80

// Receive data buffer
uint8_t buffer[BUFLEN];

// Current position ins buffer
uint32_t inpos = 0;
uint32_t outpos = 0;

// True while receiving data (waiting for CR or BUFLEN characters)
bool receive = true;

/**************************************************************************//**
 * @brief
 *    GPIO initialization
 *****************************************************************************/
void initGpio(void)
{
  CMU_ClockEnable(cmuClock_GPIO, true);

  // Configure VCOM transmit pin to board controller as an output
  GPIO_PinModeSet(BSP_BCC_TXPORT, BSP_BCC_TXPIN, gpioModePushPull, 1);

  // Configure VCOM reeive pin from board controller as an input
  GPIO_PinModeSet(BSP_BCC_RXPORT, BSP_BCC_RXPIN, gpioModeInput, 0);

  // Enable VCOM connection to board controller
  GPIO_PinModeSet(BSP_BCC_ENABLE_PORT, BSP_BCC_ENABLE_PIN, gpioModePushPull, 1);
}

/**************************************************************************//**
 * @brief
 *    USART0 initialization (VCOM on xG1/xG12/xG13 boards)
 *****************************************************************************/
void initUsart0(void)
{
  CMU_ClockEnable(cmuClock_USART0, true);

  // Default asynchronous initializer (115.2 Kbps, 8N1, no flow control)
  USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;

  // Configure and enable USART0
  USART_InitAsync(USART0, &init);

  // Enable NVIC USART sources
  NVIC_ClearPendingIRQ(USART0_RX_IRQn);
  NVIC_EnableIRQ(USART0_RX_IRQn);
  NVIC_ClearPendingIRQ(USART0_TX_IRQn);
  NVIC_EnableIRQ(USART0_TX_IRQn);


  USART0->ROUTEPEN |= USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
}


void USART0_RX_IRQHandler(void)
{
  // Get the character just received
  buffer[inpos] = USART0->RXDATA;

  // Exit loop on new line or buffer full
  if ((buffer[inpos] != '\r') && (inpos < BUFLEN))
    inpos++;
  else
    receive = false;   // Stop receiving on CR

  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_RXDATAV);
}

/**************************************************************************//**
 * @brief
 *    The USART0 transmit interrupt outputs characters.
 *****************************************************************************/
void USART0_TX_IRQHandler(void)
{
  // Send a previously received character
  if (outpos < inpos)
    USART0->TXDATA = buffer[outpos++];
  else
  /*
   * Need to disable the transmit buffer level interrupt in this IRQ
   * handler when done or it will immediately trigger again upon exit
   * even though there is no data left to send.
   */
  {
    receive = true;   // Go back into receive when all is sent
    USART_IntDisable(USART0, USART_IEN_TXBL);
  }
  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_TXBL);
}

/**************************************************************************//**
 * @brief
 *    Main function
 *****************************************************************************/
int main(void)
{
  uint32_t i;

  // Chip errata
  CHIP_Init();

  // Initialize GPIO and USART0
  initGpio();
  initUsart0();

  while (1)
  {
    // Zero out buffer
    for (i = 0; i < BUFLEN; i++)
      buffer[i] = 0;

    // Enable receive data valid interrupt
    USART_IntEnable(USART0, USART_IEN_RXDATAV);

    // Wait in EM1 while receiving to reduce current draw
    while (receive)
      EMU_EnterEM1();

    // Disable receive data valid interrupt
    USART_IntDisable(USART0, USART_IEN_RXDATAV);

    // Enable transmit buffer level interrupt
    USART_IntEnable(USART0, USART_IEN_TXBL);

    // Wait in EM1 while transmitting to reduce current draw
    while (!receive)
      EMU_EnterEM1();

    // Reset buffer indices
    inpos = outpos = 0;
  }
}
--- Updated ---

Hello FVM , if i understand correctly the code example , enabling USART0_TX_IRQn is more general and by enabling USART_IEN_TXBL we get more specific.
Where can i see this link between the two?


is there some specific diagram i can see to see more "general" enable "and more "spesific" enable?
Thanks.

// Enable transmit buffer level interrupt
USART_IntEnable(USART0, USART_IEN_TXBL);

and
NVIC_EnableIRQ(USART0_TX_IRQn);
 
Last edited:

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Update :
I think its like two doors that we need a key for both of them in order to passthrew.
The key is the enable which allows to use the interupts in from usrt_IEN we need also to enable USART0_TX_IRQn and USART0_RX_IRQn.



Thanks
1603487234199.png
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,644
Helped
14,072
Reputation
28,401
Reaction score
12,739
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,823
A global USART interrupt enable and 17 specific interrupt trigger criteria. What's unclear about it?
 

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello FvM,correct me if i am wrong ,what you call a GLOBAL USART interapt enable is actually has nothing to do with efr32fg14 peripheries,
Its the Cortex-M4 property for allowing USART0_TX_IRQn in NVIC.

Thanks.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
47,644
Helped
14,072
Reputation
28,401
Reaction score
12,739
Trophy points
1,393
Location
Bochum, Germany
Activity points
276,823
Yes, both must be enabled to allow interrupts to occur.
 
  • Like
Reactions: yefj

    yefj

    points: 2
    Helpful Answer Positive Rating

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
18,391
Helped
4,104
Reputation
8,208
Reaction score
4,037
Trophy points
113
Activity points
121,080
Hi,

It may seem to make no sense now. But after you programmed a couple of applications you will see it makes sense.
You decide which functions you want to be interrupt driven. According this you enable the induvidual UART interrupts.
This is done once per application. It needs to be set up once during start up.
But you may enable/disable UART during runtime. For example when you are very busy with other stuff and don't want
to be interrupted, then the global UART_interrupt_enable may be useful.

Klaus
 
  • Like
Reactions: yefj

    yefj

    points: 2
    Helpful Answer Positive Rating

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello , In the example code shown bellow we have certian interrupt dinamics.
In the MAIN function we clear and enable the TX RX cortex-M interupts which is fine.
But in the interupt handlers we clear the interrupts and we set them again in the while(1) loop in MAIN.

Why are we doing this constand clear and set of the interrupt?
Its supposed to be always set and to execute the handler when ever we recieve data.

Maybe I think its like an alarm clock that goes ON,and in order to stay alert for the next data stream we need to turn the alarm off and to set it ready in case we got a new one coming.
Correct?

Thanks.
Code:
#include "em_device.h"
#include "em_chip.h"
#include "em_emu.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"

#include "bsp.h"

// Size of the buffer for received data
#define BUFLEN  80

// Receive data buffer
uint8_t buffer[BUFLEN];

// Current position ins buffer
uint32_t inpos = 0;
uint32_t outpos = 0;

// True while receiving data (waiting for CR or BUFLEN characters)
bool receive = true;

/**************************************************************************//**
 * @brief
 *    GPIO initialization
 *****************************************************************************/
void initGpio(void)
{
  CMU_ClockEnable(cmuClock_GPIO, true);

  // Configure VCOM transmit pin to board controller as an output
  GPIO_PinModeSet(BSP_BCC_TXPORT, BSP_BCC_TXPIN, gpioModePushPull, 1);

  // Configure VCOM reeive pin from board controller as an input
  GPIO_PinModeSet(BSP_BCC_RXPORT, BSP_BCC_RXPIN, gpioModeInput, 0);

  // Enable VCOM connection to board controller
  GPIO_PinModeSet(BSP_BCC_ENABLE_PORT, BSP_BCC_ENABLE_PIN, gpioModePushPull, 1);
}

/**************************************************************************//**
 * @brief
 *    USART0 initialization (VCOM on xG1/xG12/xG13 boards)
 *****************************************************************************/
void initUsart0(void)
{
  CMU_ClockEnable(cmuClock_USART0, true);

  // Default asynchronous initializer (115.2 Kbps, 8N1, no flow control)
  USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;

  // Configure and enable USART0
  USART_InitAsync(USART0, &init);

  // Enable NVIC USART sources
  NVIC_ClearPendingIRQ(USART0_RX_IRQn);
  NVIC_EnableIRQ(USART0_RX_IRQn);
  NVIC_ClearPendingIRQ(USART0_TX_IRQn);
  NVIC_EnableIRQ(USART0_TX_IRQn);

  // Enable RX and TX for USART0 VCOM connection
  USART0->ROUTELOC0 = BSP_BCC_RX_LOCATION | BSP_BCC_TX_LOCATION;
  USART0->ROUTEPEN |= USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
}

/**************************************************************************//**
 * @brief
 *    The USART0 receive interrupt saves incoming characters.
 *****************************************************************************/
void USART0_RX_IRQHandler(void)
{
  // Get the character just received
  buffer[inpos] = USART0->RXDATA;

  // Exit loop on new line or buffer full
  if ((buffer[inpos] != '\r') && (inpos < BUFLEN))
    inpos++;
  else
    receive = false;   // Stop receiving on CR

  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_RXDATAV);
}

/**************************************************************************//**
 * @brief
 *    The USART0 transmit interrupt outputs characters.
 *****************************************************************************/
void USART0_TX_IRQHandler(void)
{
  // Send a previously received character
  if (outpos < inpos)
    USART0->TXDATA = buffer[outpos++];
  else
  /*
   * Need to disable the transmit buffer level interrupt in this IRQ
   * handler when done or it will immediately trigger again upon exit
   * even though there is no data left to send.
   */
  {
    receive = true;   // Go back into receive when all is sent
    USART_IntDisable(USART0, USART_IEN_TXBL);
  }
  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_TXBL);
}

/**************************************************************************//**
 * @brief
 *    Main function
 *****************************************************************************/
int main(void)
{
  uint32_t i;

  // Chip errata
  CHIP_Init();

  // Initialize GPIO and USART0
  initGpio();
  initUsart0();

  while (1)
  {
    // Zero out buffer
    for (i = 0; i < BUFLEN; i++)
      buffer[i] = 0;

    // Enable receive data valid interrupt
    USART_IntEnable(USART0, USART_IEN_RXDATAV);

    // Wait in EM1 while receiving to reduce current draw
    while (receive)
      EMU_EnterEM1();

    // Disable receive data valid interrupt
    USART_IntDisable(USART0, USART_IEN_RXDATAV);

    // Enable transmit buffer level interrupt
    USART_IntEnable(USART0, USART_IEN_TXBL);

    // Wait in EM1 while transmitting to reduce current draw
    while (!receive)
      EMU_EnterEM1();

    // Reset buffer indices
    inpos = outpos = 0;
  }
}
 

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
18,391
Helped
4,104
Reputation
8,208
Reaction score
4,037
Trophy points
113
Activity points
121,080
Hi,

in main loop they switch between "receiving" and "transmitting".
This may be useful for half duplex communication(like RS485) in transmit mode to avoid the hardware echo to cause a receive interrupt.

For full duplex communication I see no need to ENABLE/DISABLE the interrupt.
--> Try to enable both interrrupts before the while(1) loop and see what happens.

Another reason may be that both ISRs use the same buffer. So during data transmit...when a byte is received it will corrupt buffer content.
If so, there are better techniques, like using two buffers that get interchanged after every receive_complete. And the use of DMA, which does not need processing within an ISR. But most probably the code is written just as basic function example.


Klaus
 

yefj

Full Member level 5
Joined
Sep 12, 2019
Messages
316
Helped
0
Reputation
0
Reaction score
1
Trophy points
18
Activity points
1,641
Hello Klauss, I have tried to implement even simpler case
where ,in a case i send "a" the controller sends back 0F in endless loop
in a case i send "b" the controller sends back 1F in endless loop
in a case i send "c" the controller sends back 2F in endless loop

The program keeps sending the old value over and over(with small delay) till it gets a new command.
In reality when i sent a command letters it sent back nothing.
Where did i go wrong implemeting the RX interrupt?
Thanks.

Code:
#include "em_device.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "em_chip.h"
#include <stdint.h>
#include <stdbool.h>
#include "em_emu.h"
#include "bsp.h"
#include "bsp_trace.h"



// Receive data buffer
uint8_t buffer;
uint8_t tx_buffer;



void USART0_RX_IRQHandler(void)
{
  // Get the character just received
  buffer = USART0->RXDATA;

  switch (buffer)
        {
        case 'a':

            tx_buffer=0x0F;
          break;

        case 'b':
            tx_buffer=0x2F;
        break;

        case 'c':
                    tx_buffer=0x4F;
         break;

        default:

        break;

        }//end switch
  // Clear the requesting interrupt before exiting the handler
  USART_IntClear(USART0, USART_IF_RXDATAV);
}



int main(void)
{
  uint32_t i;

  // Chip errata
  CHIP_Init();
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_USART0, true);


  //EFR32fg14 LOC2 page 157 data sheet TX P0
  GPIO_PinModeSet(gpioPortA,2, gpioModePushPull, 1);

//EFR32fg14 LOC2 page 157 data sheet RX P2
  GPIO_PinModeSet(gpioPortA,3, gpioModeInput, 0);

  GPIO_PinModeSet(gpioPortA, 5, gpioModePushPull, 1);


  // Default asynchronous initializer (115.2 Kbps, 8N1, no flow control)
  USART_InitAsync_TypeDef init = USART_INITASYNC_DEFAULT;

  // Configure and enable USART0
  USART_InitAsync(USART0, &init);
  //datasheet page 157 location2  rx portA pin3(P2) ,tx port A pin2(P0)
  USART0->ROUTELOC0 = USART_ROUTELOC0_RXLOC_LOC2 | USART_ROUTELOC0_TXLOC_LOC2;
  USART0->ROUTEPEN |= USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;


  // Enable NVIC USART sources
  NVIC_ClearPendingIRQ(USART0_RX_IRQn);
  NVIC_EnableIRQ(USART0_RX_IRQn);
  NVIC_ClearPendingIRQ(USART0_TX_IRQn);
  NVIC_EnableIRQ(USART0_TX_IRQn);


  while (1)
  {

      USART_Tx(USART0,tx_buffer);
      USART_Tx(USART1,'\n');
      for(i=0;i<115;i++)//delay loop
      {
            GPIO_PinOutSet(gpioPortA,5);
            GPIO_PinOutClear(gpioPortA,5);
       }

    // Enable receive data valid interrupt
    USART_IntEnable(USART0, USART_IEN_RXDATAV);







  }
}
 
Last edited:

Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top