Description of the program: An LED toggles on and off from a set delay time in R2.
A separate C program loads the PRU program, starts the core and then prompts the user for a Time to do a delay. Upon the user entering a time, the c program writes that value to dataram and reads back the mapped memory from the PRU to show. The PRU loop does a SBBO each time as well as a LBBO for a single R2 . My LBBO call however is not returning the proper value, I am likely using the wrong pointer value. Here is where I believe the problem is, how I interpret what register address to start at by setting an arbitrary r9 to the start. *ldi r9, 9 // offset to the start of the third 32 bit value * *lbbo r2, r9, 0 ,4 // read 4 bytes from there and store it into r2* *After I write from C into the dataram for * Here is the pru program #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 .text main: // init ldi r0, 0 ldi r1, 0xffff ldi r3, 777 ldi r4, 777 ldi r8, 1000 ldi r5, 10000 main_loop: //Load value of PRU data memory in general register r2 ldi r9, 9 // offset to the start of the third lbbo r2, r9, 0 ,4 mov r6, r2 // to prove in the c program that data arrived and is correct when displayed R2 should equal R6- debug mov r2, r6 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 ) ldi r14.w2, %hi_rlz(r2) call delay_n2_cycles // led off mov r30, r0 ldi r14, %lo(r2) ldi r14.w2, %hi_rlz(r2 ) 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] */ Here is the c program #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[4] = (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; } Ok so maybe I am messing up R2 in how I assign it trying to set it to a 32 bit value. I must bee missing a concept on how to get the LBBO working to read back what the user writes into the data ram. On Sunday, November 27, 2016 at 2:09:27 PM UTC-7, din...@gmail.com wrote: > > Hi, check my comments inline. > > On Sunday, November 27, 2016 at 10:15:00 PM UTC+2, Neil Jubinville wrote: >> >> 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 , 48* >> >> and like magic my c pru memap dumped out values I have stuffed in some of >> the registers. >> >> see below >> >> ------------------------------------- >> value R0 = 0 >> value R1 = 65535 >> value R2 = 8192 >> value R3 = 16 >> value R4 = 777 >> value R5 = 25 >> value R6 = -136853601 >> value R7 = 2146680819 >> value R8 = 1 >> value R9 = -45491713 >> value R10 = -89 >> value 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 set >> >> *r2 = 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? >> > > Could you share your full source code? > >> >> --------- >> >> 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* >> > Yes, the & is not needed for pru-gcc. But for the sake of compatibility > I'll make it optional with the next release. > > > >> >> >> 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? >> > Dataram has no register mapping. It is simply memory. Consider the > following example: > ldi r1, 101 > ldi r2, 64 > sbbo r1, r2, 0, 4 > Converted to C syntax, it would look like: > unsigned int r1 = 101; > unsigned int *r2 = (void *)64; > r2[0] = r1; > > > > >> >> >> <https://lh3.googleusercontent.com/-PR6M_jNKhu4/WDs-tnOriEI/AAAAAAAAASU/VTpqCAMst9wgqHo1G8r1mmuserz0ZOprwCLcB/s1600/Screen%2BShot%2B2016-11-27%2Bat%2B1.13.55%2BPM.png> >> >> >> >> *Thx! * >> >> >> >> >> >> >> On Saturday, November 26, 2016 at 12:43:37 PM UTC-7, Charles Steinkuehler >> wrote: >>> >>> On 11/26/2016 1:33 PM, Neil Jubinville wrote: >>> > >>> > Here is my basic understanding - Focusing on PRU0: >>> > >>> > Each PRU has 8K of 'dataram' - This is where I expect R1,R2,R3 ---- >>> R31 to be >>> > stored. *Is this true? I see many people changing the reference at >>> *0x0000_0n00, >>> > n = c24_blk_index[3:0], do I need to set where the Rn's lay down in >>> memory? >>> >>> NO >>> >>> The data ram is what it says...data ram. The registers are what they >>> say...registers. Registers are *NOT* data ram. If you want the >>> register values to appear in memory, you have to write them out using >>> the SBBO instruction. >>> >>> > Docs also state that the PRU 0 Data ram starts at *0x4a300000*; >>> > >>> > int registerStart; >>> > registerStart = *(int*)0x4a300000; >>> > printf("--> R0 = %d" + registerStart); >>> > >>> > However I get a seg fault trying to print what is in R0 that way. >>> That was more >>> > to just do a direct look see if possible and go around all the >>> interfaces. >>> >>> 0x4a300000 is a physical address. You can use that if you are >>> directly accessing memory (via /dev/mem, bus-mastering DMA, or >>> something that doesn't use an MMU like the PRU core). If you try to >>> access a physical address from a standard application that has not >>> been mapped into your process memory space, the MMU will forbid access >>> and your program seg-faults. >>> >>> To access the PRU memory in your application, use the address provided >>> to you by the prussdrv_map_prumem function. >>> >>> -- >>> Charles Steinkuehler >>> cha...@steinkuehler.net >>> >> -- For more options, visit http://beagleboard.org/discuss --- You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/ab70d060-a13f-41b7-854d-7f13e1aa8aa2%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.