So my question is whether anyone can offer up any debugging best practices for PRUSS code. Thanks in advance!
Jerrill
1) Write a program that just writes to the local memory address of the
PRU core you're using. If the code loads and run, you can read the
memory from Linux and check that your code is running. Later, you can
re-use this code to insert the ugly equivalent of a printf() to learn
more about some part of your code:
#define CONST_LOCAL_RAM C24
mov r13, 0xbabec0de
sbco r13, CONST_LOCAL_RAM, 0, 4
You should then have just enough to write 0xbabec0de to 0x4a300000
(from Linux devmem2) on the AM3359 assuming you are using PRU0, if
it's PRU1 it'll be at 0x4a302000
2) Setup IRQs, the INTC can be overwhelming at first, but once you
reduce it's true capabilities to what you really need it's not that
bad. Get the PRU to trigger an IRQ to linux, and then the userspace
programs using uio_pruss can display information as it happens, maybe
you might setup a DEBUG IRQ that fires and the userspace program then
immediately reads something from the PRU's local memory and prints it
to your console.
3) Setup macros to do push/pop so you can create assembly functions.
This will enable you to use call/ret safely by saving and restoring
register contexts. I have the follwoing simple macros in pasm header
file:
#define sp r24
#define lr r23
#define STACK_TOP (0x2000 - 4)
#define STACK_BOTTOM (0x2000 - 0x200)
.macro stack_init
mov sp, STACK_BOTTOM
.endm
.macro push
.mparam reg, cnt
sbbo reg, sp, 0, 4*cnt
add sp, sp, 4*cnt
.endm
.macro pop
.mparam reg, cnt
sub sp, sp, 4*cnt
lbbo reg, sp, 0, 4*cnt
.endm
Now you can define simple functions like:
do_something:
push lr, 1 // save r1
push r1, 4 // save r1-r4
... do stuff ...
pop r1, 4
pop lr
ret
4) Then I would attempt to do something like toggle a GPIO and hook it
up to an o-scope if you so desire (or maybe you can use a LED gpio).
Toggle the GPIO using the PRU firmware you write that sets up and
configures the GPIO blocks. For access to the global system memory
from the PRU core, you need to enable the OCP master ports in the
SYSCFG register (TRM 4.9.1.2), this wasn't obvious to me at the time.
I have updated a kernel space pruss mfd driver that some folks from TI
submitted to the arm kernel mailing list, but was never accepted. If
a few people were interested, I could setup a blog with some quick
demos on the beaglebone and post the code on github.
- Kyle
www.kylemanna.com
> -- To join: http://beagleboard.org/discuss
> To unsubscribe from this group, send email to:
> beagleboard...@googlegroups.com
> Frequently asked questions: http://beagleboard.org/faq
>
> 2) Setup IRQs, the INTC can be overwhelming at first, but once you
> reduce it's true capabilities to what you really need it's not that
> bad. Get the PRU to trigger an IRQ to linux, and then the userspace
> programs using uio_pruss can display information as it happens, maybe
> you might setup a DEBUG IRQ that fires and the userspace program then
> immediately reads something from the PRU's local memory and prints it
> to your console.
Use only if needed.
>
> 3) Setup macros to do push/pop so you can create assembly functions.
> This will enable you to use call/ret safely by saving and restoring
> register contexts. I have the follwoing simple macros in pasm header
> file:
Yes, as soon as your code gets more complex you'll need this. But only
after you got a decent memory layout, proper initalization etc.
Yes, but be carefull ! Linux (kernel) memory is easily corrupted if you
make a mistake.
You can do the enable both from user space or from the PRU. If you use
the PRU you can turn it on and off at need, reducing the risk of memory
corruption if your program faults.
-- Bas
Frequently asked questions: http://beagleboard.org/faq
-- To join: http://beagleboard.org/discuss
To unsubscribe from this group, send email to:
Frequently asked questions: http://beagleboard.org/faq
Someone has started a PRU debugger, but it still seems that it's in the early stages of development:
4) Then I would attempt to do something like toggle a GPIO and hook it up to an o-scope if you so desire (or maybe you can use a LED gpio). Toggle the GPIO using the PRU firmware you write that sets up and configures the GPIO blocks.
I have updated a kernel space pruss mfd driver that some folks from TI submitted to the arm kernel mailing list, but was never accepted. If a few people were interested, I could setup a blog with some quick demos on the beaglebone and post the code on github.
The first key part is if you intended to use the normal GPIO and need
to access the L3 bus, you'll need to enable access by STANDBY_INIT in
the SYSCFG register. I wasted alot of time trying to access main
system memory until I stumbled on this bit.
Here is some rough code I had laying around that would loop and toggle
a GPIO using the eCAP counter. You'll need to disable the eCAP loop
code or configure eCAP yourself. It's ugly, I'd clean it up if I had
time. Hopefully it'll at least give you ideas as to what to do.
Push and pop are macros I wrote to simulate a stack:
#define STACK_TOP (0x2000 - 4)
#define STACK_BOTTOM (0x2000 - 0x200)
.macro stack_init
mov sp, STACK_BOTTOM
.endm
///////////////////////////////////////////////////////////////
// Stack Push
// reg - starting register to push
// cnt - number of registers to push starting at reg
///////////////////////////////////////////////////////////////
.macro push
.mparam reg, cnt
sbbo reg, sp, 0, 4*cnt
add sp, sp, 4*cnt
.endm
///////////////////////////////////////////////////////////////
// Stack Pop
// reg - starting register to pop
// cnt - number of registers to pop starting at reg
///////////////////////////////////////////////////////////////
.macro pop
.mparam reg, cnt
sub sp, sp, 4*cnt
lbbo reg, sp, 0, 4*cnt
.endm
///////////////////////////////////////////////////////////////
// GPIO test
//
// @param R1 number of loops to run
///////////////////////////////////////////////////////////////
gpio_test:
push lr, 1
push r1, 4
mov R3, R1
// Set OE to output for GPIO 33 & 34
mov r4, #0x4804c100
LBBO R1, r4, 0x34, 4
mov R2, #0xfffffff9
and R1, R1, R2
SBBO R1, r4, 0x34, 4
gpio_loop:
LBBO R1, r4, 0x3c, 4
and R1, R1, R2
SBBO R1, r4, 0x3c, 4
LBBO R1, r4, 0x3c, 4
or R1, R1, #0x6
SBBO R1, r4, 0x3c, 4
sub R3, R3, #1
QBGE gpio_end, R3, #0 // quick branch if 0 > r3
//QBA gpio_loop
GPIO_POLL_IRQ:
lbco r1, c3, 0x2e, 2
QBBS GPIO_CLEAR_CONT, r1.w0, 6
QBA GPIO_POLL_IRQ
GPIO_CLEAR_CONT:
mov r1, 0xff
SBCO r1, c3, 0x30, 2
QBA gpio_loop
gpio_end:
pop r1, 4
pop lr, 1
ret
- Kyle
www.kylemanna.com
Someone has started a PRU debugger, but it still seems that it's in the early stages of development: