XMEGA32A4U RXCIF flag not being set

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <asf.h>
#include <string.h>

#define TEST_LED1 IOPORT_CREATE_PIN(PORTB, 2)
#define TEST_LED2 IOPORT_CREATE_PIN(PORTB, 3)
#define GSM_POWER_EN IOPORT_CREATE_PIN(PORTD, 0)
#define GSM_POWER_KEY IOPORT_CREATE_PIN(PORTD, 1)
#define CHRG_EN IOPORT_CREATE_PIN(PORTB, 0)
#define C_RXD0 IOPORT_CREATE_PIN(PORTC, 2)
#define C_TXD0 IOPORT_CREATE_PIN(PORTC, 3)

void usart_send(unsigned char *data);
void usart_receive(unsigned char *x, unsigned char size);

void usart_send(unsigned char *data)
{
 while(*data != '\0')
 {
  usart_putchar(USART_SERIAL, *data);
  while (!usart_tx_is_complete(USART_SERIAL)) {}
  usart_clear_tx_complete(USART_SERIAL);
  data++;
 }
}

void usart_receive(unsigned char *x, unsigned char size)
{
 unsigned char i = 0;

 if (size > 0) {
  while (i < size - 1) {              // check space is available (including additional null char at end)
   unsigned char c;
   c = (unsigned char) usart_getchar(USART_SERIAL);
   while (usart_rx_is_complete(USART_SERIAL)) {}
   usart_clear_rx_complete(USART_SERIAL);
   if (c == '\0') break;           // break on NULL character
   x[i] = c;                       // write into the supplied buffer
   i++;
  }
  x[i] = 0;                           // ensure string is null terminated
 }
}

int main (void)
{
 uint8_t init_command[] = "AT\r";
 unsigned char response_buf[10];
 bool powered_on = false;

 // Initialize board
 board_init();
 sysclk_init();
  
 // Disable interrupts
 if(pmic_level_is_enabled(PMIC_LVL_LOW)) pmic_disable_level(PMIC_LVL_LOW);
 if(pmic_level_is_enabled(PMIC_LVL_MEDIUM)) pmic_disable_level(PMIC_LVL_MEDIUM);
 if(pmic_level_is_enabled(PMIC_LVL_HIGH)) pmic_disable_level(PMIC_LVL_HIGH);
 
 if (cpu_irq_is_enabled()) cpu_irq_disable();
 
 // Enable IO service
 ioport_init();
 
 // Set TEST_LEDT1 as output
 ioport_set_pin_dir(TEST_LED1, IOPORT_DIR_OUTPUT);
 ioport_set_pin_dir(TEST_LED2, IOPORT_DIR_OUTPUT);
 
 // Enable GPS on MC 60
 ioport_set_pin_dir(GSM_POWER_EN, IOPORT_DIR_OUTPUT);
 ioport_set_pin_dir(GSM_POWER_KEY, IOPORT_DIR_OUTPUT);
 
 // Enable power and turn on MC 60
 ioport_set_value(GSM_POWER_EN, true);
 ioport_set_value(GSM_POWER_KEY, true);
  
 // Set USART pin direction
 ioport_set_pin_dir(C_RXD0, IOPORT_DIR_INPUT);
 ioport_set_pin_dir(C_TXD0, IOPORT_DIR_OUTPUT);
 
 // USART options
 static usart_rs232_options_t USART_SERIAL_OPTIONS = {
  .baudrate = USART_SERIAL_BAUDRATE,
  .charlength = USART_SERIAL_CHAR_LENGTH,
  .paritytype = USART_SERIAL_PARITY,
  .stopbits = USART_SERIAL_STOP_BIT
 };
 
 // Initialize USART
 usart_init_rs232(USART_SERIAL, &USART_SERIAL_OPTIONS);
 usart_set_rx_interrupt_level(USART_SERIAL, USART_INT_LVL_LO);
 usart_set_tx_interrupt_level(USART_SERIAL, USART_INT_LVL_OFF);

​ // Setup interrupt services
 pmic_init();
 cpu_irq_enable();
  
 while (true) {
  while (powered_on == false) {
   usart_send(init_command);
   usart_receive(response_buf, 10);
   if (strstr((char*)response_buf, "OK")) {
    powered_on = true;
    response_buf[0] = '\0';
   }
  }
  if (powered_on == true) {
   ioport_set_value(TEST_LED1, true);
  }
 }
}

ISR(USART_RX_Vect) {
 ioport_set_value(TEST_LED2 , true);
}

​I've highlighted the problematic rows. Basically the RXCIF flag is never being set in the STATUS register of the UART on PORT C. TX is fine. The XMEGA never exists the usart_receive function, because it's stuck in an infinite loop (usart_rx_is_complete is never true). This is the code for usart_rx_is_complete:

 

static inline bool usart_rx_is_complete(USART_t * usart)
{
 return (usart)->STATUS & USART_RXCIF_bm;
}

This is what the USART_RXCIF_bm looks in ASF:

 

#define USART_RXCIF_bm  0x80  /* Receive Interrupt Flag bit mask. */

​According to the datasheet: http://www.atmel.com/Images/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf (p. 294) the bit mask it right

​So I'm wondering, what might be wrong?

Last Edited: Mon. Oct 30, 2017 - 11:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Normally getchar() is a blocking function, i.e. it will not return until a char is received, so no need to test/clear the flag as it is handled for you.

 

Jim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Jim, thanks for the reply!

 

It is blocking and that's the problem. The flag is never set in the first place. If I read straight from the DATA register of the UART (USARTC0.DATA), I can get the characters, but if I call getchar() it never returns anything, because the RXCIF flag in the STATUS register is never set.

So the getchar() function looks something like this:

 

uint8_t usart_getchar(USART_t *usart) {
    while(usart_rx_is_complete(usart) == false) {}

​    return ((uint8_t)usart->DATA);
}

​The usart_rx_is_complete is checking if the flag is set, so it looks something like this:

 

bool usart_rx_is_complete(USART_t *usart) {
​    return (usart)->STATUS & USART_RXCIF_bm;
​}

It never returns true, stays as false and the while in the getchar() is looping forever.

Last Edited: Mon. Oct 30, 2017 - 01:58 PM