interrupt condition in the example code

Thread Starter

yef smith

Joined Aug 2, 2020
750
Hello, for my EFR32FG14 controller An interupt is when we stop the main code to run a sub code.
In the example bellow our interrupt code is a function called USART1_TX_IRQHandler.

We have these two lines where NVIC_enable says that USART1_TX_IRQn is our interrupt function.
but i cant see in the code ,the codition we check before we are calling USART1_TX_IRQHandler.
How in the code i can see the codition in which we could know that USART1_TX_IRQHandler is about to be called?

Thanks.

Code:
  NVIC_ClearPendingIRQ(USART1_TX_IRQn);
    NVIC_EnableIRQ(USART1_TX_IRQn);
Code:
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"
#include "em_usart.h"
#include "em_ldma.h"

#define TX_BUFFER_SIZE   10
#define RX_BUFFER_SIZE   TX_BUFFER_SIZE

uint8_t TxBuffer[TX_BUFFER_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
uint32_t TxBufferIndex = 0;

uint8_t RxBuffer[RX_BUFFER_SIZE] = {0};
uint32_t RxBufferIndex = 0;

/**************************************************************************//**
 * @brief USART1 TX IRQ Handler
 *****************************************************************************/
void USART1_TX_IRQHandler(void)
{
  // Send and receive incoming data
  USART_Tx(USART1, TxBuffer[TxBufferIndex++]);

  // Stop sending once we've gone through the whole TxBuffer
  if (TxBufferIndex == TX_BUFFER_SIZE)
  {
    TxBufferIndex = 0;
  }
}

/**************************************************************************//**
 * @brief USART1 RX IRQ Handler
 *****************************************************************************/
void USART1_RX_IRQHandler(void)
{
  // Send and receive incoming data
  RxBuffer[RxBufferIndex++] = USART_Rx(USART1);

  // Stop once we've filled up our buffer
  if (RxBufferIndex == RX_BUFFER_SIZE)
  {
    // Place breakpoint here and observe RxBuffer
    // RxBuffer should contain 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9
    RxBufferIndex = 0;
  }
}

/**************************************************************************//**
 * @brief Initialize USART1
 *****************************************************************************/
void initUSART1 (void)
{
    CMU_ClockEnable(cmuClock_GPIO, true);
    CMU_ClockEnable(cmuClock_USART1, true);

    // Configure GPIO mode
    GPIO_PinModeSet(gpioPortC, 8, gpioModePushPull, 0); // US1_CLK is push pull
    GPIO_PinModeSet(gpioPortC, 9, gpioModePushPull, 1); // US1_CS is push pull
    GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); // US1_TX (MOSI) is push pull
    GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 1);    // US1_RX (MISO) is input

    // Start with default config, then modify as necessary
    USART_InitSync_TypeDef config = USART_INITSYNC_DEFAULT;
    config.master       = true;            // master mode
    config.baudrate     = 1000000;         // CLK freq is 1 MHz
    config.autoCsEnable = true;            // CS pin controlled by hardware, not firmware
    config.clockMode    = usartClockMode0; // clock idle low, sample on rising/first edge
    config.msbf         = true;            // send MSB first
    config.enable       = usartDisable;    // Make sure to keep USART disabled until it's all set up
    USART_InitSync(USART1, &config);

    // Set USART pin locations
    USART1->ROUTELOC0 = (USART_ROUTELOC0_CLKLOC_LOC11) | // US1_CLK       on location 11 = PC8 per datasheet section 6.4 = EXP Header pin 8
                        (USART_ROUTELOC0_CSLOC_LOC11)  | // US1_CS        on location 11 = PC9 per datasheet section 6.4 = EXP Header pin 10
                        (USART_ROUTELOC0_TXLOC_LOC11)  | // US1_TX (MOSI) on location 11 = PC6 per datasheet section 6.4 = EXP Header pin 4
                        (USART_ROUTELOC0_RXLOC_LOC11);   // US1_RX (MISO) on location 11 = PC7 per datasheet section 6.4 = EXP Header pin 6

    // Enable USART pins
    USART1->ROUTEPEN = USART_ROUTEPEN_CLKPEN | USART_ROUTEPEN_CSPEN | USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN;

    // Enabling TX interrupts to transfer whenever
    // there is room in the transmit buffer
    USART_IntClear(USART1, USART_IF_TXBL);
    USART_IntEnable(USART1, USART_IEN_TXBL);
    NVIC_ClearPendingIRQ(USART1_TX_IRQn);
    NVIC_EnableIRQ(USART1_TX_IRQn);

    // Enabling RX interrupts to trigger whenever
    // a new packet arrives from the slave
    USART_IntClear(USART1, USART_IF_RXDATAV);
    USART_IntEnable(USART1, USART_IEN_RXDATAV);
    NVIC_ClearPendingIRQ(USART1_RX_IRQn);
    NVIC_EnableIRQ(USART1_RX_IRQn);

    // Enable USART1
    USART_Enable(USART1, usartEnable);
}

/**************************************************************************//**
 * @brief Main function
 *****************************************************************************/
int main(void)
{
  // Initialize chip
  CHIP_Init();

  // Initialize USART1 as SPI master
  initUSART1();

  // After the USART is initialized transfers will automatically start based off of certain interrupt flag conditions
  // A new packet will be sent to the slave whenever the TX Buffer is empty after a previous successful transfer
  // and a packet will be sent from the slave back whenever it receives a packet from the master and will be handled
  // by the USART_RX_IRQHandler
  while(1);
}
 

BobTPH

Joined Jun 5, 2013
8,938
but i cant see in the code ,the codition we check before we are calling USART1_TX_IRQHandler.
That is the whole point of an interrupt! You don’t call the interrupt handler in the code, it is automatically called when some condition occurs. In the case of a UART, that condition is when a character has been received, or, for output, when the transmitter is ready for the next character.

Bob
 

Papabravo

Joined Feb 24, 2006
21,225
Hello BobPH,How do we know that our TXBL trigger is in such position that it will call the
USART1_TX_IRQHandle
It requires that your learn the hardware of the processor and examine the code in the "C Startup" file which is included by the linkage editor into each "C Program". You could also take it on faith, if you do not have the inclination or the ability to "go into the weeds".
 

Thread Starter

yef smith

Joined Aug 2, 2020
750
Hello PapaBravo, i want to gain the intuition regarding the TXBL,The manual says.
"When data has been moved from the TX buffer, the TXBL bit in the USARTn_STATUS register is set, indicating that a new transmit byte may be written "
We need to call our handle function in order to transmit which will causeTXBL trigger.
What causes the trigger to go high before we even sent some thing?
 

Papabravo

Joined Feb 24, 2006
21,225
Hello PapaBravo, i want to gain the intuition regarding the TXBL,The manual says.
"When data has been moved from the TX buffer, the TXBL bit in the USARTn_STATUS register is set, indicating that a new transmit byte may be written "
We need to call our handle function in order to transmit which will causeTXBL trigger.
What causes the trigger to go high before we even sent some thing?
In a receiver, an interrupt is SET, saying the RECEIVE DATA BUFFER is full.
In a transmitter, an interrupt is SET, When the TRANSMIT DATA BUFFER is empty. this happens BEFORE any data is sent. As soon as the TRANSMIT DATA BUFFER is loaded, it is moved to the TRANSMIT SHIFT REGISTER to be sent. This will take 10 or 11 bit times. So the TRANSMIT DATA BUFFER can be loaded again immediately. This is a traditional UART implementation. It can be improved with a TRANSMIT DATA FIFO. In this case you can load up the FIFO very quickly, much quicker than the data can be sent. At some point you have to wait for a vacant slot.

Sometimes you will get a TRANSMIT DATA BUFFER empty and there will be no data to go. In this case we disable the transmit interrupt and wait for data.
 
Top