Hi all,
I had a few hours to play with the pruss, but I came to a dead end…
My goal is to read ADCs, ADS8326 to be precise.
It’s a kind of SPI adc with one clock, one select, one out.
I’d like to use 4 in parallel, which means only one clock, one select and 4 inputs on the PRUSS.
I try to pull up CLK line and then read each input, shift them into variables to be sent to main app.
When I look at the CLK line on a scope, it’s taking way too much time to get input states and shift even if the asm code should only take a few cycles.
I’m lazy, I write the pruss code in C, but asm looks nice.
Here’s the code in C
#define ADC1 (1 << 14)
#define ADC2 (1 << 15)
#define ADC3 (1 << 16)
#define ADC4 (1 << 17)
#define SOC_GPIO_1_REGS (0x4804C000)
#define SOC_GPIO_3_REGS (0x481AE000)
#define GPIO_PIN_LOW (0x0)
#define GPIO_PIN_HIGH (0x1)
#define GPIO_CLEARDATAOUT (0x190)
#define GPIO_SETDATAOUT (0x194)
#define GPIO_DATAIN (0x138)
#define GPIO_DATAOUT (0x13C)
#define GPIO_OE (0x134)
#define HWREG(x) (*((volatile unsigned int *)(x)))
#define ADC_CLK_PIN 12
#define ADC_CS_PIN 13
#define ADC_CLK_HI (HWREG(SOC_GPIO_1_REGS + GPIO_SETDATAOUT) = (1 << ADC_CLK_PIN))
#define ADC_CLK_LOW (HWREG(SOC_GPIO_1_REGS + GPIO_CLEARDATAOUT) = (1 << ADC_CLK_PIN))
#define ADC_CS_HI (HWREG(SOC_GPIO_1_REGS + GPIO_SETDATAOUT) = (1 << ADC_CS_PIN))
#define ADC_CS_LOW (HWREG(SOC_GPIO_1_REGS + GPIO_CLEARDATAOUT) = (1 << ADC_CS_PIN))
#define PRU0_ARM_INTERRUPT 19
#define SYSCFG (*(&C4+0x01))
int C4 attribute((cregister(“MEM”,near),peripheral)); //only compatible with v1.1.0B1 +
//add following lines to MEMORY{} in lnk.cmd
//PAGE 2:
// MEM : o = 0x00026000 l = 0x00002000 CREGISTER=4
volatile register unsigned int __R31;
void main()
{
/Intialise OCP Master port for accessing external memories/
SYSCFG&=0xFFFFFFEF;
ocp_init();
shm_init();
/Start Main Code/
int i,j;
unsigned int sensor_1=0, sensor_2=0, temp=0;
HWREG(SOC_GPIO_1_REGS + GPIO_OE) &= ~(1 << ADC_CLK_PIN); // output
HWREG(SOC_GPIO_1_REGS + GPIO_OE) &= ~(1 << ADC_CS_PIN); // output
HWREG(SOC_GPIO_3_REGS + GPIO_OE) |= ADC1; // input
HWREG(SOC_GPIO_3_REGS + GPIO_OE) |= ADC2; // input
HWREG(SOC_GPIO_3_REGS + GPIO_OE) |= ADC3; // input
HWREG(SOC_GPIO_3_REGS + GPIO_OE) |= ADC4; // input
ADC_CLK_HI;
DELAY1;
while (1)
{
ADC_CLK_HI;
asm volatile
(
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
" NOP \n"
);
//READ
sensor_1 |= (HWREG(SOC_GPIO_3_REGS + GPIO_DATAIN) & ADC1);
sensor_1 |= ((HWREG(SOC_GPIO_3_REGS + GPIO_DATAIN) & ADC2)<<16);
sensor_2 |= (HWREG(SOC_GPIO_3_REGS + GPIO_DATAIN) & ADC3);
sensor_2 |= ((HWREG(SOC_GPIO_3_REGS + GPIO_DATAIN) & ADC4)<<16);
ADC_CLK_LOW;
if (j!=15)
{
// shift bits
sensor_1 = sensor_1 << 1;
sensor_2 = sensor_2 << 1;
}
delay_100();
}
Relevant part reading sensor_1 in asm:
.dwpsn file “adc_pru.c”,line 154,column 4,is_stmt,isa 0
LDI r0, 0x4000 ; [] |154|
LDI32 r1, 0x481ae138 ; [] |154|
LBBO &r1, r1, 0, 4 ; [] |154|
AND r0, r1, r0 ; [] |154|
LBBO &r1, r2, 8, 4 ; [] |154| sensor_1
OR r0, r1, r0 ; [] |154|
SBBO &r0, r2, 8, 4 ; [] |154| sensor_1
.dwpsn file “adc_pru.c”,line 155,column 4,is_stmt,isa 0
LDI r0, 0x8000 ; [] |155|
LDI32 r1, 0x481ae138 ; [] |155|
LBBO &r1, r1, 0, 4 ; [] |155|
AND r0, r1, r0 ; [] |155|
LSL r0, r0, 0x10 ; [] |155|
LBBO &r1, r2, 8, 4 ; [] |155| sensor_1
OR r0, r1, r0 ; [] |155|
SBBO &r0, r2, 8, 4 ; [] |155| sensor_1
My great trouble is that it takes to much time, in fact way too much.
Using this code, the CLK line is at 757 Khz.
CLK hi is around 1us and low is the rest…
I’d like to achieve at least 2Mhz for CLK line.
I might have misread the doc, but isn’t an instruction supposed to be 5ns ?
That should be 35ns for first part and 40ns for second part.
Any clue or help ?
The learning curve is a bit harder than I tought
Thanks