2

I'm getting some problem and strange behave while try to read a complete string. I'm using a homemade demo board equipped with an atxmega32a4u and basically what i'd like to do is set a parameter (output voltage setpoint) through serial communication while the MCU does his stuff (control a buck converter and send back through serial some data as voltage and current ). Let's look at the code: here we have the main function

int main(void)
{   
osc_init();
PORTC_OUTSET = PIN7_bm; //Let's make PC7 as TX
PORTC_DIRSET = PIN7_bm; //TX pin as output

PORTC_OUTCLR = PIN6_bm;
PORTC_DIRCLR = PIN6_bm; //PC6 as RX

adc_init();
timer_init();
timer1_init();              //init all the peripheral
Serial_init();
stdout = stdin = &usart_str;

char l[100];


while (1) 
{

    if(!((USARTC1_STATUS & USART_RXCIF_bm)==0))
    {
        printf("**MAIN**\n");
        uart_getstring(l);
        printf("**DIGITATO %s **\n ",l);
    }
    printf("tensione: %f V corrente: %f A\n",v_bat,cur);
}

}

As you can see in the external while loop i just send back data with printf function (which works very good and gives me good formatted string to display in a serial monitor like the arduino ide ones). The nested loop starting when it find the USART_RXCIF flag setted, meaning that the incoming buffer is waiting to be read. Then it calls the uart_getstring() function which here we have:

void uart_getstring(char* line)
{   
int z=0;

while( !(USARTC1_STATUS & USART_RXCIF_bm) ); //Wait until data has been received.

char data='a';

while((data!='\r')){

        while( !(USARTC1_STATUS & USART_RXCIF_bm) );

        data = USARTC1_DATA; //Temporarly store received data
        printf("**GOT** %d carattere %c \n",z,data);

        line[z] = data;
        z++;

    }
    line[z]='\0';   
}

Please note that all the control stuff were made in a ISR function and serial is done in main loop without usart interrupt. However i also tried to disable all other process and running just the main function alone but got the same problem

So i tried this with the arduino ide's serial monitor which allow me to send command to the board and receive answer back. What happen is tricky, if i send a string just 1 or 2 char it works fine! But if i send a longer string it fails, it just send me back the string as it was of only 2 char. Lets see some example:

>> a
<<
**MAIN**
**GOT** 0 carattere a 
**GOT** 1 carattere  
**DIGITATO a **

>> aa
<<
**MAIN**
**GOT** 0 carattere a 
**GOT** 1 carattere a
**GOT** 2 carattere 
**DIGITATO aa **

and then if i send something longer it fails

>> fail
<<
**MAIN**
**GOT** 0 carattere f
**GOT** 1 carattere a
**GOT** 2 carattere 
**DIGITATO fa **

I also tried it through a python script and also just using the screen command but the result was ever the same. Any help would be appreciated. Thank you a lot

2 Answers2

0

Okey I got the answer by myself looking at the datasheet. It seems that the rx and tx buffer is shared, so i tried to comment out the debugging printf inside the function and it just worked! hope this could help someone however

  • Where in the datasheet did you read that? XMEGA UART is full duplex, I don't think a shared buffer is your problem. – Rev Sep 27 '18 at 08:35
  • Thank you very much for your reply Rev1.0! I sed that because in page 294 of datasheet, it says that the rx and tx buffer has the same addresses. I though this could make sense, however i'm not an advanced programmer and didn't know how the thing works really, just don't know what two-level FIFO means. However i noticed that by removing that printf things starts to work fine. I didn't though about what your suggested just because i can't fully understand how a string is transmitted! Isn't there any buffer (other than _DATA ones) that store data if the mcu is busy? Thank you – Nicola Barlabà Sep 28 '18 at 09:10
0

A shared received buffer is NOT your problem. The problem occurs, because the execution time of

printf("**GOT** %d carattere %c \n",z,data);

blocks the code for too long, while the rest of the string is being sent by the terminal. The XMEGA receive buffer consists of a two-level FIFO.

Lets take a look at the case where you tried to send "fail".

while((data!='\r')){

    // This blocks until the first char 'f' is received, which is OK.
    while( !(USARTC1_STATUS & USART_RXCIF_bm) );

    // At this point, 'f' is located in the DATA buffer.
    // The reception of the next char 'a' immediately starts next and is handled
    // by the UART receiver hardware.
    data = USARTC1_DATA; //Temporarly store received data

    // You just cleared the DATA buffer by reading it, so there is room for 'a'
    // after it has been received completely.

    // printf() blocks the code for a very long time
    printf("**GOT** %d carattere %c \n",z,data);

    // While you sent data using printf(), the terminal program sent the remaining
    // characters 'i' and 'l'. However, because DATA was already holding 'a' and
    // it wasn't cleared in between, the other chars got lost.

    line[z] = data;
    z++;

}

I hope this makes it clear.

Rev
  • 5,827
  • 4
  • 27
  • 51
  • Thank you very much for your reply Rev1.0! I sed that because in page 294 of datasheet, it says that the rx and tx buffer has the same addresses. I though this could make sense, however i'm not an advanced programmer and didn't know how the thing works really, just don't mean what double FIFO means. However i noticed that by removing that printf things starts to work fine. I didn't though about what your suggested just because i can't fully understand how a string is transmitted! Isn't there any buffer (other than _DATA ones) that store data if the mcu is busy? Thank you – Nicola Barlabà Sep 28 '18 at 09:02
  • 1
    They "share the same I/O address". But that isn't an issue in this case. Please consider accepting my answer or ask if you have further questions. – Rev Sep 28 '18 at 09:16
  • 1
    "Isn't there any buffer (other than DATA) that store data if the mcu is busy?" - That would be the FIFO, but as I pointed out, that is limited to storing one byte while receiving the next one. Other controllers may have bigger FIFO buffers. – Rev Sep 28 '18 at 09:18