Forum Discussion
How to implement mutual exclusion for critical sections in code?
Hi @CarlosAM_INTEL ,
I am using Altera Cyclone V SOC Development kit. I have modified the example code provided alongwith namely,
Altera-SoCFPGA-HardwareLib-16550-CV-ARMCC:
The interrupt callback function that writes data into the buffer is modified as below:
volatile unsigned int tail = 0;
volatile unsigned int head = 0;
char buffer[ALT_16550_BUFFER_PROVISION_RX_BUFFER_SIZE];
void recieveData(ALT_16550_BUFFER_t * buffer1)
{
#if ALT_16550_BUFFER_ENABLE_SMP
/* Signal we are in the RX section. */
buffer1->isr_rx = true;
#endif
ALT_STATUS_CODE status = ALT_E_SUCCESS;
uint32_t fifo_level_rx;
uint32_t copy_size;
if (status == ALT_E_SUCCESS)
{
status = alt_16550_fifo_level_get_rx(buffer1->handle, &fifo_level_rx);
}
if (status == ALT_E_SUCCESS)
{
/* Copy the RX FIFO into the RX buffer. */
// alt_16550_int_disable_rx(buffer.handle);
// alt_int_global_disable_all();
// portCPU_IRQ_DISABLE();
const unsigned int tail_1 = tail;
const unsigned int head_1 = head;
// portCPU_IRQ_ENABLE();
if(head_1 < tail_1) {
copy_size = stdminul(fifo_level_rx,tail_1 - head_1);
}else{
copy_size = stdminul(fifo_level_rx,ALT_16550_BUFFER_PROVISION_RX_BUFFER_SIZE - head_1);
}
alt_16550_fifo_read(buffer1->handle,&(buffer[head_1]), copy_size);
// portCPU_IRQ_DISABLE();
head = (head_1 + copy_size) % ALT_16550_BUFFER_PROVISION_RX_BUFFER_SIZE;
// portCPU_IRQ_ENABLE();
// alt_int_global_enable_all();
// alt_16550_int_enable_rx(buffer.handle);
/* Disable RX interrupts if the RX buffer is full. */
/* if ((tail == 0) && (head == ALT_16550_BUFFER_PROVISION_RX_BUFFER_SIZE))
{
status = alt_16550_int_disable_rx(buffer1->handle);
}*/
}
}
The function in main that reads bytes from the buffer is given below:
char readBuffer() {
portCPU_IRQ_DISABLE();
const unsigned int tail_1 = tail;
const unsigned int head_1 = head;
portCPU_IRQ_ENABLE();
if(tail_1 == head_1) {
return NULL;
}
const char data = rxBuffer.buffer[tail_1];
portCPU_IRQ_DISABLE();
tail = (tail_1+1) % ALT_16550_BUFFER_PROVISION_RX_BUFFER_SIZE;
portCPU_IRQ_ENABLE();
// alt_int_global_enable_all();
// alt_16550_int_enable_rx(buffer.handle);
// alt_int_global_enable();
return data;
}
#define portCPU_IRQ_DISABLE() \
__asm volatile ( "CPSID i"); \
__asm volatile ( "DSB" ); \
__asm volatile ( "ISB" );
#define portCPU_IRQ_ENABLE() \
__asm volatile ( "CPSIE i"); \
__asm volatile ( "DSB" ); \
__asm volatile ( "ISB" );
I wish to protect access of tail and head. The interrupt function is receiving the whole data. But when we read from the buffer, some bytes are lost ( almost half).