On the AM5728 (Beagle X-15) I have performed pin muxing to change pin vin1a_d6 to pr1_pru0_gpi3 (attaches to external push button), and gpio4_8 to pr1_pru1_gpo4 (attaches to external LED). Using a combination of code from the TI trainings I have set up a scenario that will turn the LED on and off when the button is pushed. RPMsg is also enabled and sends a message to the device driver saying whether the button is pushed or released.
Currently I debounce with using a large delay [__delay_cycles(100000000)]. The problem with this is that the response time is too slow for my desired functionality however, reducing the delay time causes the remoteproc to either completely freeze and require a restart or loses all functionality and doesn’t register the button push at all.
I am new to embedded systems and PRU, and am unsure if this is a PRU/RPMsg problem or a debouncing issue. I have tried different types of debouncing methods and it doesn’t improve the situation. Is there a specific method to debounce PRU inputs or is there any advice to improving the speed of my input/output response.
Attached the code (2 files that work across remoteproc4 and 5)
#include <stdint.h>
#include <pru_cfg.h>
/*TODO: Include intc.h */
#include <pru_intc.h>
// PRU Core 1
#define PRU1
volatile register uint32_t __R30;
volatile register uint32_t __R31;
/* Defines */
#define PRU0
/* PRU0-to-PRU1 interrupt */
#define PRU0_PRU1_EVT (16)
#define PRU0_PRU1_TRIGGER (__R31 = (PRU0_PRU1_EVT - 16) | (1 << 5))
/* SW1 offset */
/*TODO: Define GPI offset for SW1 */
#define SW1 (1 << 3)
/* INTC configuration
-
We are going to map User event 16 to Host 1
-
PRU1 will then wait for r31 bit 31 (designates Host 1) to go high
-
*/
void configIntc(void)
{
/* Clear any pending PRU-generated events */
__R31 = 0x00000000;
/* Map event 16 to channel 1 */
CT_INTC.CMR4_bit.CH_MAP_16 = 1; /*TODO: Select correct bit field and enter proper value */;
/* Map channel 1 to host 1 */
CT_INTC.HMR0_bit.HINT_MAP_1 = 1; /*TODO: Select correct bit field and enter proper value */;
/* Ensure event 16 is cleared */
CT_INTC.SICR = 16; /*TODO: Clear proper event */;
/* Enable event 16 */
CT_INTC.EISR = 16; /*TODO: Enable proper event */;
/* Enable Host interrupt 1 */
CT_INTC.HIEISR |= (1 << 0); /*TODO: Enable proper event */;
// Globally enable host interrupts
CT_INTC.GER = 1; /*TODO: Enable global events */;
}
void main(void)
{
/* Configure GPI and GPO as Mode 0 (Direct Connect) */
CT_CFG.GPCFG0 = 0x00000;
/* Clear GPO pins */
__R30 &= 0xFFFF00000;
/* Configure INTC */
configIntc();
while (1) {
if ((__R31 & SW1) != SW1) {
__delay_cycles(100000000);
PRU0_PRU1_TRIGGER;
}
}
}
#include <stdint.h>
#include <stdio.h>
#include <pru_cfg.h>
#include <pru_intc.h>
#include <rsc_types.h>
#include <pru_rpmsg.h>
#include “resource_table.h”
#include “intc_map_1.h”
#include <stdbool.h>
#include <string.h>
volatile register uint32_t __R30;
volatile register uint32_t __R31;
#define HOST1_MASK (0x80000000)
#define LED_ON (__R30 |= (1 <<4))
#define LED_OFF (__R30 &= ~(1 << 4))
//RPMsg variables
#define TO_ARM_HOST 18
#define FROM_ARM_HOST 19
#define CHAN_NAME “rpmsg-pru”
#define CHAN_PORT 31
#define CHAN_DESC “Channel 31”
#define VIRTIO_CONFIG_S_DRIVER_OK 4
bool RPMessage=true;
//Debounce variables
int pressed = 0;
int pressed_conf_lvl = 0;
int released_conf_lvl = 0;
//Push button debouncing
volatile bool buttonPressed;
void main(void)
{
struct pru_rpmsg_transport transport;
uint16_t src=1024, dst=31;
volatile uint8_t *status;
/* Initialise RPMsg messages depending on switch state*/
char switch_press[20];
uint16_t closed_len = 9;
memcpy(switch_press, "LED on \n", closed_len);
char switch_release[20];
uint16_t open_len = 10;
memcpy(switch_release, "LED off \n", open_len);
/* Allow OCP master port access by the PRU so the PRU can read external memories */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
/* Clear the status of the PRU-ICSS system event that the ARM will use to 'kick' us */
CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST;
/* Make sure the Linux drivers are ready for RPMsg communication */
status = &resourceTable.rpmsg_vdev.status;
while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK));
/* Initialize the RPMsg transport structure */
pru_rpmsg_init(&transport, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1, TO_ARM_HOST, FROM_ARM_HOST);
/* Create the RPMsg channel between the PRU and ARM user space using the transport structure. */
while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME, CHAN_DESC, CHAN_PORT) != PRU_RPMSG_SUCCESS);
while (1)
{
//Check if interrupt set to HOST 1 from switch
if (__R31 & HOST1_MASK)
{
//if interrupt detected increment press confidence
pressed_conf_lvl ++;
//reset release as a press is detected
released_conf_lvl = 0;
//threshold for debounced press
if (pressed_conf_lvl >= 10)
{
if (pressed == 0)
{
//Send RPMsg that LED is off and turn LED off
pru_rpmsg_send(&transport, dst, src, switch_press, closed_len);
LED_ON;
pressed = 1;
//flag that a message has been sent
RPMessage = true;
}
}
}
else
{
released_conf_lvl ++;
if (released_conf_lvl >= 10)
{
//Send message that switch is closed, LED will turn on
if(!RPMessage)
{
//Send message that LED on and turn LED on
pru_rpmsg_send(&transport, dst, src, switch_release, open_len);
LED_OFF;
//Flag that message has been sent
RPMessage=true;
}
else
{
RPMessage=false;
}
pressed = 0;
released_conf_lvl = 0;
pressed_conf_lvl = 0;
}
}
//Clear interrupts from switch and RPMsg
CT_INTC.SICR = 16;
CT_INTC.SICR_bit.STATUS_CLR_INDEX = FROM_ARM_HOST;
//Delay loop otherwise reading device file crashes PRU
__delay_cycles(1000000000);
}
}