Thx Charles, that was it. I was treating the registers as application of dataram memory.In the assembly loop: I did a : sbbo r0, r0, 0 , 48and like magic my c pru memap dumped out values I have stuffed in some of the registers.see below-------------------------------------value R0 = 0value R1 = 65535value R2 = 8192value R3 = 16value R4 = 777value R5 = 25value R6 = -136853601value R7 = 2146680819value R8 = 1value R9 = -45491713value R10 = -89value R11 = -1345356802------------------------------------I do have a more basic question though about the value in R2 = 8192. My understanding is the general purpose registers are 32 bit.In my assembly I setr2 = 0x0BEBC200 // decimal 200,000,000 to reflect the core frequency.however as you can see the R2 after the mem copy to dataram shows 8192. Why is it not reading 200,000,000 in R2 after the transfer?
---------Also, another question. Syntax wise the first r0 in the statement below 'should' have &r0 but I get unknown register error when compiling. If I leave out the & it works and the transfer does occur. Is this a nuance of the gcc-pru compiler vs a direct pasm compile?sbbo r0, r0, 0 , 48
Yet another question: the second argument of r0 reflects the starting address point in dataram. I would have expected dataram as a free for all address space that I managed. Is the reference of an Rn type syntax simply a convenience for addressing in dataram and dataram has the notion of its own register mapping?
#include "memparams.hp"
#define CONST_PRUCFG 0xC4
#define CPU_HZ (200 * 1000 * 1000)//lbco r3, CONST_PRUCFG, 4, 4
.text .section .init0, "x" .global __start__start: /* Initialize stack pointer. */ ldi sp, %lo(__stack_top) ldi sp.w2, %hi_rlz(__stack_top) r2 = 0x0BEBC200 // set r2 to a default of 200,000,000 jmp main
.text .section .textmain:
// init ldi r0, 0 ldi r1, 0xffff ldi r3, 777 ldi r4, 777 ldi r8, 1000 ldi r5, 10000
main_loop:
//Load valeu of PRU data memory in general register r2 //ldi r9, 9 // offset to the start of the third lbbo r2, r2, 0 ,4 mov r6, r2 // to prove in the c program that data arrived and is correct when displayed R2 should equal R6- debug
sbbo r0, r0, 0 , 48 // copy all 12 registers to memory R0...R11 .
// the goal is for R2 to get set in a C program outside theis assembly. Thus changing the speed of the // blinking LED - defualt is set to 1 second = 200,000,000 cycles in CPU delay.
// led on mov r30, r1 ldi r14, %lo( r2/4 ) ldi r14.w2, %hi_rlz(r2/4) call delay_n2_cycles
// led off mov r30, r0 ldi r14, %lo(r2/4) ldi r14.w2, %hi_rlz(r2/4 ) call delay_n2_cycles
jmp main_loop
delay_n2_cycles: sub r14, r14, 1 qbne delay_n2_cycles, r14, 0 ret
my_resource_table: .word 1, 0, 0, 0 /* struct resource_table base */ .word 0 /* uint32_t offset[1] */
#include <stdio.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#include <err.h>#include <sys/mman.h>#include <libelf.h>
#include "prussdrv.h"#include "pruss_intc_mapping.h"
#define AM33XX_PRUSS_IRAM_SIZE 8192#define AM33XX_PRUSS_DRAM_SIZE 8192#define PRU_NUM 0#define ADDEND1 0x98765400u#define ADDEND2 0x12345678u#define ADDEND3 0x10210210u#define LOOPS 30
#define DDR_BASEADDR 0x80000000#define OFFSET_DDR 0x00001000#define OFFSET_SHAREDRAM 0x00000000 //equivalent with 0x00002000
#define PRUSS0_SHARED_DATARAM 4
static int LOCAL_exampleInit ( );static unsigned short LOCAL_examplePassed ( unsigned short pruNum, unsigned int millis );static int mem_fd;static void *ddrMem, *sharedMem;static unsigned int *sharedMem_int;static int counter ;
int main (int argc, char *argv[]){ counter = 0 ;
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; int ret;
printf("Initializing the PRUs...\n"); prussdrv_init();
/* Open PRU Interrupt */ ret = prussdrv_open(PRU_EVTOUT_0); if (ret) errx(EXIT_FAILURE, "prussdrv_open open failed\n");
/* Get the interrupt initialized */ prussdrv_pruintc_init(&pruss_intc_initdata);
printf("\tINFO: Initializing example. - Writing Data to Local CPU DDR Ram \r\n"); LOCAL_exampleInit(PRU_NUM);
printf("Starting ...\n"); prussdrv_pru_enable(0); prussdrv_pru_enable(1);
unsigned int blinkySpeed = 1000;
while (counter < LOOPS){
printf("Please Enter a blinky speed in milliseconds:"); scanf("%d" , &blinkySpeed ); LOCAL_examplePassed(PRU_NUM, blinkySpeed ); //usleep(5 * 1000 * 1000); counter = counter + 1; }
fflush(stdout);
/* Disable PRU and close memory mapping*/ prussdrv_pru_disable(PRU_NUM); //munmap(ddrMem, 0x0FFFFFFF); //close(mem_fd); prussdrv_exit();
printf("Program done.\n");
return EXIT_SUCCESS;}
static int LOCAL_exampleInit ( ){ void *DDR_regaddr1, *DDR_regaddr2, *DDR_regaddr3;
/* open the device */ mem_fd = open("/dev/mem", O_RDWR); if (mem_fd < 0) { printf("Failed to open /dev/mem (%s)\n", strerror(errno)); return -1; }
/* map the DDR memory */ ddrMem = mmap(0, 0x0FFFFFFF, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, DDR_BASEADDR); if (ddrMem == NULL) { printf("Failed to map the device (%s)\n", strerror(errno)); close(mem_fd); return -1; }
/* Store Addends in DDR memory location */ DDR_regaddr1 = ddrMem + OFFSET_DDR; DDR_regaddr2 = ddrMem + OFFSET_DDR + 0x00000004; DDR_regaddr3 = ddrMem + OFFSET_DDR + 0x00000008;
*(unsigned long*) DDR_regaddr1 = ADDEND1; *(unsigned long*) DDR_regaddr2 = ADDEND2; *(unsigned long*) DDR_regaddr3 = ADDEND3;
return(0);}
static unsigned short LOCAL_examplePassed ( unsigned short pruNum, unsigned int millis ){ unsigned int result_0, result_1, result_2, result_3,result_4,result_5,result_6,result_7,result_8,result_9,result_10,result_11;
/* Allocate PRU Dataram memory. */ prussdrv_map_prumem(PRUSS0_PRU0_DATARAM, &sharedMem); sharedMem_int = (unsigned int*) sharedMem;
// set R2 which hold our delay valy for the blinky action in the pru sharedMem_int[2] = (millis * 1000 * 200);
// read all the current data ram fields in result_0 = sharedMem_int[ 0]; result_1 = sharedMem_int[ 1]; result_2 = sharedMem_int[ 2]; result_3 = sharedMem_int[ 3]; result_4 = sharedMem_int[ 4]; result_5 = sharedMem_int[ 5]; result_6 = sharedMem_int[ 6]; result_7 = sharedMem_int[ 7]; result_8 = sharedMem_int[ 8]; result_9 = sharedMem_int[ 9]; result_10 = sharedMem_int[ 10]; result_11 = sharedMem_int[ 11];
printf("-------------------------------------\n"); //printf("%p\n", (void *) &sharedMem_int[0]); printf("value R0 = %d\n ", result_0); printf("value R1 = %d\n", result_1); printf("value R2 = %d\n", result_2); printf("value R3 = %d\n ", result_3); printf("value R4 = %d\n", result_4); printf("value R5 = %d\n", result_5); printf("value R6 = %d\n ", result_6); printf("value R7 = %d\n", result_7); printf("value R8 = %d\n", result_8); printf("value R9 = %d\n ", result_9); printf("value R10 = %d\n", result_10); printf("value R11 = %d\n", result_11); //return ((result_0 == ADDEND1) & (result_1 == ADDEND2) & (result_2 == ADDEND3)) ;
return 1;
} lbbo r2, r0, 8 ,4
mov r6, r2 // to prove in the c program that data arrived and is correct when displayed R2 should equal R6- debug
sbbo r0, r0, 0 , 48 // copy all 12 registers to memory R0...R11 .
// the goal is for R2 to get set in a C program outside theis assembly. Thus changing the speed of the
// blinking LED - defualt is set to 1 second = 200,000,000 cycles in CPU delay.
// led on
mov r30, r1
mov r14,r6
call delay_n2_cycles
// led off
mov r30, r0
mov r14, r6
call delay_n2_cycles
/*
// led on
mov r30, r1
ldi r14, %lo( r6/4 )
ldi r14.w2, %hi_rlz(r6/4)
call delay_n2_cycles
// led off
mov r30, r0
ldi r14, %lo(r6/4)
ldi r14.w2, %hi_rlz(r6/4 )
call delay_n2_cycles
*/ ldi r2, %lo(200000) ldi, r2.w0 %hi_rlz(200000).macro ldi32 rx, expr
ldi \rx, %lo(\expr)
ldi \rx\().w2, %hi_rlz(\expr)
.endm
; Use like this:
ldi32 r2, 200000
uint32_t *r2; r2 = (uint32_t)(*r2); mov r2,r6