Tool/software: TI C/C++ Compiler
Hi, I am trying to get acquainted with PRU using PRU labs. I was able to get the first lab working easily but for the second one it seems that the interrupts aren't working. I have tested the LED connected to PRU1 and switch connected to PRU0 independently and they work. It's just that the interrupt part doesn't work.
Here is my code:
// button_pru0.c
/* * Switch is connected to P9.27 (pru0_r31_5) in active high * Sends interrupt using event 16 to PRU1 */ #include <stdint.h> #include <pru_cfg.h> #include <pru_intc.h> #include "resource_table_empty.h" #define PRU0 volatile register uint32_t __R30; volatile register uint32_t __R31; /* * PRU0 to PRU1 interrupt * PRU cores can generate interrupts manually using events 16-31 * however these are mapped to bits [3:0] in the r31 register * Additionally, we have to trigger bit 5 to strobe the interrupt */ #define PRU0_PRU1_EVT (16) #define PRU0_PRU1_TRIGGER (__R31 = (PRU0_PRU1_EVT - 16) | (1 << 5)) // switch mask #define SW1 (1<<5) /* * int configuration */ void configIntc(void) { // clear any pending PRU events __R31 = 0x00000000; // map event 16 to channel 1 // channel map registers (CMRm) define the channel for each system event // there is one register per 4 events, therefore 16 CMR for 64 events // for event 16 we will use CMR4 CT_INTC.CMR4_bit.CH_MAP_16 = 1; // map channel 1 to host 1 // host map registers (HMRm) define the channel for each host event // one register per 4 channels, therefore 3 HMR for 10 channels // host 1 is connected to R31 bit 31 for PRU0 and PRU1 CT_INTC.HMR0_bit.HINT_MAP_1 = 1; // 4.4.2.3.2 Interrupt Enabling in TRM // ensure event 16 is cleared // after servicing an event, event status has to be cleared // event N can be cleared by writing N into the system event status indexed clear register (SICR) CT_INTC.SICR = 16; // enable event 16 // system events that are required to be propagated to host must be enabled // event N can be enabled by writing N in the system event enable indexed set register (EISR) CT_INTC.EISR = 16; // enable host interrupt 1 // done by writing N to HIEISR register CT_INTC.HIEISR |= (1 << 0); // globally enable host interrupts // set EN bit (bit 0) in global enable register (GER) to 1 CT_INTC.GER = 1; } void main(void) { // Configure GPI/O as Mode 0 (Direct input) // bit 1-0 // 00 - direct input mode // 01 - 16bit parallel capture mode // 10 - 28bit shift mode // 11 - Mii_rt mode CT_CFG.GPCFG0 = 0x0000; // clear all 16 output pins __R30 &= 0xFFFF0000; // configure interrupt configIntc(); while(1) { // wait for SW1 to be pressed (active high) if((__R31 & SW1) == SW1) { // wait 500 ms for debounce __delay_cycles(100000000); // interrupt PRU1 PRU0_PRU1_TRIGGER; } } }
// led_pru1.c
/*
* led is connected to P8.44 (pru1_r30_3)
*/
#include <stdint.h>
#include <pru_cfg.h>
#include <pru_intc.h>
#include "resource_table_empty.h"
volatile register uint32_t __R30;
volatile register uint32_t __R31;
#define PRU1
// host 1 is mapped to bit 31 of R31
#define HOST1_MASK (1<<31)
#define PRU0_PRU1_EVT (16)
#define TOGGLE_LED (__R30 ^= (1<<3))
void main(void)
{
// GPIO mode - direct connect
CT_CFG.GPCFG0 = 0x0000;
// clear all output pins
__R30 &= 0xFFFF0000;
while(1)
{
// wait while host 1 is detected
if(__R31 & HOST1_MASK)
{
TOGGLE_LED;
// clear interrupt event
CT_INTC.SICR = 16;
// delay to ensure that the event is cleared in INTC
__delay_cycles(5); // 5 cycles is an overkill
}
}
}
/****************************************************************************/
/* AM335x_PRU.cmd */
/* Copyright (c) 2015 Texas Instruments Incorporated */
/* */
/* Description: This file is a linker command file that can be used for */
/* linking PRU programs built with the C compiler and */
/* the resulting .out file on an AM335x device. */
/****************************************************************************/
-cr /* Link using C conventions */
/* Specify the System Memory Map */
MEMORY
{
PAGE 0:
PRU_IMEM : org = 0x00000000 len = 0x00002000 /* 8kB PRU0 Instruction RAM */
PAGE 1:
/* RAM */
PRU_DMEM_0_1 : org = 0x00000000 len = 0x00002000 CREGISTER=24 /* 8kB PRU Data RAM 0_1 */
PRU_DMEM_1_0 : org = 0x00002000 len = 0x00002000 CREGISTER=25 /* 8kB PRU Data RAM 1_0 */
PAGE 2:
PRU_SHAREDMEM : org = 0x00010000 len = 0x00003000 CREGISTER=28 /* 12kB Shared RAM */
DDR : org = 0x80000000 len = 0x00000100 CREGISTER=31
L3OCMC : org = 0x40000000 len = 0x00010000 CREGISTER=30
/* Peripherals */
PRU_CFG : org = 0x00026000 len = 0x00000044 CREGISTER=4
PRU_ECAP : org = 0x00030000 len = 0x00000060 CREGISTER=3
PRU_IEP : org = 0x0002E000 len = 0x0000031C CREGISTER=26
PRU_INTC : org = 0x00020000 len = 0x00001504 CREGISTER=0
PRU_UART : org = 0x00028000 len = 0x00000038 CREGISTER=7
DCAN0 : org = 0x481CC000 len = 0x000001E8 CREGISTER=14
DCAN1 : org = 0x481D0000 len = 0x000001E8 CREGISTER=15
DMTIMER2 : org = 0x48040000 len = 0x0000005C CREGISTER=1
PWMSS0 : org = 0x48300000 len = 0x000002C4 CREGISTER=18
PWMSS1 : org = 0x48302000 len = 0x000002C4 CREGISTER=19
PWMSS2 : org = 0x48304000 len = 0x000002C4 CREGISTER=20
GEMAC : org = 0x4A100000 len = 0x0000128C CREGISTER=9
I2C1 : org = 0x4802A000 len = 0x000000D8 CREGISTER=2
I2C2 : org = 0x4819C000 len = 0x000000D8 CREGISTER=17
MBX0 : org = 0x480C8000 len = 0x00000140 CREGISTER=22
MCASP0_DMA : org = 0x46000000 len = 0x00000100 CREGISTER=8
MCSPI0 : org = 0x48030000 len = 0x000001A4 CREGISTER=6
MCSPI1 : org = 0x481A0000 len = 0x000001A4 CREGISTER=16
MMCHS0 : org = 0x48060000 len = 0x00000300 CREGISTER=5
SPINLOCK : org = 0x480CA000 len = 0x00000880 CREGISTER=23
TPCC : org = 0x49000000 len = 0x00001098 CREGISTER=29
UART1 : org = 0x48022000 len = 0x00000088 CREGISTER=11
UART2 : org = 0x48024000 len = 0x00000088 CREGISTER=12
RSVD10 : org = 0x48318000 len = 0x00000100 CREGISTER=10
RSVD13 : org = 0x48310000 len = 0x00000100 CREGISTER=13
RSVD21 : org = 0x00032400 len = 0x00000100 CREGISTER=21
RSVD27 : org = 0x00032000 len = 0x00000100 CREGISTER=27
}
/* Specify the sections allocation into memory */
SECTIONS {
/* Forces _c_int00 to the start of PRU IRAM. Not necessary when loading
an ELF file, but useful when loading a binary */
.text:_c_int00* > 0x0, PAGE 0
.text > PRU_IMEM, PAGE 0
.stack > PRU_DMEM_0_1, PAGE 1
.bss > PRU_DMEM_0_1, PAGE 1
.cio > PRU_DMEM_0_1, PAGE 1
.data > PRU_DMEM_0_1, PAGE 1
.switch > PRU_DMEM_0_1, PAGE 1
.sysmem > PRU_DMEM_0_1, PAGE 1
.cinit > PRU_DMEM_0_1, PAGE 1
.rodata > PRU_DMEM_0_1, PAGE 1
.rofardata > PRU_DMEM_0_1, PAGE 1
.farbss > PRU_DMEM_0_1, PAGE 1
.fardata > PRU_DMEM_0_1, PAGE 1
.resource_table > PRU_DMEM_0_1, PAGE 1
}
/* * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * ======== resource_table_empty.h ======== * * Define the resource table entries for all PRU cores. This will be * incorporated into corresponding base images, and used by the remoteproc * on the host-side to allocated/reserve resources. Note the remoteproc * driver requires that all PRU firmware be built with a resource table. * * This file contains an empty resource table. It can be used either as: * * 1) A template, or * 2) As-is if a PRU application does not need to configure PRU_INTC * or interact with the rpmsg driver * */ #ifndef _RSC_TABLE_PRU_H_ #define _RSC_TABLE_PRU_H_ #include <stddef.h> #include <rsc_types.h> struct my_resource_table { struct resource_table base; uint32_t offset[1]; /* Should match 'num' in actual definition */ }; #pragma DATA_SECTION(pru_remoteproc_ResourceTable, ".resource_table") #pragma RETAIN(pru_remoteproc_ResourceTable) struct my_resource_table pru_remoteproc_ResourceTable = { 1, /* we're the first version that implements this */ 0, /* number of entries in the table */ 0, 0, /* reserved, must be zero */ 0, /* offset[0] */ }; #endif /* _RSC_TABLE_PRU_H_ */
Everything compiles properly. I have also noticed that if I don't include the resource table, as in the lab the PRU units don't reboot.
Please let me know if you find the issue