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.

long long comparison issue

Other Parts Discussed in Thread: AM3359

hello,

I use clpru compiler for am3359's PRU. Here is a code which seems to work in a wrong way:

volatile long long time=0, adcTime=0;	
while (1) { adcTime = time; time+=1000; if (time >= adcTime + (long long)(20000)) { msg(time, adcTime); break; } }

"if" fires when (adcTime + 20000) becomes greater when 2^32.

msg: 4294949000( 4294948000 )

here asm part:

;* --------------------------------------------------------------------------*
;*   BEGIN LOOP ||$C$L18||
;*
;*   Loop source line                : 136
;*   Loop closing brace source line  : 144
;*   Known Minimum Trip Count        : 1
;*   Known Maximum Trip Count        : 4294967295
;*   Known Max Trip Count Factor     : 1
;* --------------------------------------------------------------------------*
||$C$L18||:    
	.dwpsn	file "pru_main.c",line 137,column 3,is_stmt,isa 0
        LDI       r0, ||time||          ; [ALU_PRU] |137| time
        LBBO      &r0, r0, 0, 8         ; [ALU_PRU] |137| 
        SBBO      &r0, r2, 68, 8        ; [ALU_PRU] |137| adcTime
	.dwpsn	file "pru_main.c",line 139,column 3,is_stmt,isa 0
        LDI       r14, ||time||         ; [ALU_PRU] |139| time
        LDI       r16, 0x03e8           ; [ALU_PRU] |139| 
        ZERO      &r15, 4               ; [ALU_PRU] |139| 
        LBBO      &r0, r14, 0, 8        ; [ALU_PRU] |139| 
        ADD       r0, r16, r0           ; [ALU_PRU] |139| 
        ADC       r1, r15, r1           ; [ALU_PRU] |139| 
        SBBO      &r0, r14, 0, 8        ; [ALU_PRU] |139| 
	.dwpsn	file "pru_main.c",line 140,column 3,is_stmt,isa 0
        LDI       r15, 0x4e20           ; [ALU_PRU] |140| 
        ZERO      &r14, 4               ; [ALU_PRU] |140| 
        LBBO      &r0, r2, 68, 8        ; [ALU_PRU] |140| adcTime
        ADC       r14, r14, r1          ; [ALU_PRU] |140| 
        ADD       r15, r15, r0          ; [ALU_PRU] |140| 
        XOR       r14.b3, r14.b3, 0x80  ; [ALU_PRU] |140| 
        LDI       r0, ||time||          ; [ALU_PRU] |140| time
        LBBO      &r0, r0, 0, 8         ; [ALU_PRU] |140| 
        XOR       r1.b3, r1.b3, 0x80    ; [ALU_PRU] |140| 
        QBLT      ||$C$L18||, r14, r1   ; [ALU_PRU] |140| 
;* --------------------------------------------------------------------------*
        QBGT      ||$C$L19||, r14, r1   ; [ALU_PRU] |140| 
;* --------------------------------------------------------------------------*
        QBLT      ||$C$L18||, r15, r0   ; [ALU_PRU] |140| 
;* --------------------------------------------------------------------------*

I'm not so good at asm to understand is right or not. Or may be there is my misunderstanding?

  • Not an expert in PRU assembly, but the second 64-bit add looks wrong: it appears that the carry bit is used (in ADC) before it is produced (in ADD).

    Because the first addition looks different, you might want to avoid the explicit cast of 20000 to long long and maybe assign the result of adcTime + 20000 to a temporary instead of using that expression inside the if.

  • I use the next workaround : if (time - adcTime >= (long long)(20000))

    Now it works but I'd like to draw TI's employee attention to this issue. How to do it?
  • I cannot reproduce the exact same assembly output from the compiler.  I can get close.  But that's not good enough.

    Please preprocess the source file that has this problem.  Attach the resulting preprocessed source file to your next post.  Indicate the name of the function where the problem occurs.  What compiler version do you use?  Please show the compiler build options used. 

    Thanks and regards,

    -George

  • hereis shortened source file.

    the error occur in main() function.

    clpru version:

    v2.1.1
    Build Number 1PCGL-0QRTSXTX-UAYAS-TAQ-ZAFHK_S_R_R

    build command:

    /usr/bin/clpru \

    --silicon_version=2 \

    --hardware_mac=on \

    --keep_asm \

    -i$PRU_CGT_DIR/include \

    -i$PRU_CGT_DIR/lib \

    -O0 \

    -c \

    pru_main.c

    pru_main.asm

    #include <stdint.h>
    
    //volatile register uint32_t __R30;  // Output pins 
    volatile register uint32_t __R31;  // Input pins 
    
    //#define CTRL 0x22000 //Start of control registers
    
    void adc_init_Uc(void)
    {
    	__asm__ __volatile__
    	(
    	//Init ADC CLKDIV
        " LDI32 r8, 0x44E0D04C \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
    	//Init ADC CTRL register to enable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000004 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //ts charge delay
        " LDI32 r8, 0x44E0D060 \n"
    	" LDI32 r9, 0x00000001 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPCONFIG 1
        " LDI32 r8, 0x44E0D064 \n"
    	" LDI32 r9, 0x002A8010 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 1
        " LDI32 r8, 0x44E0D068 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Enable ADC steps //STEPENEBLE mask
        " LDI32 r8, 0x44E0D054 \n"
        " LDI32 r9, 0x0000002 \n"////enable 5 channels
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//disable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    }
    
    void adc_init_I1(void)
    {
    	__asm__ __volatile__
    	(
    	//Init ADC CLKDIV
        " LDI32 r8, 0x44E0D04C \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
    	//Init ADC CTRL register to enable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000004 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //ts charge delay
        " LDI32 r8, 0x44E0D060 \n"
    	" LDI32 r9, 0x00000001 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPCONFIG 1
        " LDI32 r8, 0x44E0D064 \n"
    	//" LDI32 r9, 0x00198010 \n" //AVG16
    	" LDI32 r9, 0x00198008 \n" //AVG4
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 1
        " LDI32 r8, 0x44E0D068 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Enable ADC steps //STEPENEBLE mask
        " LDI32 r8, 0x44E0D054 \n"
        " LDI32 r9, 0x0000002 \n"////enable 5 channels
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//disable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    }
    
    
    void adc_init(void)
    {
    	__asm__ __volatile__
    	(
    	//Init ADC CLKDIV
        " LDI32 r8, 0x44E0D04C \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
    	//Init ADC CTRL register to enable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000004 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //ts charge delay
        " LDI32 r8, 0x44E0D060 \n"
    	" LDI32 r9, 0x00000001 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPCONFIG 1
        " LDI32 r8, 0x44E0D064 \n"
    	" LDI32 r9, 0x00000010 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 1
        " LDI32 r8, 0x44E0D068 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//Init ADC STEPCONFIG 2
        " LDI32 r8, 0x44E0D06C  \n"
        " LDI32 r9, 0x00110010 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 2
        " LDI32 r8, 0x44E0D070 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//Init ADC STEPCONFIG 3
        " LDI32 r8, 0x44E0D074 \n"
        " LDI32 r9, 0x00198010 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 3
        " LDI32 r8, 0x44E0D078 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//Init ADC STEPCONFIG 4
        " LDI32 r8, 0x44E0D07C \n"
        " LDI32 r9, 0x002A8010 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 4
        " LDI32 r8, 0x44E0D080 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//Init ADC STEPCONFIG 5
        " LDI32 r8, 0x44E0D084 \n"
        " LDI32 r9, 0x00330010 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Init ADC STEPDELAY 5
        " LDI32 r8, 0x44E0D088 \n"
    	" LDI32 r9, 0x00000008 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
        //Enable ADC steps //STEPENEBLE mask
        " LDI32 r8, 0x44E0D054 \n"
        " LDI32 r9, 0x0000003E \n"////enable 5 channels
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//disable step editing
        " LDI32 r8, 0x44E0D040 \n"
        " LDI32 r9, 0x00000000 \n"
        " SBBO &r9, r8, 0, 4 \n"
    	);
    }
    
    void adc_start(void)
    {
    	__asm__ __volatile__
    	(
        //Enable ADC steps //STEPENEBLE mask
        " LDI32 r8, 0x44E0D054 \n"
    //    " LDI32 r9, 0x0000003E \n"////enable 5 channels
    	" LDI32 r9, 0x00000002 \n"////enable steps mask
        " SBBO &r9, r8, 0, 4 \n"
    	);
    
    	__asm__ __volatile__
    	(
    	//enables ADC 
        " LDI32 r0, 0x44E0D040 \n"
        " LDI32 r1, 0x00000001 \n"
        " SBBO &r1, r0, 0, 4 \n"
    	);
    }
    
    uint16_t adc_read(register uint32_t x)
    {
      /* must be compiled without optimizations */
    
      /* r2 used for the stack pointer, do not modify */
      /* r3 used for return address, do not modify */
      /* x=r14, y=r15, z=r16 registers used */
      /* r14 used for return values */
    
      __asm__ __volatile__
      (
       /* read fifo */
     "  LDI32 r1, 0x44e0d100 \n" //ADC_MIO_ADDR + ADC_REG_FIFO0DATA \n"
     "  LBBO &r14, r1, 0, 4 \n"
     "  LDI32 r1, 0x0000ffff \n"
     "  AND r14, r14, r1 \n"
     "  JMP R3.w2 \n"
      );
    
      return 0;
    }
    
    uint16_t adc_fifo_stat(register uint32_t x)
    {
      /* must be compiled without optimizations */
    
      /* r2 used for the stack pointer, do not modify */
      /* r3 used for return address, do not modify */
      /* x=r14, y=r15, z=r16 registers used */
      /* r14 used for return values */
    
      __asm__ __volatile__
      (
    
       /* read fifo */
     "  LDI32 r1, 0x44e0d0e4 \n" //ADC_MIO_ADDR + ADC_REG_FIFO0DATA \n"
     "  LBBO &r14, r1, 0, 4 \n"
     "  LDI32 r1, 0x0000007f \n"
     "  AND r14, r14, r1 \n"
     "  JMP R3.w2 \n"
      );
    
      return 0;
    }
    
    void cnt_start(void)
    {
    	__asm__ __volatile__
    	(
    	" LDI32 r8, 0x22000 \n" //set r8 for the lbbo
    	" LBBO &r9, r8, 0, 4 \n" // Get the control register
    	);
    	__asm__ __volatile__
    	(
    	" SET r9, r9, 3 \n" // Set the cycle counter enable
    	" SBBO &r9, r8, 0, 4 \n" // Put back to the register to start
    	);	
    }
    
    void cnt_stop(void)
    {
    	__asm__ __volatile__
    	(
    	" LDI32 r8, 0x22000 \n" //set r8 for the lbbo
    	" LBBO &r9, r8, 0, 4 \n" // Get the control register
    	);
    	__asm__ __volatile__
    	(
    	" CLR r9, r9, 3 \n" // Set the cycle counter enable
    	" SBBO &r9, r8, 0, 4 \n" // Put back to the register to start
    	);	
    }
    
    void cnt_clear(void)
    {
    	__asm__ __volatile__
    	(
    	" LDI32 r8, 0x22000 \n" //set r8 for the lbbo
    	" LDI32 r9, 0 \n" //set r8 for the lbbo
    	" SBBO &r9, r8, 12, 4 \n" // Put back to the register to start
    	);	
    }
    
    uint32_t cnt_get(register uint32_t x)
    {
    	__asm__ __volatile__
    	(
    	" LDI32 r8, 0x22000 \n" //set r8 for the lbbo
    	" LBBO &r14, r8, 0xC, 4 \n" // return value
    	" JMP R3.w2 \n"
    	);
    	//unreachable
    	return 0;
    }
    
    void mem_write_uint32(register uint32_t x, register uint32_t y)
    {
      /* i is the absolute offset relative from shared memory start */
      /* write x at shm + i */
    
      	__asm__ __volatile__
    	(
        " SBBO &r15, r14, 0, 4 \n"
    	);
    }
    
    void ocp_init(void)
    {
      /* enable ocp wide access */
    
      __asm__ __volatile__
      (
       " LBCO &r0, C4, 4, 4 \n"
       " CLR r0, r0, 4 \n"
       " SBCO &r0, C4, 4, 4 \n"
      );
    }
    
    void shm_init(void)
    {
      /* 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). */
    
      /* save r4, r5 */
      __asm__ __volatile__
      (
       " SUB r2, r2, 8 \n"
       " SBBO &r4, r2, 0, 8 \n"
      );
    
      __asm__ __volatile__
      (
       " LDI32 r4, 0x0120 \n"
       " LDI32 r5, 0x22028 \n"
       " SBBO &r4, r5, 0x00, 4 \n"
      );
    
      /* restore r4, r5 */
      __asm__ __volatile__
      (
       " LBBO &r4, r2, 0, 8 \n"
       " ADD r2, r2, 8 \n"
      );
    }
    
    void shm_write_uint32(register uint32_t i, register uint32_t x)
    {
      /* i is the absolute offset relative from shared memory start */
      /* write x at shm + i */
    
      __asm__ __volatile__
      (
       " SBCO &r15, C28, r14.w0, 4 \n"
      );
    }
    
    void shm_write_float(register uint32_t i, register float x)
    {
      __asm__ __volatile__
      (
       " SBCO &r15, C28, r14.w0, 4 \n"
      );
    }
    
    uint32_t shm_read(register uint32_t i, register uint32_t b)
    {
      /* b is the absolute offset relative from shared memory start */
      /* read x at shm + b */
      
      //r14 used for returning value
    
      __asm__ __volatile__
      (
       " LDI32 r0, 0x000000120 \n"
       " LDI32 r1, 0x22028 \n"
       " SBBO &r0, r1, 0, 4 \n"
       " LDI32 r0, 0x00100000 \n"
    
       " LDI32 r1, 0x2202c \n"
       " SBBO &r0, r1, 0, 4 \n"
    
    //   " LBCO &r14, C31, 0, 4 \n"//third operand is the offset
    	" LBCO &r14, C31, r15, 4 \n"//third operand is the offset
       " JMP R3.w2 \n"
      );
    
      /* unreached */
      return 0;
    }
    /*
    void pwm(void)
    {
    	__asm__ __volatile__
    	(
        //EPWM_TBCTL
        " LDI32 r8, 0x48300000 \n"
    	" LDI32 r9, 0x00000503 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_CMPB
        " LDI32 r8, 0x48300014 \n"
    	" LDI32 r9, 0x00001388 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_CMPA
        " LDI32 r8, 0x48300012 \n"
    	" LDI32 r9, 0x00001388 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_TBPRD
        " LDI32 r8, 0x4830000A \n"
    	" LDI32 r9, 0x0000C350 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_TBCNT
        " LDI32 r8, 0x48300008 \n"
    	" LDI32 r9, 0x00000000 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_AQCTLA
        " LDI32 r8, 0x48300016 \n"
    	" LDI32 r9, 0x00000032 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_AQCTLB
        " LDI32 r8, 0x48300018 \n"
    	" LDI32 r9, 0x00000302 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_TBCNT
        " LDI32 r8, 0x48300008 \n"
    	" LDI32 r9, 0x00000000 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    	
    	__asm__ __volatile__
    	(
        //EPWM_TBCTL
        " LDI32 r8, 0x48300000 \n"
    	" LDI32 r9, 0x00000500 \n" 
        " SBBO &r9, r8, 0, 4 \n"
    	);
    }*/
    
    uint32_t di(void)
    {
    	return __R31;
    }
    
    void delay(register uint32_t x)
    {
      __asm__ __volatile__
      (
    	" LDI32 r8, 1000 \n"
    	//" SUB r8, r14, 0 \n"
    	
    	"WAIT: \n"
    	" SUB r8, r8, 1 \n"
    	" QBNE WAIT, r8, 0 \n"
      );
    
    }
    
    pru_hal.h

    #include <stdint.h> 
    #include "pru_hal.h"
    //#include "comm.h"
    
    #define G4 4294967295
    #define TICK_TIME				200//ticks per us
    #define PIN_HIGH(x)				__R30 = __R30 | (1 << x);
    #define PIN_LOW(x)				__R30 = __R30 & ~(1 << x);
    
    #define I_COEF					8.53
    #define IMAX					100
    #define IMIN					50
    #define U_TARG					90
    #define U_TARG_DELTA			1
    #define K						6
    #define PREADC					22 * TICK_TIME
    #define AVG_ARR_SIZE			100
    #define AI_CH_NUM				5
    #define L						56//uH
    #define E						14//V
    #define B1						9//V
    #define B2						15//V
    #define UC_DELAY				70
    #define TAU_RELAX_MAX			1000
    #define TAU_RELAX_MIN			10
    #define STEPS_TO_DO				100000
    #define DEBUG_STEPS				30
    #define K_UC					(float)0.285
    
    volatile register uint32_t __R30;  // Output pins 
    
    volatile uint32_t last_cnt;
    volatile long long time;//, t1, t2, t3;
    volatile uint32_t cnt;
    volatile uint32_t vv;
    volatile uint32_t state, I1, Uc, alg;
    volatile uint32_t cfgU, cfgdU, cfgImax, cfgImin;
    
    void error(uint32_t err, uint32_t add)	
    {
    	shm_write_uint32((PRU_MEM_ERR) * 4, err);
    	shm_write_uint32((PRU_MEM_ERR_ADD) * 4, add);
    	state = PRU_STATE_ERROR;
    }
    
    void msg(uint32_t err, uint32_t add)	
    {
    	shm_write_uint32((PRU_MEM_MSG) * 4, err);
    	shm_write_uint32((PRU_MEM_MSG_ADD) * 4, add);
    }
    
    int main(void)
    {
    	volatile long long dt, charge1Time, charge2Time, UcTime, adcTime, p;
    	volatile uint32_t cur_avg;
    
    	ocp_init();
    	shm_init();
    
    	error(PRU_ERR_NONE, 0);
    	msg(PRU_MSG_NONE, 0);
    
    	cur_avg = time = charge1Time = charge2Time = 0;
    
    	while (1)	{
    		adcTime = time;//время запуска АЦП
    
    		time+=1000;
    		if (time >=  adcTime + (long long)(20000)) {//контролируем что мы не вышли за пределы времени ожидания АЦП
    			msg(time, adcTime);
    			break;
    		}
    	}
    
    	while(1)	{
    		cur_avg++;
    		shm_write_uint32((PRU_AI_DATA_OFFSET + 4) * 4, (uint32_t)cur_avg);
    	}
    
    	__halt();
    	return 0;
    }
    

  • I have not found cl6x on my machine to preprocess sources.
  • Thank you for submitting a test case.  I can reproduce the same error.  I filed SDSCM00052375 in the SDOWP system to have this investigated.  You are welcome to track it with the SDOWP link below in my signature.

    Gigo Dret said:
    I have not found cl6x on my machine to preprocess sources

    You don't need to submit a preprocessed test case any longer.  But to answer your question ... cl6x is the compiler for the TI C6000 family of devices.  Substitute clpru instead.

    Thanks and regards,

    -George