3

I am having a problem with programming the serial for Arduino in C. The application demands speed, so I need to do it in C. I am using Codeblocks for it as it is easy to compile.

As I also want the serial feature not blocking the application and giving debug capability, I am trying to write a circular buffer type of serial library. The application does not need to receive data, only print.

The problem begins with the serial interrupt apparently not firing and the program blocks, the compiler does give a warning:

main.c|11|warning: ‘UART_UDRE_vect’ appears to be a misspelled signal handler|

The test program is as follows:

#include<avr/io.h>
#include<avr/interrupt.h>

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)

char ok = 0;

ISR(UART_UDRE_vect) {
    ok = 1;
    UCSR0B &= ~(1<<5);
}

int main(void) {
  UBRR0H  = (BAUD_PRESCALE >> 8);
  UBRR0L  = BAUD_PRESCALE;
  UCSR0B |= (1<<TXEN0);
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
  sei();
  while(1){
    // write the byte to the serial port
    UDR0 = '0';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
    UDR0 = '\n';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
  }
  return 0;
}

The configuration and baud rates are correct because the echo example found here does work.

Also other examples does not use UDRE, only RX interruption and that is not what I am looking for.

Am I forgetting something?

dda
  • 6,030
  • 2
  • 25
  • 34
BigFilhao
  • 157
  • 6
  • 15
  • I don't know this tool chain at all, but a common problem is forgetting to register the interrupt in the interrupt vector table. How is this done here? – Lundin Oct 30 '17 at 14:38
  • interrutions are listed in the avr interrupt.h library, as documented here: [link](http://www.atmel.com/webdoc/avrlibcreferencemanual/group__avr__interrupts.html) – BigFilhao Oct 30 '17 at 14:46
  • Arduino uses C++, does it not? – underscore_d Oct 30 '17 at 14:51
  • Ok. You particular AVR derivate is not listed below `UART_UDRE_vect`. Shouldn't it be named `USART_UDRE_vect `? – Lundin Oct 30 '17 at 14:51
  • Your handler should be named `USART_UDRE_vect` (or `USART0_UDRE_vect` or something). The warning tells you exactly that, that you misspelled it. – vgru Oct 30 '17 at 14:51
  • yes, just edited the question, but problem still remains, now it prints only the first character, "ok" is never set again – BigFilhao Oct 30 '17 at 14:53
  • 1
    Variables shared with an interrupt must be declared as `volatile` or the compiler might not understand that they are used and therefore break your program upon optimization. `static volatile char ok;` – Lundin Oct 30 '17 at 14:55
  • it worked! thanks a lot! – BigFilhao Oct 30 '17 at 14:58
  • I'll post that as answer then. – Lundin Oct 30 '17 at 14:59
  • I did a rollback of the question so that it contains the initial problem with the wrong vector name. In case anyone comes across the same problem in the future and finds this question. – Lundin Oct 30 '17 at 15:02

1 Answers1

1

Two problems:

  • According to the documentation you linked, the interrupt vector for your particular part ATmega328p should be named USART_UDRE_vect.

  • Variables shared with an interrupt must always be declared as volatile or the compiler might not understand that they are used and therefore break your program upon optimization. Basically the compiler thinks that the variable ok can never get another value than 0, since it doesn't see a function call to the ISR anywhere (since it is called by hardware, not by the program). Change the declaration to static volatile char ok;

Lundin
  • 195,001
  • 40
  • 254
  • 396