Here’s my implementation, in case someone needs something similar or in case someone wants to review and criticize.
On the ARM Side:
`
/////////////////////////////////////////////////////////////////////
// Ring buffer.
//
// Communication with PRU is through a ring buffer in the
// PRU shared memory area.
// shared_ram[0] to shared_ram[127] is the buffer data.
// shared_ram[128] is the start (read) pointer.
// shared_ram[129] is the end (write) pointer.
//
// Messages are 32 bit unsigned ints.
//
// Read these:
// * http://en.wikipedia.org/wiki/Circular_buffer#Use_a_Fill_Count
// * https://groups.google.com/forum/#!category-topic/beagleboard/F9JI8_vQ-mE
static volatile unsigned int* shared_ram = NULL;
void* p;
prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, &p);
shared_ram = (volatile unsigned int*)p;
unsigned int buffer_size;
volatile unsigned int *buffer_start;
volatile unsigned int *buffer_end;
void buffer_init(){
buffer_size = 128;
buffer_start = &(shared_ram[128]); // value inited to 0 in pru
buffer_end = &(shared_ram[129]); // value inited to 0 in pru
}
static inline int buffer_is_empty(){
return (*buffer_start == *buffer_end);
}
static inline void buffer_read(unsigned int* message){
*message = shared_ram[*buffer_start & (buffer_size-1)];
// Don’t write buffer start before reading message (mem barrier)
// http://stackoverflow.com/questions/982129/what-does-sync-synchronize-do
// https://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier
__sync_synchronize();
// Increment buffer start, wrap around size
*buffer_start = (buffer_start+1) & (2buffer_size - 1);
}
void main(){
buffer_init();
unsigned int message;
while(!buffer_is_empty()){
buffer_read(&message);
}
}
`
On the PRU side:
`
/////////////////////////////////////////////////////////////////////
// RING BUFFER
//
// Communication with ARM processor is througn a ring buffer in the
// PRU shared memory area.
// shared_ram[0] to shared_ram[127] is the buffer data.
// shared_ram[128] is the start (read) pointer.
// shared_ram[129] is the end (write) pointer.
//
// Messages are 32 bit unsigned ints.
//
// Read these:
// * http://en.wikipedia.org/wiki/Circular_buffer#Use_a_Fill_Count
// * https://groups.google.com/forum/#!category-topic/beagleboard/F9JI8_vQ-mE
volatile unsigned int* shared_ram = (volatile unsigned int *)0x10000;
unsigned int buffer_size;
volatile unsigned int *buffer_start;
volatile unsigned int *buffer_end;
void init_buffer(){
// data in shared_ram[0] to shared_ram[127]
buffer_size = 128;
buffer_start = &(shared_ram[128]);
buffer_end = &(shared_ram[129]);
*buffer_start = 0;
*buffer_end = 0;
}
inline void buffer_write(unsigned int message){
shared_ram[*buffer_end & (buffer_size-1)] = message;
unsigned int is_full = (*buffer_end == (*buffer_start^buffer_size)); // ^ is orex
if(is_full){
// Increment buffer start, wrap around size
*buffer_start = (buffer_start+1) & (2buffer_size - 1);
}
// Increment buffer end, wrap around size
*buffer_end = (buffer_end+1) & (2buffer_size - 1);
}
void main(){
buffer_init();
buffer_write(0xff0000ff);
buffer_write(0x11335577);
//…
}
`