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.

CCS/AM3358: PRU_0: File Loader: Verification failed...

Part Number: AM3358


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!