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.

Starterware/AM3358: How to drive PRU outputs in assembly

Part Number: AM3358

Tool/software: Starterware

Hello everybody,

I'm doing some tests with a BBB, and I would like to drive four outputs with PRU1.

As starting point, I've cleaned the PruDemo project, contained inside the pru software support package, leaving included only PRU_LED0 and PRU_LED1

With the code below I can drive the output GPIO2[22], GPIO2[23], GPIO2[24], GPIO2[25], making them toggling.

file pru_cape_demo.c

int main(void)
{
//sets pin mux for PRU cape
PRUCapePinmux();

//Sets and Enables clock, Zeros memory, resets PRU

PRUICSSInit();

UARTInit();

LEDTest();

}

int LEDTest(void)
{

PRUMemLoad(PRU_ICSS1, PRU0_IRAM, 0, sizeof(LED0_INST), (unsigned int*)LED0_INST); // copia da LED0_INST a 0x4A334000

PRUMemLoad(PRU_ICSS1, PRU0_DRAM, 0, sizeof(LED0_DATA), (unsigned int*)LED0_DATA); // copia da LED0_DATA a 0x4A300000

PRUMemLoad(PRU_ICSS1, PRU1_IRAM, 0, sizeof(LED1_INST), (unsigned int*)LED1_INST); // copia da LED1_INST a 0x4A338000
PRUMemLoad(PRU_ICSS1, PRU1_DRAM, 0, sizeof(LED1_DATA), (unsigned int*)LED1_DATA); // copia da LED1_DATA a 0x4A302000

PRUEnable(PRU_ICSS1, PRU0); // scrive 0xb in CTRL a (0x4A300000 + 0x00022000) 4.5.1.1 del trm
PRUEnable(PRU_ICSS1, PRU1); // scrive 0xb in CTRL a (0x4A300000 + 0x00024000) 4.5.1.1 del trm

...

}

void PRUCapePinmux(void)
{
// P8 pin27 -> pr1_pru1_pru_r30[8] -> U5
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_VSYNC) =
(5 << 0) |
(0 << 3) | // attiva Pull
(0 << 4) |
(0 << 5) | // RX
(0 << 6);

// P8 pin29 -> pr1_pru1_pru_r30[9] -> R5
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_HSYNC) =
(5 << 0) |
(0 << 3) | // attiva Pull
(0 << 4) |
(0 << 5) | // RX
(0 << 6);

// P8 pin28 -> pr1_pru1_pru_r30[10] -> V5
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_PCLK) =
(5 << 0) |
(0 << 3) | // attiva Pull
(0 << 4) |
(0 << 5) | // RX
(0 << 6);

// P8 pin30 -> pr1_pru1_pru_r30[11] -> R6
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_AC_BIAS_EN) =
(5 << 0) |
(0 << 3) | // attiva Pull
(0 << 4) |
(0 << 5) | // RX
(0 << 6);

}

Inside the PRU_LED1 project, this code works correctly.

void main(void)
{
 /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
 CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

 /*****************************************************************/
 /* Access PRU Shared RAM using Constant Table */
 /*****************************************************************/


 /* C28 defaults to 0x00000000, we need to set bits 23:8 to 0x0120 in order to have it point to 0x00012000 */

 PRU1_CTRL.CTPPR0_bit.C28_BLK_POINTER = 0x0120;

 /* Ensure CT_DDR (C31) is pointing to DDR memory (0x80001000) */

 PRU1_CTRL.CTPPR1_bit.C31_BLK_POINTER = 0x0010; // (0x80001000)

 gpio = 0x0F00;
 __R30 = gpio;       // all 4 leds on

 /* Toggle the LEDs */
 while (1)
 {
  __R30 = 0x000; // all 4 leds off
  __delay_cycles(10);
  __R30 = gpio; // all 4 leds on
  __delay_cycles(10);
 }

 /* Halt PRU core */
 __halt();
}

Now, I disable this code, and I insert an .asm file inside the project PRU_LED1 , containing this code

.asg r0, r_data_addr

.asg r1, r_data_len
.asg r4, r_gpio2_zeros
.asg r6, r_bit_num
.asg r7, r_sleep_counter
.asg r8, r_temp_addr
.asg r9, r_temp1
.asg r10, r_data0
.asg r11, r_data1
.asg r12, r_data2
.asg r13, r_data3
.asg r22, r_gpio2_mask
.asg r26, r_gpio2_addr
.asg r28, r_temp2

.asg 0x481AC000, GPIO2

.asg 0x190, GPIO_CLEARDATAOUT ; 25.4.1.25
.asg 0x194, GPIO_SETDATAOUT ; 25.4.1.26 TRM

.asg 20, PRU1_ARM_INTERRUPT
.asg 0x24000, PRU_CONTROL_ADDRESS
.asg 0x24028, CTPPR_0
.asg 0x2402C, CTPPR_1

CONST_PRUDRAM .set C24
CONST_SHAREDRAM .set C28
CONST_L3RAM .set C30
CONST_DDR .set C31

.global main

; gpio2-22,23,24,25

main:


LBCO &r0, C4, 4, 4 
CLR r0, r0, 4 
SBCO &r0, C4, 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).
LDI32 r0, 0x00000120
LDI32 r1, CTPPR_0 
SBBO &r0,r1,0x00,4

; 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).
LDI32 r0, 0x00100000
LDI32 r1, CTPPR_1
SBBO &r0,r1,0x00,4


qua:

  ; Load the address(es) of the GPIO devices
  LDI32 r_gpio2_mask, 0x03c00000 
  LDI32 r_gpio2_addr, (GPIO2 | GPIO_CLEARDATAOUT)
  SBBO &r_gpio2_mask, r_gpio2_addr, 0, 4

  LBCO &r5, c31, 0, 4
  ADD r5, r5, 0x01             ; counter to be read @ 0x80001000
  SBCO &r5, c31, 0, 4

  LDI32 r_gpio2_mask, 0x03c00000
  LDI32 r_gpio2_addr, GPIO2 | GPIO_SETDATAOUT
  SBBO &r_gpio2_mask, r_gpio2_addr, 0, 4

JMP qua

...

Here my problems begin.

It run, and debugging from the PruDemo I can see R5 counting throught an 0x80001000 memory readout, but the outputs don't toggle.

I don't understand what I'm missing.

Someone can help me ?

Mario

  • Hi Mario,

    How are you checking the value of 0x80001000? Are you using CCS to debug your code?

    If you're using CCS, I'd suggest halting the PRU and stepping through your code in the Disassembly window, checking that the PRU registers and GPIO2 registers are what you expect. To view the PRU registers, you can using the Registers window. To view the GPIO2 registers, I'd suggest clicking on the ARM core in the Debug window and entering the memory address in the Memory Browser window. (You won't be able to access these registers while you have the PRU selected in the Debug window.)

    Also, are you setting the correct pinmux value for the GPIO2 in the Pad Control registers? An incorrect pinmux setting would prevent the I/O from toggling, even if your PRU assembly code is correct.

    Regards,
    Melissa