There are many information about PRU usage out there but most of them 
expect to have a Linux-system running which initialises PRU. In case 
somebody wants to utilitise it out of a bare-metal or Starterware 
application one is lost in the dark. PRU-registers are documentend in 
AM3358 TRM but creating working code out of these specifications is not an 
easy thing. So after it is working for me I'll provide all information here.

To create the code running on PRU I'm using TI's C-compiler from 
http://software-dl.ti.com/codegen/non-esd/downloads/download.htm#PRU

Compilation of the source-file "main.c" is done by calling

clpru --silicon_version=3 -I/opt/ti/ccsv6/tools/compiler/ti-cgt-pru_2.1.0/
include/ -I/opt/ti/ccsv6/tools/compiler/ti-cgt-pru_2.1.0/lib/ \
      -o4 --opt_for_speed=5 main.c -z AM3359_PRU.cmd -o PRU_tests.out -m 
PRU_tests.map

This generates an ELF-file PRU_tests.out and a linker map file 
PRU_tests.map which is needed to evaluate the start-address of the PRU-code 
later.

Next split the ELF file into two separate sections for text (read-only, 
executable program code) and data (readable and writable but not 
executable):

hexpru bin.cmd PRU_tests.out

This results in two files text.bin and data.bin which later have to be 
loaded into instruction- and data-RAM of PRU. Now one can start with the 
code running on AM3358 that initialises PRU0. First some definitions are 
necessary that contain register-addresses:

#define HWREG(x) (*((volatile unsigned int *)(x)))

#define CM_PER_PRU_ICSS_CLKCTRL   (0x000000E8u) // set to 0x00000002 to 
enable/wake up

#define CM_PER_PRU_ICSS_CLKSTCTRL            (0x00000140u)  // unset to 
0x00000002 to enable/wake up
#define CM_PER_PRU_ICSS_CLKSTCTRL_UART_GCLK  (0x00000040u)  // activate 
UART clock
#define CM_PER_PRU_ICSS_CLKSTCTRL_IEP_GCLK   (0x00000020u)  // activate IEP 
clock
#define CM_PER_PRU_ICSS_CLKSTCTRL_OCP_GCLK   (0x00000010u)  // activate OCP 
clock

#define PRU_PHYS_BASE_CTRL 0x0000

#define PRUSS_CFG_BASE_SYSCFG 0x0004
#define PRUSS_CFG_BASE_GPCFG0 0x0008
#define PRUSS_CFG_BASE_GPCFG1 0x000C
#define PRUSS_CFG_BASE_CGR    0x0010
#define PRUSS_CFG_BASE_PIN_MX 0x0040
#define PRUSS_CFG_BASE_PMAO   0x0028

And the code that initialises PRU's required clocks, copies text.bin and 
data.bin into related RAM-areas, specifies start-address taken out of MAP 
file and starts the whole thing:

   volatile int i=0;

   // reset the PRU, this may not be necessary in case of initial start-up
   HWREG(SOC_PRM_PER_REGS)|=0x00000002;
   while ((HWREG(SOC_PRM_PER_REGS) & 0x00000002)==0); //wait until reset 
was done
   HWREG(SOC_PRM_PER_REGS)&=0xFFFFFFFD; // clear reset bit

   // wake-up and nebale PRU, enable OCP-clock (mandatory)
   // UART and IEP clock have to be enabled here too when needed
   HWREG(SOC_CM_PER_REGS+CM_PER_PRU_ICSS_CLKCTRL)=0x00000002;
   HWREG(SOC_CM_PER_REGS+CM_PER_PRU_ICSS_CLKSTCTRL)=(
CM_PER_PRU_ICSS_CLKSTCTRL_OCP_GCLK);

   // have a short delay before next step
   while (i<10000)
   {
      i++;
   }
   HWREG(PRUSS_CFG_BASE+PRUSS_CFG_BASE_SYSCFG)=(0x00000005);
   while ((HWREG(PRUSS_CFG_BASE+PRUSS_CFG_BASE_SYSCFG) & 0x00000020)!=0); // 
check wait state bit

   // copy text and data into PRU0 instruction and data RAM
   memcpy((void*)PRU0IRAM_PHYS_BASE,(void*)text_bin,sizeof(text_bin));
   memcpy((void*)DATARAM0_PHYS_BASE,(void*)data_bin,sizeof(data_bin));

   // set start address and execute
   HWREG(PRU0CONTROL_PHYS_BASE+PRU_PHYS_BASE_CTRL)|=0x04200000; // set 
start address
   HWREG(PRU0CONTROL_PHYS_BASE+PRU_PHYS_BASE_CTRL)|=0x00000002; // execute


The delay before writing 0x00000005 into SYSCFG-register is necessary for 
some reason, I don't know if this is a good solution or if there is a 
wait-/ready-bit to be checked somewhere.

The start-address where execution of PRU-code has to begin can be found in 
created MAP-file. There an entry

00000420   _c_int00_noinit_noargs_noexit

can be found. _c_int00_noinit_noargs_noexit is the entry point for code 
generated with TI's C-compiler and 00000420 is it's address. It has to be 
shifted up by 16 bit and written into CTRL-register.

Any comments, ideas, improvements are welcome! And feel free to use this 
code without any restrictions.

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to