Tool/software: Code Composer Studio
Hello,
my PRU application is based on the PRU_RPMsg_Echo_Interrupt0/1 example from the PRU Software Support Package (https://git.ti.com/pru-software-support-package).
The code compiles fine, but I get the following error when trying to load the firmware (CCS Version: 8.1.0.00011, XDS110 Debug Probe):
PRU_0: File Loader: Verification failed: Values at address 0x0000@Program_Memory do not match Please verify target memory and memory map.
PRU_0: GEL: File: C:\Users\... .out: a data verification error occurred, file load failed.
I figure it has to do with the linker linker command file and the GEL file, but I can't find the issue.
AM335x_PRU.cmd:
/****************************************************************************/
/* AM335x_PRU.cmd */
/* Copyright (c) 2015-2018 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 = 0x00010000 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
PRU_MII_RT : org = 0x00032000 len = 0x00000058 CREGISTER=27
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
}
AM335x_PRU_ICSS_local.gel:
/****************************************************************************/
/* AM335x_PRU_ICSS_local.gel */
/* Copyright (c) 2016 Texas Instruments Incorporated */
/* Author: Rafael de Souza */
/* Rev: 1.0 */
/* */
/* Description: This GEL file is loaded with each PRU core. */
/* It primarily configures the PRU memory map for */
/* Code Composer Studio to properly display the valid */
/* memory regions of the PRU core. */
/* The routine OnTargetConnect can be customized to add */
/* other HW initialization routines. */
/* */
/****************************************************************************/
menuitem "Memory_Map"
hotmenu Enable_Memory_map()
{
PRU_ICSS_Memory_Map();
}
hotmenu Disable_Memory_map()
{
GEL_MapReset();
GEL_MapOff();
}
OnTargetConnect()
{
PRU_ICSS_Memory_Map();
}
/*********************************************/
/* PRU_ICSS Memory Map */
/* */
/* 0x00000000 - 0x00002000 Program RAM */
/* 0x00000000 - 0x00002000 Data RAM0 */
/* 0x00002000 - 0x00004000 Data RAM1 */
/* 0x00010000 - 0x00013000 Shared RAM */
/* 0x00020000 - 0x00022000 PRUSS_INTC */
/* 0x00022000 - 0x00022400 PRU0 Control */
/* 0x00024000 - 0x00024400 PRU1 Control */
/* 0x00026000 - 0x00028000 CFG */
/* 0x00028000 - 0x0002A000 UART0 */
/* 0x0002E000 - 0x00030000 IEP */
/* 0x00030000 - 0x00032000 eCAP0 */
/* 0x00032000 - 0x00034000 MII RT */
/* 0x00034000 - 0x00036000 MDIO */
/*********************************************/
PRU_ICSS_Memory_Map()
{
GEL_MapReset();
GEL_MapOn();
GEL_MapAdd(0x00000000,0,0x2000,1,1); /* Program RAM */
GEL_MapAdd(0x00000000,1,0x2000,1,1); /* Data RAM0 */
GEL_MapAdd(0x00002000,1,0x2000,1,1); /* Data RAM1 */
GEL_MapAdd(0x00010000,2,0x3000,1,1); /* Shared RAM */
GEL_MapAdd(0x00020000,2,0x2000,1,1); /* PRUSS_INTC */
GEL_MapAdd(0x00022000,2,0x400,1,1); /* PRU0 Control */
GEL_MapAdd(0x00024000,2,0x400,1,1); /* PRU1 Control */
GEL_MapAdd(0x00026000,2,0x2000,1,1); /* CFG */
GEL_MapAdd(0x00028000,2,0x2000,1,1); /* UART0 */
GEL_MapAdd(0x0002E000,2,0x2000,1,1); /* IEP */
GEL_MapAdd(0x00030000,2,0x2000,1,1); /* eCAP0 */
GEL_MapAdd(0x00032000,2,0x2000,1,1); /* MII RT */
GEL_MapAdd(0x00034000,2,0x2000,1,1); /* MDIO */
}
resource_table_0.h:
/*
* Copyright (C) 2016-2018 Texas Instruments Incorporated - <a href="http://www.ti.com/">http://www.ti.com/</a>
*
*
* 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.
*/
#ifndef _RSC_TABLE_PRU_H_
#define _RSC_TABLE_PRU_H_
#include <stddef.h>
#include <rsc_types.h>
#include "pru_virtio_ids.h"
/*
* Sizes of the virtqueues (expressed in number of buffers supported,
* and must be power of 2)
*/
#define PRU_RPMSG_VQ0_SIZE 16
#define PRU_RPMSG_VQ1_SIZE 16
/*
* The feature bitmap for virtio rpmsg
*/
#define VIRTIO_RPMSG_F_NS 0 //name service notifications
/* This firmware supports name service notifications as one of its features */
#define RPMSG_PRU_C0_FEATURES (1 << VIRTIO_RPMSG_F_NS)
/* Definition for unused interrupts */
#define HOST_UNUSED 255
/* Mapping sysevts to a channel. Each pair contains a sysevt, channel. */
struct ch_map pru_intc_map[] = { {16, 2},
{17, 0},
};
struct my_resource_table {
struct resource_table base;
uint32_t offset[2]; /* Should match 'num' in actual definition */
/* rpmsg vdev entry */
struct fw_rsc_vdev rpmsg_vdev;
struct fw_rsc_vdev_vring rpmsg_vring0;
struct fw_rsc_vdev_vring rpmsg_vring1;
/* intc definition */
struct fw_rsc_custom pru_ints;
};
#pragma DATA_SECTION(resourceTable, ".resource_table")
#pragma RETAIN(resourceTable)
struct my_resource_table resourceTable = {
1, /* Resource table version: only version 1 is supported by the current driver */
2, /* number of entries in the table */
0, 0, /* reserved, must be zero */
/* offsets to entries */
{
offsetof(struct my_resource_table, rpmsg_vdev),
offsetof(struct my_resource_table, pru_ints),
},
/* rpmsg vdev entry */
{
(uint32_t)TYPE_VDEV, //type
(uint32_t)VIRTIO_ID_RPMSG, //id
(uint32_t)0, //notifyid
(uint32_t)RPMSG_PRU_C0_FEATURES, //dfeatures
(uint32_t)0, //gfeatures
(uint32_t)0, //config_len
(uint8_t)0, //status
(uint8_t)2, //num_of_vrings, only two is supported
{ (uint8_t)0, (uint8_t)0 }, //reserved
/* no config data */
},
/* the two vrings */
{
0, //da, will be populated by host, can't pass it in
16, //align (bytes),
PRU_RPMSG_VQ0_SIZE, //num of descriptors
0, //notifyid, will be populated, can't pass right now
0 //reserved
},
{
0, //da, will be populated by host, can't pass it in
16, //align (bytes),
PRU_RPMSG_VQ1_SIZE, //num of descriptors
0, //notifyid, will be populated, can't pass right now
0 //reserved
},
{
TYPE_POSTLOAD_VENDOR, PRU_INTS_VER0 | TYPE_PRU_INTS,
sizeof(struct fw_rsc_custom_ints),
{
0x0000,
/* Channel-to-host mapping, 255 for unused */
0, HOST_UNUSED, 2, HOST_UNUSED, HOST_UNUSED,
HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED,
/* Number of evts being mapped to channels */
(sizeof(pru_intc_map) / sizeof(struct ch_map)),
/* Pointer to the structure containing mapped events */
pru_intc_map,
},
},
};
#endif /* _RSC_TABLE_PRU_H_ */
I can connect to the PRU's just fine through JTAG, but can't get the firmware loaded. Any ideas what might cause the issue?
Thank you!

