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.

PRU debugging on Linux - pView whereabouts?

Other Parts Discussed in Thread: AM3358

Hi,

I'm developing a high-speed PRU stepper generator native on Linux.

I notice the PASM manual refers to a debugging tool called 'pView' - is that available?

A minimal debugging capability on-system (inspect/modify registers/memory, break, step etc) would be extremely valuable - the CCS tool is a bit heavy for basic debugging tasks, and I'm unsure if it is actually suited to debug a PRU application like demoed in https://github.com/beagleboard/am335x_pru_package 

I notice that a seemingly half-finished PRU debugger is at https://github.com/wz2b/prude - anybody working on that?

thanks in advance

Michael

  • If you're looking for a PRU debugger, you might want to try out prudebug (https://sourceforge.net/projects/prudebug/).

  • Hi Steven

    thanks for the hint

    actually got it to work on a beaglebone black after changing prudbg.h like so:

    // configuration defines
    //#define PRUSS_START           0x01C30000
    #define PRUSS_START             0x4a300000
    #define PRUSS_LEN               0x10000


    - Michael

  • Hi Michael,

    No problem.  I'm glad you were able to get it working on the Beaglebone Black.  Hopefully you'll find it useful.  If not, please let me know what was missing or needs improvement.

    Steve

  • Michael, Steven

    I have been trying to make is work on the Beaglebone Black but so far have been unsuccessful.

    I tried just as Michael did with modifying the PRUSS_START address. I did the following steps:

    prudebug <cr>

    pru 0

    L 0x34000 prucode.bin

    GSS

    but after I hit a key, it stops at 0x0000 PC and even after doing SS, it never increments to the next address.

    I then noticed that there were other registers in the prudbg.h file that were set differently than the BBB PRU address map.

    so I changed the following as well


    // register offsets
    #define PRU_CTRL_REG 0x0000
    #define PRU_STATUS_REG 0x0004
    #define PRU_INTGPR_REG 0x0020

    // sub-block base address (two address, one for each PRU)
    #define PRU_INST_BASE {0x34000, 0x38000}
    #define PRU_CTRL_BASE {0x22000, 0x24000}
    #define PRU_DATA_BASE {0x0000, 0x2000}

    then I reran prudebug

    L 0x34000 led_driver.bin

    I tried to do a DIS but I got the following

    [0x0000] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0001] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0002] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0003] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0004] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0005] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0006] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0007] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0008] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x0009] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000a] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000b] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000c] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000d] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000e] 0x00000000 ADD R0.b0, R0.b0, R0.b0
    [0x000f] 0x00000000 ADD R0.b0, R0.b0, R0.b0

    as if nothing was loaded in Instruction Memory

    I then run gss and I got a segmentation fault.

    Can anyone of you help ?

    Thank you

  • As L seems to take an offset of the instruction memory base, I also tried with

    L 0x0 prucode.bin but got the same results

  • Hi Chris,

    I admit I did not test that change extensively, primarily because we already have a symbolic debugger for PRU code on the LinuxCNC environment (see post on debugging near the bottom of http://www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/05/22/bbb--working-with-the-pru-icssprussv2#/?page=2)

    can you post the source  led_driver.p so we can reproduce?

    - Michael

  • Actually, it does it with any pru file. I tried with the following led_blink.bin/p but it does not work either

    // prucode.p

    .origin 0
    .entrypoint START

    #include "prucode.hp"

    #define GPIO1 0x4804c000
    #define GPIO_CLEARDATAOUT 0x190
    #define GPIO_SETDATAOUT 0x194

    START:

    // Enable OCP master port
    LBCO r0, CONST_PRUCFG, 4, 4
    CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
    SBCO r0, CONST_PRUCFG, 4, 4

    // Configure the programmable pointer register for PRU0 by setting c28_pointer[15:0]
    // field to 0x0120. This will make C28 point to 0x00012000 (PRU shared RAM).
    MOV r0, 0x00000120
    MOV r1, CTPPR_0
    ST32 r0, r1

    // Configure the programmable pointer register for PRU0 by setting c31_pointer[15:0]
    // field to 0x0010. This will make C31 point to 0x80001000 (DDR memory).
    MOV r0, 0x00100000
    MOV r1, CTPPR_1
    ST32 r0, r1

    //Load values from external DDR Memory into Registers R0/R1/R2
    LBCO r0, CONST_DDR, 0, 12

    //Store values from read from the DDR memory into PRU shared RAM
    SBCO r0, CONST_PRUSHAREDRAM, 0, 12

    // test GP output
    MOV r1, 10 // loop 10 times
    LOOP:
    MOV r2, 1<<21
    MOV r3, GPIO1 | GPIO_SETDATAOUT
    SBBO r2, r3, 0, 4

    MOV r0, 0x00f00000
    DEL1:
    SUB r0, r0, 1
    QBNE DEL1, r0, 0

    MOV R2, 1<<21
    MOV r3, GPIO1 | GPIO_CLEARDATAOUT
    SBBO r2, r3, 0, 4

    MOV r0, 0x00f00000
    DEL2:
    SUB r0, r0, 1
    QBNE DEL2, r0, 0

    SUB r1, r1, 1
    QBNE LOOP, r1, 0

    // Send notification to Host for program completion
    MOV r31.b0, PRU0_ARM_INTERRUPT+16

    // Halt the processor
    HALT

  • I didn't do any testing on the AM335x processor.  While I don't have a Beaglebone Black board, I do have a AM3358 based board.  I won't have time to look at it until tonight but will look into the issue and let you know later today.

  • Christian Joly said:

    // Send notification to Host for program completion
    MOV r31.b0, PRU0_ARM_INTERRUPT+16

    where does this interrupt arrive? do you have a matching C program on the ARM cpu which uses prussdrv? can you show that?

    maybe a better way is to get the examples from https://github.com/beagleboard/am335x_pru_package working and only attach to the already working program

    that would take out a few moving parts

    - Michael

  • Michael

    The example works fine on the BBB and yes, I have the matching C program. It is an example that I extracted from the web. Here is the main routine

    int main (void)
    {
    unsigned int ret;
    int d;
    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

    printf("\nINFO: Starting %s example.\r\n", "PRU_memAccess_DDR_PRUsharedRAM");

    /* Initialize the PRU */
    prussdrv_init ();

    /* Open PRU Interrupt */
    ret = prussdrv_open(PRU_EVTOUT_0);
    if (ret)
    {
    printf("prussdrv_open open failed\n");
    return (ret);
    }

    /* Get the interrupt initialized */
    prussdrv_pruintc_init(&pruss_intc_initdata);
    prussdrv_pru_reset(0);

    /* Initialize example */
    printf("\tINFO: Initializing example.\r\n");
    LOCAL_exampleInit(PRU_NUM);

    /* Execute example on PRU */
    printf("\tINFO: Executing example.\r\n");
    prussdrv_exec_program (PRU_NUM, "./prucode.bin");

    /* Wait until PRU0 has finished execution */
    printf("\tINFO: Waiting for HALT command.\r\n");
    prussdrv_pru_wait_event (PRU_EVTOUT_0);
    printf("\tINFO: PRU completed transfer.\r\n");
    prussdrv_pru_clear_event (PRU0_ARM_INTERRUPT);

    /* Check if example passed */
    if ( LOCAL_examplePassed(PRU_NUM) )
    {
    printf("Example executed succesfully.\r\n");
    }
    else
    {
    printf("Example failed.\r\n");
    }

    /* Disable PRU and close memory mapping*/
    prussdrv_pru_disable(PRU_NUM);
    prussdrv_exit ();
    munmap(ddrMem, 0x0FFFFFFF);
    close(mem_fd);

    return(0);
    }

    You mentioned you are using linuxcnc. What environment is it ?

  • what kernel version are you using? we've switched to the 3.8 series so a device tree overlay needs to be loaded in that case

    --

    LinuxCNC is a open-source CNC package. See www.linuxcnc.org . 

    The starting point for the latest and greatest on the Beaglebone ARM port is here: http://bb-lcnc.blogspot.co.at/

    for more detail, see the emc-developers mailing list archive

    - Michael

  • I am using Debian Wheezy. I have updated the kernel to get the overlay working so the PRU is working fine and I can run code on it.

    I just would like to also have debugging capability and I though prudebug would do the trick but it looks like it is not fully compatible with the BB Black yet

  • Wheezy is a distro; could you post the the output of 'uname -a' and the top lines of 'dmesg'?

    welcome to open source - it's ToolTime again - adapt the tools and only then start digging ;)

    -m

  • Linux arm 3.8.13-bone18.1 #4 SMP Sat Jun 1 16:49:02 PDT 2013 armv7l GNU/Linux

    [ 0.000000] Booting Linux on physical CPU 0x0
    [ 0.000000] Initializing cgroup subsys cpu
    [ 0.000000] Linux version 3.8.13-bone18.1 (christy@christy-desktop) (gcc version 4.7.3 20130226 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03) ) #4 SMP Sat Jun 1 16:49:02 PDT 2013
    [ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c5387d
    [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
    [ 0.000000] Machine: Generic AM33XX (Flattened Device Tree), model: TI AM335x BeagleBone
    [ 0.000000] Memory policy: ECC disabled, Data cache writeback
    [ 0.000000] On node 0 totalpages: 130816
    [ 0.000000] free_area_init_node: node 0, pgdat c0a50740, node_mem_map c0aca000
    [ 0.000000] Normal zone: 1024 pages used for memmap
    [ 0.000000] Normal zone: 0 pages reserved
    [ 0.000000] Normal zone: 129792 pages, LIFO batch:31
    [ 0.000000] AM335X ES1.0 (neon )
    [ 0.000000] PERCPU: Embedded 9 pages/cpu @c0ed9000 s14080 r8192 d14592 u36864
    [ 0.000000] pcpu-alloc: s14080 r8192 d14592 u36864 alloc=9*4096
    [ 0.000000] pcpu-alloc: [0] 0
    [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 129792
    [ 0.000000] Kernel command line: console=ttyO0,115200n8 root=UUID=b14a0a23-1b38-42cb-9337-9799fc8980ee ro rootfstype=ext4 rootwait fixrtc
    [ 0.000000] PID hash table entries: 2048 (order: 1, 8192 bytes)
    [ 0.000000] Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
    [ 0.000000] Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
    [ 0.000000] __ex_table already sorted, skipping sort
    [ 0.000000] allocated 1048576 bytes of page_cgroup
    [ 0.000000] please try 'cgroup_disable=memory' option if you don't want memory cgroups
    [ 0.000000] Memory: 511MB = 511MB total
    [ 0.000000] Memory: 504048k/504048k available, 20240k reserved, 0K highmem
    [ 0.000000] Virtual kernel memory layout:
    [ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
    [ 0.000000] fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
    [ 0.000000] vmalloc : 0xe0800000 - 0xff000000 ( 488 MB)
    [ 0.000000] lowmem : 0xc0000000 - 0xe0000000 ( 512 MB)
    [ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
    [ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
    [ 0.000000] .text : 0xc0008000 - 0xc08a8570 (8834 kB)
    [ 0.000000] .init : 0xc08a9000 - 0xc09d0700 (1182 kB)
    [ 0.000000] .data : 0xc09d2000 - 0xc0a535b0 ( 518 kB)
    [ 0.000000] .bss : 0xc0a535b0 - 0xc0ac9700 ( 473 kB)
    [ 0.000000] Hierarchical RCU implementation.
    [ 0.000000] RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=1.
    [ 0.000000] NR_IRQS:16 nr_irqs:16 16
    [ 0.000000] IRQ: Found an INTC at 0xfa200000 (revision 5.0) with 128 interrupts
    [ 0.000000] Total of 128 interrupts on 1 active controller
    [ 0.000000] OMAP clockevent source: GPTIMER1 at 24000000 Hz
    [ 0.000000] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956ms
    [ 0.000000] OMAP clocksource: GPTIMER2 at 24000000 Hz
    [ 0.000000] Console: colour dummy device 80x30

  • Hi Steven,

    I looked at the code and tried to make it work for the AM335X proc but I have run into a number of issues.

    1 - I have updated the header file to match the processor memory map

    2 - I have modified some of the code in prudbg.c as some offsets were hardcoded vi cmd.c

    3 - I also modified cmd.c soft_reset function. I believe you wanted to do a bitwise not and not an arithmetic not. but I am getting a segmentation fault when I run the reset command. Here is the code. The segmentation fault happens when I try to set the control register with a new value with the bit 0 cleared.

    void cmd_soft_reset()
    {
    unsigned int ctrl_reg;

    ctrl_reg = pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG];
    ctrl_reg &= ~PRU_REG_SOFT_RESET;
    printf("PRU%u 0x%08X 0x%08X\n", pru_num,pru_ctrl_base[pru_num],ctrl_reg );
    pru[pru_ctrl_base[pru_num] + PRU_CTRL_REG] = ctrl_reg;

    printf("PRU%u reset.\n", pru_num);
    }


    Any idea what is happening ? Have you had time to look at the code ?

    Thanks,

    Christian

  • This is the part of the header file I modified

    // configuration defines
    //#define PRUSS_START 0x01C30000
    #define PRUSS_START 0x4a300000
    #define PRUSS_LEN 0x80000

    // general settings
    #define MAX_CMD_LEN 25
    #define MAX_CMDARGS_LEN 200
    #define MAX_COMMAND_LINE (MAX_CMD_LEN + MAX_CMDARGS_LEN + 1)
    #define MAX_ARGS 10
    #define MAX_PRU_MEM 0x8FFFF
    #define NUM_OF_PRU 2
    #define MAX_BREAKPOINTS 5
    #define MAX_WATCH 5

    // register offsets
    #define PRU_CTRL_REG 0x0000
    #define PRU_STATUS_REG 0x0004
    #define PRU_INTGPR_REG 0x0400

    // sub-block base address (two address, one for each PRU)
    #define PRU_INST_BASE {0x34000, 0x38000}
    #define PRU_CTRL_BASE {0x22000, 0x24000}
    #define PRU_DATA_BASE {0x0000, 0x2000}

    // PRU control register bit flags
    #define PRU_REG_PCRESET_MASK 0x0000FFFF
    #define PRU_REG_RUNSTATE 0x00008000
    #define PRU_REG_SINGLE_STEP 0x00000100
    #define PRU_REG_COUNT_EN 0x00000008
    #define PRU_REG_SLEEPING 0x00000004
    #define PRU_REG_PROC_EN 0x00000002
    #define PRU_REG_SOFT_RESET 0x00000001

    // defines for command repeats
    #define LAST_CMD_NONE 0
    #define LAST_CMD_D 1
    #define LAST_CMD_DD 2
    #define LAST_CMD_DI 3
    #define LAST_CMD_DIS 4
    #define LAST_CMD_SS 5

    // defines for structures below
    #define BP_UNUSED 0
    #define BP_ACTIVE 1

    #define WA_UNUSED 0
    #define WA_PRINT_ON_ANY 1
    #define WA_HALT_ON_VALUE 2

    #define TRUE 1
    #define FALSE 0

  • Hi Christian,

    I did take a look at the PRUSS v2 (which I had not worked with before), and clearly there are some differences when compared to the PRUSS v1.  I also looked through the debugger code a bit, and I need to make a number of changes.  Since we're moving to the AM335x for new projects, I'll probably want to have this support in prudebug.  I'm shooting for Sunday night (6/9/2013) to have the changes complete and released as version 0.23.

    I'd provide you with some hints on fixing it yourself, but I think it needs some rework so it's not so PRUSS v1 centric (in other words, it'd be a long list of fixes).  Hopefully, your project can wait a few days.

     

    Steve

  • That would be fantastic. Thanks Steve

  • Hi Steve

    Have you been able to update your code for AM335X ?

    Tx

    Christian

  • Hi Christian,

    Sorry, but no I didn't.....had car problems so I spent a buch of time working on that.  I'm waiting on a part for the car (won't be in until tomorrow), so I might be able to put a little time into it tonight.  I certainly won't have time to complete all the changes I was planning, but maybe I can get it working for you.  Do you just need PRU0 working, or are you using PRU1 as well?  If it's just PRU0, I should be able to get that working (if I can find an hour or two).

    I took a quick look at the problems you were having.  I suspect the segmentation fault is due to the PRUSSv2 having a larger footprint.  Try changing PRUSS_LEN define in prudbg.h to 0x20000.  Thanks for catching the incorrect NOT on setting the control register....not sure why that worked at all. 

    If I can get an hour or so tonight, I'll post by midnight CDT.

    Steve

  • Hi Steve,

    I actually changed the PRU_LEN to 0x8000 as it is the new footprint size of PRUSSv2. I got segmentation fault with that header file. I will try with 0x2000.

    And yes, if you can update for PRU0 for now, then it would be really helpful.

    Thank you

    Christian

  • Hi Christian,

    Note the four zeros, and actually try setting it to 0x80000 (more clearly 0x8 00 00).

    Steve

  • Opps sorry... That is actually what I did. 0x80000

  • Ok, that makes sense (PRU space is 0x80000).  I got a couple of extra minutes to take another look at the modifications you made.  I believe the defines for the three types of memory space in the PRU are incorrect because these are 32-bit indexes.  Please try the following defines for a Beaglebone, and let me know how it works out.

    #define PRUSS_START  0x4A300000

    #define PRU_INST_BASE {0xD000, 0xE000}

    #define PRU_CTRL_BASE {0x8800, 0x9000}

    #define PRU_DATA_BASE {0x0000, 0x0800}

    Steve

  • Hi Steve,

    This is where I am at. It looks like the header info you gave works. I no longer get segmentation fault.

    I also modified line 159,  193,   337 of prudgb.c to change the hardcoded offset from 0x2000 to offset = pru_inst_base[pru_num];

    With this, I got the right code in instruction memory when using the DI command

    The da.c needs to be updated. A diss does not give the right instructions. I believe it is because PRUSSv2 has updated instructions.

    I have tried to run SS, G without success. It looks like the pointer counter does not increment for some reason. (The current instruction seems to be listed correctly)

    This is what I get with SS:

    PRU0> ss
    Register info for PRU0
    Control register: 0x00000101
    Reset PC:0x0000 STOPPED, SINGLE_STEP, COUNTER_DISABLED, NOT_SLEEPING, PROC_DISABLED

    Program counter: 0x0000
    Current instruction: LDI R0, 0x0000

    R00: 0x00000000 R08: 0x00000000 R16: 0x00000000 R24: 0x00000000
    R01: 0x00000000 R09: 0x00000000 R17: 0x00000000 R25: 0x00000000
    R02: 0x00000000 R10: 0x00000000 R18: 0x00000000 R26: 0x00000000
    R03: 0x00000000 R11: 0x00000000 R19: 0x00000000 R27: 0x00000000
    R04: 0x00000000 R12: 0x00000000 R20: 0x00000000 R28: 0x00000000
    R05: 0x00000000 R13: 0x00000000 R21: 0x00000000 R29: 0x00000000
    R06: 0x00000000 R14: 0x00000000 R22: 0x00000000 R30: 0x00000000
    R07: 0x00000000 R15: 0x00000000 R23: 0x00000000 R31: 0x00000000

    Another SS will give the same input

    Christian

  • Hi Christian,

    I made your changes and added a correction to line 156. 

    Unfortunately, I hadn't used my TI AM3358 Starter board in some time and it needed a little work to get running, so I ran out of time tonight.  I'm currently working on getting the PRU running, which appears to be stopped with this board/Linux distro.  If you have or know where I can get a quick cheat-sheet for the PRU startup process (power & clocking), that would be very helpful.  Otherwise, I'll just have to dig through the register settings for those subsystems.

    Steve

  • Steve,

    It seems that my initial setup in the header file were correct. The reason I am getting Segmentation fault is due to the fact that I cannot read the debug register.

    I can read the Control Register, Status Register but it crashes when I try to get the Registers info

    Do you have any idea what that could be ?

    Tx

    Christian

  • Hi Steve,

    After more digging, you were right with your initial addresses. I have changed your initialization for to get the pru pointer using the driver that I loaded on my system.

    https://github.com/beagleboard/am335x_pru_package

    I did update the driver to add an additional function to get the PRU pointer.

    Everything is working now. 

    Tx

    Christian

  • Christian,

    any chance of making all changes publically accessible say in a github repo`

    thanks

    Michael

  • I do not mind but as it is your code, I do not want to infringe on anything.

    I have also not updated yet the instruction set. If you want, I can do the instruction set update and send the updated code to you.

    Then you can make it public ?

  • Hi Christian,

    Glad you got it working!  It sounds like you got the PRU pointer from a funtion other than mmap.  What did you use?  Can you run a diff on the code and post it here?  I'd like to incorporate it into the code on SF.  If you have a SF account, I could also give you access.

    Steve

  • it's rather Steve's code, but given he published it to start with I guess that would be ok

    -m

  • Yes. I meant Steve code

  • I'd like to keep the code in one place on SF (so any effort is focused on improving one copy), but you're welcome to move a copy anywhere you'd like, modify, fork the project, etc. (BSD licensed).

    If you want the changes added to SF, you can provide me files or patches, or I can provide you access to the prudebug project on SF.

    Steve

  • Steve,

    I think it is better to keep the code in one place. I will send you the diff shortly and the added function to the driver

    Christian

  • Here is the diff. Instructions in the next post:

    diff prudebug-0.22/Makefile prudebug_cj/Makefile
    2c2,5
    < CC=arm-none-linux-gnueabi-gcc
    ---
    > CC=gcc
    > LIBRARIES = pthread prussdrv
    > INCLUDES = -I. ${LIB_PATH}
    >
    7c10
    < ${CC} ${objs} -o prudebug
    ---
    > ${CC} ${objs} -lpthread -lprussdrv -o prudebug
    diff prudebug-0.22/prudbg.c prudebug_cj/prudbg.c
    20a21,22
    > #include "prussdrv.h"
    > #include <pruss_intc_mapping.h>
    24,26c26,28
    < unsigned int pru_inst_base[] = PRU_INST_BASE;
    < unsigned int pru_ctrl_base[] = PRU_CTRL_BASE;
    < unsigned int pru_data_base[] = PRU_DATA_BASE;
    ---
    > unsigned int pru_inst_base[2] = PRU_INST_BASE;
    > unsigned int pru_ctrl_base[2] = PRU_CTRL_BASE;
    > unsigned int pru_data_base[2] = PRU_DATA_BASE;
    35c37
    < int fd;
    ---
    > int ret;
    43c45
    < unsigned long opt_pruss_addr;
    ---
    > tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
    50,75c52,63
    < opt_pruss_addr = 0;
    < while ((opt = getopt(argc, argv, "a:")) != -1) {
    < switch (opt) {
    < case 'a':
    < opt_pruss_addr = atol(optarg);
    < break;
    < default: /* '?' */
    < printf("Usage: prudebug [-a pruss-address]\n");
    < printf(" pruss-address is the memory address of the PRU in ARM memory space\n");
    < return(-1);
    < }
    < }
    < if (opt_pruss_addr == 0) opt_pruss_addr = PRUSS_START;
    <
    < // get memory pointer for PRU from /dev/mem
    < fd = open ("/dev/mem", O_RDWR | O_SYNC);
    < if (fd == -1) {
    < printf ("ERROR: could not open /dev/mem.\n\n");
    < return 1;
    < }
    < pru = mmap (0, PRUSS_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, opt_pruss_addr);
    < if (pru == MAP_FAILED) {
    < printf ("ERROR: could not map memory.\n\n");
    < return 1;
    < }
    < close(fd);
    ---
    > /* Initialize the PRU */
    > prussdrv_init ();
    > /* Open PRU Interrupt */
    > ret = prussdrv_open(PRU_EVTOUT_0);
    > if (ret)
    > {
    > printf("prussdrv_open open failed\n");
    > return (ret);
    > }
    > /* Get the interrupt initialized */
    > prussdrv_pruintc_init(&pruss_intc_initdata);
    > pru = get_dataram(0);
    94d81
    <
    156c143
    < offset = pru_num * 0x0800;
    ---
    > offset = pru_data_base[pru_num];
    159c146
    < offset = (pru_num * 0x1000) + 0x2000;
    ---
    > offset = pru_inst_base[pru_num];
    193c180
    < offset = (pru_num * 0x1000) + 0x2000;
    ---
    > offset = pru_inst_base[pru_num];
    210d196
    < // start processor
    212,219c198
    < } else {
    < // set instruction pointer
    < addr = strtol(&cmdargs[argptrs[0]], NULL, 0);
    <
    < // start processor
    < // cmd_run_at(addr);
    < printf("NOT IMPLEMENTED YET.\n");
    < }
    ---
    > }
    227d205
    < // halt the processor
    237d214
    < // halt the processor
    276d252
    < // reset the processor
    278d253
    < printf("\n");
    287d261
    < // reset the processor
    335c309
    < offset = pru_num * 0x0800;
    ---
    > offset = pru_data_base[pru_num];
    337c311
    < offset = (pru_num * 0x1000) + 0x2000;
    ---
    > offset = pru_inst_base[pru_num];
    diff prudebug-0.22/prudbg.h prudebug_cj/prudbg.h
    13,14c13,14
    < #define PRUSS_START 0x01C30000
    < #define PRUSS_LEN 0x10000
    ---
    > #define PRUSS_START 0x4a300000
    > #define PRUSS_LEN 0x80000
    21c21
    < #define MAX_PRU_MEM 0xFFFF
    ---
    > #define MAX_PRU_MEM 0x8FFFF
    32,34c32,38
    < #define PRU_INST_BASE {0x2000, 0x3000}
    < #define PRU_CTRL_BASE {0x1C00, 0x1E00}
    < #define PRU_DATA_BASE {0x0000, 0x0800}
    ---
    > #define PRU_INST_BASE {0xD000, 0xE000}
    > #define PRU_CTRL_BASE {0x8800, 0x9000}
    > #define PRU_DATA_BASE {0x0000, 0x0800}
    >
    > //#define PRU_INST_BASE {0x34000, 0x38000}
    > //#define PRU_CTRL_BASE {0x22000, 0x24000}
    > //#define PRU_DATA_BASE {0x0000, 0x2000}

  • Instructions :

    1 - Download https://github.com/beagleboard/am335x_pru_package

    2 - Add to prussdrv.c the following function under am335x_pru_package/pru_sw/app_loader/interface:  


    unsigned int *get_dataram(unsigned int prunum) {

    unsigned int *prudataram;
    if (prunum == 0)
    prudataram = (unsigned int *) prussdrv.pru0_dataram_base;
    else
    prudataram = (unsigned int *) prussdrv.pru1_dataram_base;

    return prudataram;
    }

    3 - Create Share Library

    gcc -I. -Wall -I../include   -c -fPIC -O3 -mtune=cortex-a8 -march=armv7-a -shared -o prussdrv.o prussdrv.c

    gcc -shared -o libprussdrv.so prussdrv.o

    4 - Modify include file prussdrv.h under am335x_pru_package/pru_sw/app_loader/include

    add  unsigned int *get_dataram(unsigned int prunum); to the end of the file

    5 - Copy am335x_pru_package/pru_sw/app_loader/include/* in /usr/local/include/.

         copy am335x_pru_package/pru_sw/app_loader/interface/libprussdrv.so in /usr/local/lib/.

    6 - Make sure the the pruss module is running (lsmod)

    And then you can recompile the prudbg code.

    As mentioned, I have not updated the instruction set in da.c yet

  • Thanks for the improvements and the info.  I'll merge this in and post to SF on the weekend.

    Are you sure the disassembly is incorrect?  The software migration guide states that the PRUSSv2 instruction set is upward compatible.  I do know that some of the assembler instructions are pseudo instructions, so they look different when disassembled.  Do you have a couple of examples?

    Steve

  • The disassembly is not incorrect. It does work but for example instructions like MOV are converted to LDI... I do not think that there are major changes to be done on it.

  • By the way, one more change in cmd.c line 271 - Change from ! to ~  (Soft_reset)

  • Christian,

    I would like to acknowledge your contribution in the README and somewhere on the SF prudebug page.  Is that ok?

    Steve

  • Steve,

    Sure,

    Tx

    Christian

  • Steve,

    One more modif if I may.

    in cmd.c, line 179 in cmd_run add:

    ctrl_reg &= ~PRU_REG_SINGLE_STEP;

    before 

    ctrl_reg |= PRU_REG_PROC_EN;

    The SingleStep bit needs to be cleared if single step mode has been used before.

    Tx

    Christian

  • I just wanted to place a final comment on this thread for future readers.  I believe all the issues in prudebug mentioned in this thread have been resolved in version 0.24.

  • Michael, I am having difficulty why the offsets in prudebug have values 4 times larger than the byte address offsets of the PRU 3358X reference manual. Is there any chance you could help out with this? Also, I have extended prudebug.c in a minor way to allow SS and GSS from a halt statment, and could make it available, but don't know where a good location would be.
    -Ken
  • wordsize - probably one is a uint8_t * and the other is a uint32_t *

    - Michael
  • Hi Kenneth,

    Most of the offsets are byte pointers whereas a few (usually marked) are 32-word pointers.  Which specific offset are you referring to?

    If you have additions to the code, please send them to me or post them on the Sourceforge website (http://sourceforge.net/projects/prudebug).  I'll make sure they get into the code, and I'll generate a new release.

    I've been mulling over the idea of adding source code debug features for a long time, but I wasn't sure anyone was using it so I've held off.  Anyone have any interest?

    Steve

  • Hi Steve,

    actually I have implemented source line debugging in hal_prudebug, which is quite specific in API usage to the machinekit platform as it stands, but the source code lookup routines can be lifted easily:

    the UI code which does the source lookup: github.com/.../PRU-Debugger

    the actual debugger interface: https://github.com/machinekit/machinekit/blob/master/src/hal/components/hal_prudebug.c

    - Michael

  • Steven, for example, on lines 87-98 of prudbg.c, you have:
        {
            .processor     = "AM335x",
            .short_name     = "AM335X",
            .pruss_address     = 0x4A300000,
            .pruss_len     = 0x40000,
            .num_of_pruss    = 2,
            .offsets    = {
                {
                    .pruss_inst    = 0xD000,
                    .pruss_data    = 0x0000,
                    .pruss_ctrl    = 0x8800
                },
    whereas on pg. 20 of the PRU reference guide, showing Table 6, the the global reference guide, we have

    0x0003_4000 PRU0 8KB IRAM

    which is the address of the instruction RAM for PRU0. My understanding is this address is already a byte address, so its word address would be 4 times smaller. However, you use 0xD000 which is exactly 4 times larger. Similar for the control register address. I know your addressess work from attaching gdb to the process, but I can't figure out why.

    Regarding sending you the code, I will do if you could e-mail me your e-mail address, the only address I have is for the TI forum address and I don't think I can send the changed code there, and I don't know how to post them on sourceforge.net; do they have a place for depositing code? The changes aren't many (for example: a new cmd2.c, and  a new Makefile2, so if one makes using >make -f Makefile2, one gets my modified version, if one makes using your Makefile (>make), one gets the original.

    Regarding using it; I find it essential; I can't debug the PRU code without it. I really appreciate you making it available.I do find the changes useful, but others might not. An example of using:

    Say in a loop, on can insert a HALT and compile.

    The PRUs stop at the HALT, using R will then show the registers, and if one the goes SS, one goes to the next instruction. Then using G, one goes around the loop to the second iteration, and halts again allowing inspection. Also, at the HALT, one can add a breakpoint, and then going GSS will go to the breakpoint.

  • Hi Kenneth,

    I suspect you're just not looking at it quite right (or perhaps I'm missing something in your question).  The 0x0003_4000 is the ARM byte address as you mention.  The 0x0000_D000 is 1/4 the value of the byte address and is the word index/address.  I knew it was a mistake to use both byte and word addressing in the code since it can become very confusing, but of course did it anyway.

    I'd be happy to take a look at your additions and if they look generally of use to others then I'll integrate them into the code and add you as a contributor.  You can add a entry to the General Discussion forum (I changed the access rights to allow anonymous access).  I'd leave my email (I not too concerned with a few people having my email), but bots tend to grab info like emails from forums and they have gotten to be rather clever at decoding even somewhat hidden info.

    Steve