This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/BEAGLEBK: PRU training Lab2 problem

Part Number: BEAGLEBK


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

  • The software team have been notified. They will respond here.
  • Rumman,

    Sorry for the delay, I have been away from my desk for the past two weeks.

    My current hunch is that the pin muxing on your device may not be configured properly as described in lab 4 here: processors.wiki.ti.com/.../PRU_Training:_Hands-on_Labs

    I was able to use the lab 2 solutions from the ~/pru-software-support-package/labs/lab_2/solution/ folder and confirm that the demo is working correctly on the setup on my desk. The only change that I had to make (in addition to the device tree modifications) is to copy the 'resource_table_empty.h' file to each of the two solution directories (button_led_0 and button_led_1) and then add the include line to the top of each .c file (#include "resource_table_empty.h")

    Let me know if the device tree modification doesn't help in your case or if any of the above doesn't make sense.

    Jason Reeder

    PS. Labs 1 through 3 were written with the assumption that the user would be loading the PRUs using JTAG and Code Composer Studio. In this scenario the pin muxing would be configured by the CCS gel script. Since the Linux driver wasn't responsible for loading the firmwares, this also explains why the resource table header files don't appear until lab 4.

    If you would like to run any of the first three labs with Linux, you'll need to follow the steps to update the device tree file to update the PRU cape pin muxing as well as add resource tables to the examples.