I've been programming my atmega 328p to automate my coffe machine. The timer is set using the bluetooth module HC-06, or by a set of configuration buttons that I'm gonna develop yet (the full code is on my github: https://github.com/andrehrema/Cafeteira).
I've faced some problems with serial communication, so right now I'm trying to establish a communication between the microcontroller and my pc.
To send data I'm using putty and python with serial package, both with baudrate equal to 9600.
The data is stored in the queue buffer_rx_bth, and each queue's node is of type BT_node (BT = bluetooth).
The character '|' symbolyzes the end of the string and It allows the ATmega response.
Below is the piece of code used in UART communication:
#include<avr/io.h>
#include<avr/interrupt.h>
typedef struct node_BT BT_node;
typedef struct queue_BT_data BT_data;
struct node_BT{
char byte;
BT_node *next;
};
struct queue_BT_data{
BT_node *hd;
int index;
BT_node *tl;
};
volatile BT_data * add_inst(volatile BT_data *buffer_bth, char command){
BT_node *inst = malloc(sizeof(BT_node));
inst->byte = command;
if (buffer_bth->hd == 0){
buffer_bth->hd = inst;
buffer_bth->hd->next = 0;
buffer_bth->tl = buffer_bth->hd;
return buffer_bth;
}
else{
inst->next = buffer_bth->tl->next;
buffer_bth->tl->next = inst;
buffer_bth->tl = inst;
}
return buffer_bth;
}
volatile BT_data * remove_inst(volatile BT_data *buffer_bth){
while(buffer_bth->hd->byte != '|'){
BT_node *delete = buffer_bth->hd;
buffer_bth->hd=buffer_bth->hd->next;
free(delete);
}
BT_node *delete = buffer_bth->hd;
if(buffer_bth->hd == buffer_bth->tl)
buffer_bth->tl = buffer_bth->tl->next;
buffer_bth->hd=buffer_bth->hd->next;
free(delete);
return buffer_bth;
}
volatile BT_data *buffer_rx_bth;
ISR(USART_RX_vect){ //interruption handler
UCSR0B &= ~(1<<TXCIE0); // transmition interruption disabled
char result = UDR0;
buffer_rx_bth = add_inst(buffer_rx_bth, result);
UCSR0B |= (1<<TXCIE0); // transmition interruption enabled
}
int main (void){
buffer_rx_bth = malloc(sizeof(BT_data));
buffer_rx_bth->hd=0; // queue head
buffer_rx_bth->tl=0; // tail head
BT_node * pointer = 0;
while(1){
sei()
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
if (buffer_rx_bth->tl->byte == '|'){ //verify if it is the final character
if (pointer == 0){
PORTB ^= 4;
pointer = buffer_rx_bth->hd;
}
if ( (UCSR0A & (1<<UDRE0)) && pointer!=0){
UDR0 = pointer->byte;
if(pointer->byte == '|'){
remove_inst(buffer_rx_bth);
ponteiro = 0;
}
else
pointer = pointer->next;
}
}
}
When data is sent byte per byte, as shown below, the microcontroller send an equal response, as I expected.
import serial
uc = serial.Serial("/dev/ttyACM0",9600)
uc.write('A')
uc.write('B')
uc.write('C')
uc.write('|')
uc.stop()
response: ABC|
However, when more than one byte is sent, with the method write, the answer is completely random.
import serial
uc = serial.Serial("/dev/ttyACM0",9600)
uc.write("ABC|")
response: random string
Why is this happening? How can I solve it?
1 Answer 1
Most likely the malloc and free are not thread safe so you can't allocate in interrupt and free in main loop. In general, there should be no dynamic memory allocation in interrupts. At least you should disable receive interrupts when popping a byte from the linked list. And in general rarely there should be need for linked lists using dynamic allocation in AVR applications either. Just use a preallocated array as a ring buffer, it will be more efficient and can work from main and interrupt contexts. Also, there is no TX complete interrupt function anywhere in the code, yet the code disables and enables it in RX interrupt - it is possible it jumps to reset vector after transmitting each byte, so it works for single bytes every now and then.
-
\$\begingroup\$ thank you for your support. I've tried a couple of times using a fixed buffer length. But the problem persists. The full code is available on my github [github.com/andrehrema/Cafeteira ], if you prefer, you can try to compile and execute it. \$\endgroup\$André Machoski– André Machoski2020年01月30日 13:43:32 +00:00Commented Jan 30, 2020 at 13:43
pointer = pointer->prox;
do? \$\endgroup\$