How to exchange data between host C prog and PRU C prog?

My objective is to poll sensor output using GPIO and process the data. The CPU is missing some of the pulses from sensor while processing the previous data. My idea is to use PRU to count the sensor pulses and provide the counter value to CPU using shared memory. I am using C code for PRU after installing ti-pru-cgt-installer, the PRU-C code has to write the counter data at some memory location after each pulse from sensor so that host C-prog will be able to read the data whenever it is free.

Given below is a PRU-C code which generates a square wave and user-LED blinking of 20 cycles

#include <stdint.h>
#include <pru_cfg.h>
#include <gpio_v2.h>
#include <soc_AM335x.h>
#include <gpio_v2.c>

#define PRU0_ARM_INTERRUPT 19 // Interrupt used for halt signal

#define GPIO1 (*(volatile unsigned long )(0x4804c000)) // The address of the GPIO1
#define GPIO_INSTANCE_ADDRESS0 (SOC_GPIO_0_REGS)
#define GPIO_INSTANCE_ADDRESS1 (SOC_GPIO_1_REGS)
#define GPIO_INSTANCE_ADDRESS2 (SOC_GPIO_2_REGS)
#define GPIO_INSTANCE_ADDRESS3 (SOC_GPIO_3_REGS)
#define SYSCFG (
(&C4+0x01))
int C4 attribute((cregister(“CFG”,near),peripheral)); //only compatible with v1.1.0B1 +
//add following lines to MEMORY{} in lnk.cmd
//PAGE 2:
// MEM : o = 0x00026000 l = 0x00002000 CREGISTER=4
volatile register uint32_t __R30;
volatile register uint32_t __R31;

/* Mapping Constant table register to variable */
volatile pruCfg CT_CFG attribute((cregister(“CFG”, near), peripheral));

void main(){
volatile uint32_t gpio;
int i=0,j=1;

/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

/Intialise OCP Master port for accessing external memories/
SYSCFG&=0xFFFFFFEF;

/* Toggle GPO pins TODO: Figure out which to use /
gpio = 1<<2; //p9_30
// Just a test to show how you can use assembly instructions directly
// subtract 1 from REG1
/
asm volatile
(
" SUB r1, r1, 1 \n"
);*/

/* TODO: Create stop condition, else it will toggle indefinitely */
while(j<20){
//__R30 ^= gpio;
__R30 = 0<<2;
//GPIOPinWrite(GPIO_INSTANCE_ADDRESS3, 16, GPIO_PIN_LOW);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 21, GPIO_PIN_LOW);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 22, GPIO_PIN_LOW);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 23, GPIO_PIN_LOW);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 24, GPIO_PIN_LOW);
i++;

//GPIOPinWrite(GPIO_INSTANCE_ADDRESS, 16, GPIO_PIN_LOW);
//__R30 = __R30 | 1<<2;
//for(j=0;j<5000000;j++);
//__delay_cycles(50000000);
//GPIOPinWrite(GPIO_INSTANCE_ADDRESS, 16, GPIO_PIN_HIGH);
//__R30 = __R30 & 0<<2;
//for(j=0;j<5000000;j++);
__delay_cycles(50000000);
//__R30 ^= gpio;
__R30 = 1<<2;
//GPIOPinWrite(GPIO_INSTANCE_ADDRESS3, 16, GPIO_PIN_HIGH);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 21, GPIO_PIN_HIGH);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 22, GPIO_PIN_HIGH);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 23, GPIO_PIN_HIGH);
GPIOPinWrite(GPIO_INSTANCE_ADDRESS1, 24, GPIO_PIN_HIGH);
i++;
__delay_cycles(50000000);
j++;
}
// Signal the process has completed (this will wake up the loader to tell it work is done)
__R31 = (__R31 & ~0xff) | (PRU0_ARM_INTERRUPT+16);
/* Halt the PRU core */
__halt();
}

and the host C prog to load PRU code is as below

#include <stdio.h>
#include <stdlib.h>

#include <prussdrv.h>
#include <pruss_intc_mapping.h>

#define PRU_NUM 0
#define AM33XX

int main (int argc, char **argv)
{
unsigned int ret;
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

/* Initialize the PRU */
prussdrv_init ();

/* Open PRU Interrupt */
ret = prussdrv_open(PRU_EVTOUT_0);
if (ret) {
printf(“prussdrv_open open failed\n”);
return (ret);
}

/* Get the interrupt initialized */
prussdrv_pruintc_init(&pruss_intc_initdata);

/* Execute example on PRU */
prussdrv_exec_program (PRU_NUM, “./text.bin”);

/* Wait until PRU0 has finished execution */
prussdrv_pru_wait_event (PRU_EVTOUT_0);
prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);

/* Disable PRU and close memory mapping*/
prussdrv_pru_disable (PRU_NUM);
prussdrv_exit ();

return(0);
}

The above codes are generating output and my aim is to write the counter value stored in ‘i’ from PRU code to be available to host C code. Can anyone please help me ?

and one more doubt is the lines GPIOPinWrite(GPIO_INSTANCE_ADDRESS3, 16, GPIO_PIN_HIGH); and GPIOPinWrite(GPIO_INSTANCE_ADDRESS3, 16, GPIO_PIN_LOW); doesn’t produce out put, I have tired all the four GPIO base addresses, but in vain.

You may use prussdrv_map_prumem(…) to map PRU memory to host (C-client) utility.

If no pin state change, first of all you should show us your pin mux settings of the respective pins.
HTH

Greetings

I am seriously not an expert in this area but are you not asking for your operating system to be an RTOS (Real Time Operating System) when you expect it to input values from sensors when you are calculating through previous inputs?

My understanding is that a RTOS handles interrupts differently than something like Debian.

It may be possible to get Debian to become more like an RTOS - - - if so, how is that done?

(I’m looking at the BBB for process control and automation myself!)

Dee

Greetings

I am seriously not an expert in this area but are you not asking for your operating system to be an RTOS (Real Time Operating System) when you expect it to input values from sensors when you are calculating through previous inputs?

My understanding is that a RTOS handles interrupts differently than something like Debian.

It may be possible to get Debian to become more like an RTOS - - - if so, how is that done?

(I’m looking at the BBB for process control and automation myself!)

Dee

This person is actually talking about the PRUs ( Programmable Real-time Units ), which can operate independent of the main processor, and host OS. http://elinux.org/BeagleBone_PRU_Notes

To answer your question though( to the best of my ability ) I believe there is a kernel config option to make the kernel operate more like real time Linux.https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO

However that is “soft” real-time, and from what I understand is not exactly reliable / stable for this hardware.

I’m trying to use local address while writing from PRU and use global address while reading from host C prog. Proper global and local address schemes for local mapping and global mapping of the 12KB shared memory is what I’m confused about.
/* in PRU code */
float *a;
a = 0x00001000 /*local memory mapping of 12KB memory */
*a = 1;

‘a’ will be incremented in a loop whenever a particular GPIO pin is toggled
i’m confused about global mapping of the 12KB memory to access it from host C at regular intervals of time.