Honestly, I'm not absolutely sure whether the following is a bug, since I have not real hardware to my hand. But it kind of smells like one...
The interrupt vector USART_UDRE_vect of the mega328 seems to work differently in 1.0.0 (up to R941) compared to in SimulIDE 0.4.15 SR9. This vector should be jumped to, once UDR0 is empty and this vector is usually used to send data handled by interrupt.
In SimulIDE 0.4.15 SR9 the interrupt is activated once UDRIE0 is set and UDR0 is empty. This is also initially true.
For SimulIDE 1.0.0 it seems that the register has actively to be set to UDR0 = 0 before setting UDRIE0. Otherwise the interrupt will not get active.
Situation:
"Expected" result:
Shown result:
EDIT:
Another difference is, that in 1.0.0 the last space of the string str_1/str_2 gets sent twice. Simulide 0.4.15 SR9 sends it (correctly) only once.
The interrupt vector USART_UDRE_vect of the mega328 seems to work differently in 1.0.0 (up to R941) compared to in SimulIDE 0.4.15 SR9. This vector should be jumped to, once UDR0 is empty and this vector is usually used to send data handled by interrupt.
In SimulIDE 0.4.15 SR9 the interrupt is activated once UDRIE0 is set and UDR0 is empty. This is also initially true.
For SimulIDE 1.0.0 it seems that the register has actively to be set to UDR0 = 0 before setting UDRIE0. Otherwise the interrupt will not get active.
Situation:
- insert mega328 (set frequency to 8 MHz)
- flash hex (attached)
- open serial monitor
- run
"Expected" result:
- in prevoius versions: text "test_one " is output continuously on serial monitor
- sending letter "r" via serial monitor changes to text "test_two " as continuous output
Shown result:
- no text output, no output on pins
- receiving seems to work since byte 0x0118 toggles for send text "r" on serial monitor
- Writing 0 to UDR0 ahead of the while loop kind of solves the problem. However, this leads to sending an empty message (0x00) in the beginning, which has to be handled on the receiver side.
This work around can also be seen in the code below, marked in the comments.
EDIT:
Another difference is, that in 1.0.0 the last space of the string str_1/str_2 gets sent twice. Simulide 0.4.15 SR9 sends it (correctly) only once.
- Code:
#define F_CPU 8000000L
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#define UART_BUFFER_SIZE 10
#define BAUD_RATE 9600L
#define UBRR_VAL ((F_CPU+BAUD_RATE*8)/(BAUD_RATE*16)-1)
char uart_tx_buffer[UART_BUFFER_SIZE];
char str_1[] = "test_one ";
char str_2[] = "test_two ";
uint8_t str_flg = 0;
volatile uint8_t data_tx_finished_flg = 1;
int main ()
{ // set Baud rate
UBRR0H = UBRR_VAL >> 8;
UBRR0L = UBRR_VAL & 0xFF;
// activate send & transmit of 8 bit msgs
UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0);
UCSR0C = (1<<UCSZ00)| (1<<UCSZ01);
// UDR0 = 0; // =============>> this solves the problem in v1.0.0 <<================
// start interrupts
sei();
while(1)
{ // only in case of finished transfer
if (data_tx_finished_flg==1 )
{ // reset flag, choose text and activate sending
data_tx_finished_flg = 0;
if (str_flg ==0) strcpy(uart_tx_buffer, str_1);
else strcpy(uart_tx_buffer, str_2);
UCSR0B |= (1<<UDRIE0);
}
}
}
// once RX complete
ISR(USART_RX_vect)
{ // read data register and toogle str flag
char data = UDR0;
if (data=='r') str_flg = 1 - str_flg;
}
// once data register is empty
ISR(USART_UDRE_vect)
{ // set pointer to buffer and act_char to next character
static char* uart_tx_p = uart_tx_buffer;
char act_char = *uart_tx_p++;
// if character is 0
if (act_char==0 )
{ // deactivate sending, reset pointer and set finished flag
UCSR0B &= ~(1<<UDRIE0);
uart_tx_p = uart_tx_buffer;
data_tx_finished_flg = 1;
} // else set data register
else UDR0 = act_char;
}
- Attachments
- UART_interrupt.zip
- You don't have permission to download attachments.
- (1 Kb) Downloaded 1 times
Last edited by arcachofo on Tue Feb 15, 2022 12:33 am; edited 2 times in total (Reason for editing : Mark as solved (green color).)