AnsweredAssumed Answered

STM32F722IEK6 processor not counting properly

Question asked by Brian Dang on Apr 21, 2018
Latest reply on Apr 24, 2018 by Brian Dang

STM32F722IEK6 customer board, Eclipse Neon 3 Release (4.6.3)

 

Hello All,

I am having a weird problem that the processor/compiler seems not behaving normal. The for-loop delay counter

for(m=0; m<1500; m++);

running in the Canon_w() routine takes much longer than should be to finish whenever I run the delay loop below at the end of Canon_read() routine.

rd_clk_hi_delay:

            for(n=0; n<1500; n++);    // delay before next command

 

If this loop (in Canon_r() )  was commented out then the delay loop in Canon_w() runs correctly. Why?

I attach two scope captures showing the GPIOF goes high before and goes low after the delay.

The good one shows the delay in the Canon_w() with about 18usec, and the bad one with 268usec  

There is no interrupt routines running as I'm aware. 

Could someone please help to explain what I am doing wrong here? 

Thank you,

Brian 

 

 

 

 

 

Main()

{

  // start writing to Canon:

    SPI2->CR1 = 0x037F; // enable SPI to generate rising edge on sclk and trigger the 9bit serial spi decode of picoscope

    // Add delay here from clk rising edge to first TX data clk: 100us

  for(n=0; n<5000; n++);

// infinite loop here to capture on scope:

Canon_init:

       while(!(GPIOF->IDR & 0x100)); // wait until clk (PF8) is high again           

       

       Canon_w(0x0A);

       Canon_read();

       Canon_w(0x0A);

       Canon_read();

       goto Canon_init;

 

}

// //////////////////////////////////////////////////////////////////////////////////////////

 

       unsigned char Canon_read()

       {

              unsigned int temp1;

              unsigned int n;

 

              // the next two lines for clearing any overflow error flag before loading

              temp1=SPI2->DR;

              temp1=SPI2->SR;            //

              while(!(SPI2->SR & 2));          // wait if TX buffer not empty

              *(volatile uint8_t*)&SPI2->DR = 0;      // make 8 clk to reading data

              while(!(SPI2->SR & 1));          // wait for RX buffer full then read the data:

              temp1=SPI2->DR;            // read data

              GPIOF->ODR |=2;            // Hi on IOF pin before delay and low after delay loop

              for(n=0; n<1500; n++);                  // delay for garantee CLK's ACK went low before checking ACK going high. was 2000

              GPIOF->ODR &=~2;

              // check pin PF7 for sclk signal busy stat: Low means lens busy

              while(!(GPIOF->IDR & 0x100)); // wait until clk (PF8) is high again

              // This next delay loop will cause problem in the Canon_w() delay loop, but why?

              // comment out this loop then Canon_w() runs OK

rd_clk_hi_delay:

//            for(n=0; n<1500; n++);    // delay before next command

              return((unsigned char)temp1);

       }

 

       // check pin PF8 for sclk signal busy stat:

       void Canon_w(unsigned int command)            // send command to lens

       {

              unsigned int temp1;

              unsigned int m;

 

              // the next two lines for clearing any overflow error flag before loading

              temp1=SPI2->DR;

              temp1=SPI2->SR;            //

              while(!(SPI2->SR & 2));          // wait if TX buffer not empty

              *(volatile uint8_t*)&SPI2->DR = command;      //

              while(!(SPI2->SR & 1));          // wait for RX buffer full then read the data:

              temp1=SPI2->DR;                         // read data

              // The next delay loop runs much longer than it should whenever rd_clk_hi_delay loop is enable (see Canon_read())

              GPIOF->ODR |=2;

              for(m=0; m<1500; m++);                  // 2500 delay for garantee CLK's ACK went low before checking ACK going high. (1400 is right on)

              GPIOF->ODR &=~2;

              while(!(GPIOF->IDR & 0x100)); // wait until clk is high again

wr_clk_hi_delay:

              for(m=0; m<1500; m++);    // delay before next command

       }

 

Here is the Disassembly code of the two subroutines with the debugger:

I can't find anything wrong in the code that can cause the loop counter to run so long:

 

Canon_read:
08003778: ldr r3, [pc, #96] ; (0x80037dc <Canon_read+100>)
0800377a: ldr r2, [r3, #12]
2169 temp1=SPI2->SR; //
0800377c: ldr r3, [r3, #8]
2170 while(!(SPI2->SR & 2)); // wait if TX buffer not empty
0800377e: ldr r3, [pc, #92] ; (0x80037dc <Canon_read+100>)
08003780: ldr r3, [r3, #8]
08003782: tst.w r3, #2
08003786: beq.n 0x800377e <Canon_read+6>
2171 *(volatile uint8_t*)&SPI2->DR = 0; // make 8 clk to reading data
08003788: movs r2, #0
0800378a: ldr r3, [pc, #84] ; (0x80037e0 <Canon_read+104>)
0800378c: strb r2, [r3, #0]
2172 while(!(SPI2->SR & 1)); // wait for RX buffer full then read the data:
0800378e: ldr r3, [pc, #76] ; (0x80037dc <Canon_read+100>)
08003790: ldr r3, [r3, #8]
08003792: tst.w r3, #1
08003796: beq.n 0x800378e <Canon_read+22>
2173 temp1=SPI2->DR; // read data
08003798: ldr r3, [pc, #64] ; (0x80037dc <Canon_read+100>)
0800379a: ldr r0, [r3, #12]
2174 GPIOF->ODR |=2; // Hi on IOF pin before delay and low after delay loop
0800379c: ldr r2, [pc, #68] ; (0x80037e4 <Canon_read+108>)
0800379e: ldr r3, [r2, #20]
080037a0: orr.w r3, r3, #2
080037a4: str r3, [r2, #20]
2175 for(n=0; n<1500; n++); // delay for garantee CLK's ACK went low before checking ACK going high. was 2000
080037a6: movs r3, #0
080037a8: b.n 0x80037ac <Canon_read+52>
080037aa: adds r3, #1
080037ac: movw r2, #1499 ; 0x5db
080037b0: cmp r3, r2
080037b2: bls.n 0x80037aa <Canon_read+50>
2176 GPIOF->ODR &=~2;
080037b4: ldr r2, [pc, #44] ; (0x80037e4 <Canon_read+108>)
080037b6: ldr r3, [r2, #20]
080037b8: bic.w r3, r3, #2
080037bc: str r3, [r2, #20]
2178 while(!(GPIOF->IDR & 0x100)); // wait until clk (PF8) is high again
080037be: ldr r3, [pc, #36] ; (0x80037e4 <Canon_read+108>)
080037c0: ldr r3, [r3, #16]
080037c2: tst.w r3, #256 ; 0x100
080037c6: beq.n 0x80037be <Canon_read+70>
080037c8: movs r3, #0
080037ca: b.n 0x80037ce <Canon_read+86>
2182 for(n=0; n<1500; n++); // delay before next command
080037cc: adds r3, #1
080037ce: movw r2, #1499 ; 0x5db
080037d2: cmp r3, r2
080037d4: bls.n 0x80037cc <Canon_read+84>
2184 }
080037d6: uxtb r0, r0
080037d8: bx lr
080037da: nop
080037dc: subs r0, #0
080037de: ands r0, r0
080037e0: subs r0, #12
080037e2: ands r0, r0
080037e4: asrs r0, r0, #16
080037e6: ands r2, r0
2193 temp1=SPI2->DR;
Canon_w:
080037e8: ldr r3, [pc, #92] ; (0x8003848 <Canon_w+96>)
080037ea: ldr r2, [r3, #12]
2194 temp1=SPI2->SR; //
080037ec: ldr r3, [r3, #8]
2195 while(!(SPI2->SR & 2)); // wait if TX buffer not empty
080037ee: ldr r3, [pc, #88] ; (0x8003848 <Canon_w+96>)
080037f0: ldr r3, [r3, #8]
080037f2: tst.w r3, #2
080037f6: beq.n 0x80037ee <Canon_w+6>
2196 *(volatile uint8_t*)&SPI2->DR = command; //
080037f8: uxtb r3, r0
080037fa: ldr r2, [pc, #80] ; (0x800384c <Canon_w+100>)
080037fc: strb r3, [r2, #0]
2197 while(!(SPI2->SR & 1)); // wait for RX buffer full then read the data:
080037fe: ldr r3, [pc, #72] ; (0x8003848 <Canon_w+96>)
08003800: ldr r3, [r3, #8]
08003802: tst.w r3, #1
08003806: beq.n 0x80037fe <Canon_w+22>
2198 temp1=SPI2->DR; // read data
08003808: ldr r3, [pc, #60] ; (0x8003848 <Canon_w+96>)
0800380a: ldr r3, [r3, #12]
2200 GPIOF->ODR |=2;
0800380c: ldr r2, [pc, #64] ; (0x8003850 <Canon_w+104>)
0800380e: ldr r3, [r2, #20]
08003810: orr.w r3, r3, #2
08003814: str r3, [r2, #20]
2201 for(m=0; m<1500; m++); // 2500 delay for garantee CLK's ACK went low before checking ACK going high. (1400 is right on)
08003816: movs r3, #0
08003818: b.n 0x800381c <Canon_w+52>
0800381a: adds r3, #1
0800381c: movw r2, #1499 ; 0x5db
08003820: cmp r3, r2
08003822: bls.n 0x800381a <Canon_w+50>
2202 GPIOF->ODR &=~2;
08003824: ldr r2, [pc, #40] ; (0x8003850 <Canon_w+104>)
08003826: ldr r3, [r2, #20]
08003828: bic.w r3, r3, #2
0800382c: str r3, [r2, #20]
2203 while(!(GPIOF->IDR & 0x100)); // wait until clk is high again
0800382e: ldr r3, [pc, #32] ; (0x8003850 <Canon_w+104>)
08003830: ldr r3, [r3, #16]
08003832: tst.w r3, #256 ; 0x100
08003836: beq.n 0x800382e <Canon_w+70>
08003838: movs r3, #0
0800383a: b.n 0x800383e <Canon_w+86>
2205 for(m=0; m<1500; m++); // delay before next command
0800383c: adds r3, #1
0800383e: movw r2, #1499 ; 0x5db
08003842: cmp r3, r2
08003844: bls.n 0x800383c <Canon_w+84>
2206 }
08003846: bx lr
08003848: subs r0, #0
0800384a: ands r0, r0
0800384c: subs r0, #12
0800384e: ands r0, r0
08003850: asrs r0, r0, #16
08003852: ands r2, r0

Outcomes