Part Number: AM3354
Tool/software: TI C/C++ Compiler
Hi!
I've been using the PASM-compiler, but decided to change my code to fit with the recommended clpru compiler. (For BeagleBone Black) Previously i've been able to
compile the source code directly to '.bin' and upload it using the prussdrv.h execute command, but clpru gives me an '.obj' and '.out'-flie. I've been looking for answers with linking '.obj'-files, but didn't find any good answers. Do anyone have a brief explanation of how my code should be linked to get the '.bin' file, alternatively other options using the '.obj'-file?
Until now i've loaded the '.obj'-file using prussdrv_exec_program(PRUNUM, "PROGRAM FILE").
This did however not work with JAL, with .asg i predefined a CALL_REG to store return address, but when running it gives no indication of jumping or returning.
;******************************************************************************
;* PRU C/C++ Codegen Unix v2.1.4 *
;* Date/Time created: Tue Mar 21 04:57:50 2017 *
;******************************************************************************
.compiler_opts --abi=eabi --endian=little --hll_source=on --object_format=elf --silicon_version=3 --symdebug:none
; optpru --call_assumptions=3 --gen_opt_info=2 /tmp/08571jbUso2 /tmp/08571YOCaL9 --opt_info_filename=empty.nfo
; acpiapru -@/tmp/08571SM9heD
.sect ".text:main"
.clink
.global ||main||
;***************************************************************
;* FNAME: main FR SIZE: 0 *
;* *
;* FUNCTION ENVIRONMENT *
;* *
;* FUNCTION PROPERTIES *
;* 0 Auto, 0 SOE *
;***************************************************************
||main||:
;* --------------------------------------------------------------------------*
ZERO &r14, 4 ; [ALU_PRU] |2|
JMP r3.w2 ; [ALU_PRU]
.asg "0", MOSI ;r30_0 (P9.31)
.asg "1", MISO ;r31_1 (P9.29)
.asg "2", SPI_SCLK ;r31_2 (P9.30)
.asg "3", CS_PIN ;r30_3 (P9.28)
.asg "r30", PIN_OUT
.asg "r31", PIN_IN
.asg "32", PRU0_R31_VEC_VALID ; allows notification of program completion
.asg "1" , PRU_EVTOUT_0 ;he event number that is sent back
.asg "r0", CLOCK_STATE
.asg "r30.w0", CALL_REG ;Call register for returning from instruction
.asg "r1", DATA_SIZE ;Outgoing data size(from host) [bytes]
.asg "r2", DATA_OUT ;Outgoing data (from host)
.asg "r3", DATA_IN ;Incoming data (from slave)
.asg "r4", DATA_OUT_OFFSET ;Keep track of data loading from registers
.asg "r5", DATA_IN_OFFSET ;Keep track of data loading to registers
.asg "r6", BIT_COUNTER ;Counts bits to decrement bytes
.asg "r7", SHARED_RAM_OFFSET ;Holds start address of PRU Shared RAM
.asg "r8", CTRL_REG ;Holds signals from/to master
.asg "r9", TEMP_CONST_REG ;Temporarily hold constants to MOV
.asg "r10", TEST_REG
START:
; Enable the OCP master port -- allows transfer of data to Linux userspace
LBCO &r0, C4, 4, 4 ; load SYSCFG reg into r0 (use c4 const addr)
CLR r0, r0, 4 ; clear bit 4 (STANDBY_INIT)
SBCO &r0, C4, 4, 4 ; store the modified r0 back at the load addr
LDI32 DATA_OUT_OFFSET, 8 ;Data to write starts at third register (first loaded manually)
LBBO &DATA_OUT, SHARED_RAM_OFFSET, 4, 4 ;Loads first 4 bytes of data sent from host
LDI32 DATA_IN_OFFSET, 28 ;Start-offset used to send read data to host
LDI32 BIT_COUNTER, 31
LDI32 SHARED_RAM_OFFSET, 0x10000
SET PIN_OUT, PIN_OUT, CS_PIN
QBA WAIT_FOR_SIGNAL
WAIT_FOR_SIGNAL:
LBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4 ;Load signals from host
QBBC WAIT_FOR_SIGNAL, CTRL_REG, 0 ;Repeat if LSB = 0
CLR CTRL_REG, CTRL_REG, 0
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
QBA GET_DATA_SIZE
GET_DATA_SIZE:
LBBO &DATA_SIZE, SHARED_RAM_OFFSET, 4, 4 ;Aquire size of data to be transmitted
QBA WAIT_FOR_TRANSMISSION
WAIT_FOR_TRANSMISSION:
JAL CALL_REG, CHECK_CLOCK_LOW ;Check clock, r <---------------This JAL does not work
CLR PIN_OUT, PIN_OUT, CS_PIN ;Initiate communication
;Section responsible for sending/receiving data:
WRITE_BIT:
LDI32 CTRL_REG, 3
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
SUB BIT_COUNTER, BIT_COUNTER, 1 ;Decrement counter
QBBC WRITE_LOW, DATA_OUT, 31 ;Check if bit 31 DATA_OUT is low
WRITE_HIGH:
LDI32 CTRL_REG, 4
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
SET PIN_OUT, PIN_OUT, MOSI
LSL DATA_OUT, DATA_OUT, 1
QBA READ_BIT
WRITE_LOW:
LDI32 CTRL_REG, 5
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
CLR PIN_OUT, PIN_OUT, MOSI
LSL DATA_OUT, DATA_OUT, 1
READ_BIT:
LDI32 CTRL_REG, 6
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
JAL CALL_REG, CHECK_CLOCK_LOW
QBBC READ_LOW, PIN_IN, MISO
READ_LOW:
LDI32 CTRL_REG, 7
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
CLR DATA_IN, DATA_IN, 1
LSL DATA_IN, DATA_IN, 1
QBNE WRITE_BIT, BIT_COUNTER,0
QBA STORE_LOAD_DECREMENT
READ_HIGH:
LDI32 CTRL_REG, 8
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
SET DATA_IN, DATA_IN, 1
LSL DATA_IN, DATA_IN, 1
QBNE WRITE_BIT, BIT_COUNTER, 0
QBA STORE_LOAD_DECREMENT
;End of send/receive-section
STORE_LOAD_DECREMENT:
LDI32 CTRL_REG, 9
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
;STORE:
SBBO &DATA_IN, SHARED_RAM_OFFSET, DATA_IN_OFFSET, 4
ADD DATA_IN_OFFSET, DATA_IN_OFFSET, 4 ;Update counter for unused registers
;LOAD:
LBBO &DATA_OUT, SHARED_RAM_OFFSET, DATA_OUT_OFFSET, 4
ADD DATA_OUT_OFFSET, DATA_OUT_OFFSET, 4 ;Update counter for unsent data
;DECREMENT:
SUB DATA_SIZE, DATA_SIZE, 4 ;Decrement number of bytes
LDI32 BIT_COUNTER, 31 ;Reset bit counter
QBNE WRITE_BIT, DATA_SIZE, 0 ;Keep sending bytes until all data sent
LDI r31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0 ;Transmission done, alert host
QBA WAIT_FOR_SIGNAL ;Wait for new data
CHECK_CLOCK_LOW:
;/////////TEST////////////
;LDI32 CTRL_REG,10
;SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
;;;//END_TEST/////////////
QBBS CHECK_CLOCK_LOW, PIN_OUT, SPI_SCLK
JMP CALL_REG
CHECK_CLOCK_HIGH:
LDI CTRL_REG, 11
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
QBBC CHECK_CLOCK_HIGH, PIN_OUT, SPI_SCLK
JMP CALL_REG
END:
LDI32 CTRL_REG, 190
SBBO &CTRL_REG, SHARED_RAM_OFFSET, 0, 4
LDI r31.b0, PRU0_R31_VEC_VALID | PRU_EVTOUT_0
HALT
/////////C-Code for uploading program to PRU and communicating with it:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <prussdrv.h>
#include <pruss_intc_mapping.h>
#define ADC_PRU_NUM 0 // using PRU0 for the ADC capture
#define CLK_PRU_NUM 1 // using PRU1 for the sample clock
#define DATA_IN_OFFSET 28
enum CONTROL {
PAUSED = 0,
RUNNING = 1,
UPDATE = 3
};
int main (void)
{
prussdrv_init();
if(getuid()!=0){
printf("You must run this program as root. Exiting.\n");
exit(EXIT_FAILURE);
}
prussdrv_open(PRU_EVTOUT_0);
// Initialize structure used by prussdrv_pruintc_intc
// PRUSS_INTC_INITDATA is found in pruss_intc_mapping.h
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
prussdrv_pruintc_init(&pruss_intc_initdata);
volatile void *shared_memory_void = NULL;
volatile uint32_t *shared_memory = NULL;
prussdrv_map_prumem(PRUSS0_SHARED_DATARAM, (void**) &shared_memory_void);
shared_memory = (uint32_t*) shared_memory_void;
uint32_t ctrl_Reg = 1;
uint32_t writeData[6];
writeData[0] = 61;
writeData[1] = 104;
for (int i = 0; i < 4; i++)
{
writeData[i+2] = 0;
}
for (int i = 0; i < 6; i++)
{
shared_memory[i+2] = writeData[i];
}
shared_memory[0] = 1;
shared_memory[1] = 200;
//prussdrv_pru_write_memory(PRUSS0_SHARED_DATARAM, 0, ctrl_Reg, 4);
//prussdrv_pru_write_memory(PRUSS0_SHARED_DATARAM, 4, writeData, 24);
// Load and execute the PRU program on the PRU
prussdrv_exec_program (ADC_PRU_NUM, "./test.obj");
printf("PRU running, waiting for transmission... %d\n", shared_memory[0]);
while(shared_memory[0] != 0)
{
}
printf("PRU transmission started, shared_memory[0] = %d.\n", shared_memory[0]);
uint32_t shared_memory_old = 0;
//printf("change in value: %d\n", shared_memory[0]);
while(shared_memory[0] != 190)
{
if (shared_memory[0] != shared_memory_old);
{
printf("%d\n", shared_memory[0]);
shared_memory_old = shared_memory[0];
}
}
printf("End of program");
// Disable PRU and close memory mappings
prussdrv_pru_disable(ADC_PRU_NUM);
prussdrv_pru_disable(CLK_PRU_NUM);
prussdrv_exit ();
return EXIT_SUCCESS;
}