We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi guys,
I use a _global_reg var in my program to avoid save/load:
_global_var uint32_t finished_pixels;
this variable is updated in ADC interrupt.
In main, I have following code:
register uint32_t processed_pixels = 0;
finished_pixels = 0; // Initial global reg
while (processed_pixels >= finished_pixels)
{
// Process new pixel
...
}
But the armcc will optimize all code in while loop, i.e, "// Process new pixel" section.
I tried "volatile _global_var uint32_t finished_pixels;", but the compiler says it has no effect and the same thing happens;
Now I use "volatile register uint32_t processed_pixels = 0;" to avoid the trap, but it looks ugly.
Is that a compile bug?
Any bettrer solutions?
Thanks a lot!
If you're not doing anything else you could just stay uninterruptible for 0.25 usec and poll for the values. I'd have limit counts on the wait loops just in case something goes wrong - you don't want to stay uninterruptible too long. I assume there's nothing else critical to be done within 0.25 usec. If it was just about possible to do the job with interrupts it should be easy this way.
Um sorry, I see you said 1024 values. In 0.25usec. That's rather a bit over the top silly me! I guess you mean each point in 0.25usec so a total of 256usec. Which is still less than the critical time for most things so what I said might still be okay.
Sorry daith, I made a mistake. As you said, on pixel takes up to 0.25us.
I use a sub pixel algorithm to accumulate pixel values and location weighted pixel values:
note: val_sum is a global uint32_t and weighted_sum is a uint64_t var.
the assembly code uses lots save/load as following:
ADC1_2_IRQHandler PROC
;;;787
;;;788 void ADC1_2_IRQHandler(void)
000254 b4c0 PUSH {r6,r7}
;;;789 {
;;;790 /* Test on ADC end of conversion interrupt */
;;;791 // if(ADC_GetITStatus(ADC1, ADC_IT_EOC))
;;;792 {
;;;793 register uint32_t val;
;;;794
;;;795 #if USE_INTERPOLATION
;;;796 register uint32_t interpolation;
;;;797 #endif
;;;798
;;;799 /* Clear ADC end of conversion interrupt -- 读取ADC1->DR时自动清除 */
;;;800 // ADC_ClearITPendingBit(ADC1, ADC_IT_EOC)
;;;801
;;;802 /* ADC value */
;;;803 val = ADC1->DR;
000256 f04f40a0 MOV r0,#0x50000000
00025a 6c00 LDR r0,[r0,#0x40]
;;;804
;;;805 #if USE_INTERPOLATION
;;;806 interpolation = (prev_val + val) >> 1;
;;;807 prev_val = val;
;;;808
;;;809 interpolation *= interpolation;
;;;810 val_sum += interpolation;
;;;811 curr_pixel++;
00025c 1c64 ADDS r4,r4,#1
00025e 1829 ADDS r1,r5,r0 ;806
000260 0849 LSRS r1,r1,#1 ;806
000262 fb01f201 MUL r2,r1,r1 ;809
000266 4912 LDR r1,|L1.688|
000268 4605 MOV r5,r0 ;807
00026a 68cb LDR r3,[r1,#0xc] ;810 ; val_sum
;;;812 weighted_sum += interpolation * curr_pixel;
00026c e9d1c704 LDRD r12,r7,[r1,#0x10]
000270 189e ADDS r6,r3,r2 ;810
000272 fb02f304 MUL r3,r2,r4
000276 2200 MOVS r2,#0
000278 eb130c0c ADDS r12,r3,r12
00027c eb420307 ADC r3,r2,r7
;;;813 #endif
;;;814
;;;815 val *= val;
000280 4368 MULS r0,r5,r0
;;;816 val_sum += val;
000282 4406 ADD r6,r6,r0
;;;817 curr_pixel++;
000284 1c64 ADDS r4,r4,#1
;;;818 weighted_sum += val * curr_pixel;
000286 4360 MULS r0,r4,r0
000288 eb10000c ADDS r0,r0,r12
00028c 415a ADCS r2,r2,r3
00028e 60ce STR r6,[r1,#0xc] ; val_sum
;;;819
;;;820 #if USE_INTERPOLATION
;;;821 if (curr_pixel >= (PIXEL_CNT << 1))
000290 e9c10204 STRD r0,r2,[r1,#0x10]
000294 f5b46f00 CMP r4,#0x800
;;;822 #else
;;;823 if (curr_pixel >= PIXEL_CNT)
;;;824 #endif
;;;825 {
;;;826 /* 已采集足够像素,关掉ADC中断 */
;;;827 ADC_ITConfig(ADC1, ADC_IT_EOC, DISABLE);
;;;828 }
;;;829 }
;;;830 }
000298 bf3c ITT CC
00029a bcc0 POPCC {r6,r7}
00029c 4770 BXCC lr
00029e 2200 MOVS r2,#0 ;827
0002a0 bcc0 POP {r6,r7} ;827
0002a2 2104 MOVS r1,#4 ;827
0002a4 f04f40a0 MOV r0,#0x50000000 ;827
0002a8 f7ffbffe B.W ADC_ITConfig
;;;831
ENDP
For a STM32F302CBT6@72MHZ, only 93M/s*0.25us=23 single cycle instructions allowed.
Also. the row pixel values should be send to UART in calibrate mode.
So I tried get data in ADC interrupt & process data in main loop/calibrate loop to avoid save/load.
Could you give me further suggestion?
Thanks.