4

I have the following 5 lines of code and want the this lines are executed in exact this order with O2 or O3:

    PORT->Group[GPIO_PORTB].OUTCLR.reg = (volatile uint32_t) 1 << 9;
    TC3->COUNT16.COUNT.reg =  (volatile uint16_t) 0;
    TC3->COUNT16.CC[0].reg = (volatile uint16_t) vusb_driver->in_data->bitlength;
    SERCOM0->SPI.DATA.reg = (volatile uint32_t) 0x54;
    DMAC->Channel[USB_SEND_SD_DMA_CH].CHCTRLA.reg = (volatile uint8_t) DMAC_CHCTRLA_ENABLE;

If I optimize with O2 or O3 the code breaks at line 264 because this line must be executed before line 265:

  261:      PORT->Group[GPIO_PORTB].OUTCLR.reg = (volatile uint32_t) 1 << 9;
200001EE   ldr  r1, [pc, #84]        
   263:         TC3->COUNT16.CC[0].reg = (volatile uint16_t) vusb_driver->in_data->bitlength;
200001F0   ldr  r5, [pc, #84]        
   264:         SERCOM0->SPI.DATA.reg = (volatile uint32_t) 0x54;
200001F2   ldr  r4, [pc, #88]        
   265:         DMAC->Channel[USB_SEND_SD_DMA_CH].CHCTRLA.reg = (volatile uint8_t) DMAC_CHCTRLA_ENABLE;
200001F4   ldr  r0, [pc, #88]        
   261:         PORT->Group[GPIO_PORTB].OUTCLR.reg = (volatile uint32_t) 1 << 9;
200001F6   mov.w    r6, #512         
200001FA   str.w    r6, [r1, #148]       
   262:         TC3->COUNT16.COUNT.reg =  (volatile uint16_t) 0;
200001FE   strh r2, [r3, #20]        
   263:         TC3->COUNT16.CC[0].reg = (volatile uint16_t) vusb_driver->in_data->bitlength;
20000200   ldr  r2, [r5]         
20000202   ldr  r2, [r2, #20]        
20000204   ldrh.w   r2, [r2, #72]        
20000208   strh r2, [r3, #28]        
   264:         SERCOM0->SPI.DATA.reg = (volatile uint32_t) 0x54;
2000020A   movs r5, #84      
   265:         DMAC->Channel[USB_SEND_SD_DMA_CH].CHCTRLA.reg = (volatile uint8_t) DMAC_CHCTRLA_ENABLE;
2000020C   movs r2, #2       
   264:         SERCOM0->SPI.DATA.reg = (volatile uint32_t) 0x54;
2000020E   str  r5, [r4, #40]   

 
makurisan
  • 467
  • 3
  • 13
  • 1
    Does this answer your question? [Force order of execution of C statements?](https://stackoverflow.com/questions/19292075/force-order-of-execution-of-c-statements) – stark Sep 11 '20 at 14:05
  • I suppose `-o0` isn't acceptable ? – A P Jo Sep 11 '20 at 14:40
  • Where does the store to `DMAC->Channel[USB_SEND_SD_DMA_CH].CHCTRLA.reg` occur in the above assembly listing? It looks like it has only got as far as storing to `SERCOM0->SPI.DATA.reg` so far. – Ian Abbott Sep 11 '20 at 14:57

2 Answers2

2

Your use of volatile is incorrect, you should define the destination objects as volatile to ensure they are written to exactly in the order of the program.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
1

The compiler is - in the regular case - allowed to reorder instructions if the effect of the execution is the same (this is the "as-if rule"). So you must do one of the following:

  • Indicate to it that the instructions will have a different effect (e.g. by making the relevant .reg variables volatile; or through aliasing of pointers etc.)
  • Use some sort of compiler-specific directives to control its behavior.
  • Not compile, i.e. generate your machine code in a different manner.

Specifically, if you choose the first option, you must explain - to the compiler and perhaps to yourself, why is it that

line [264] must be executed before line 265

In what sense "must" it be executed before 265? Who would notice? It's likely that a concrete answer to this question is something you could use to force the desired order of execution.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • _"In what sense "must" it be executed before 265"_: maybe it's some hardware requirement. – Jabberwocky Sep 11 '20 at 14:05
  • @Jabberwocky: That wouldn't answer the question. What _is_ the hardware requirement, _exactly_? – einpoklum Sep 11 '20 at 14:55
  • Good question, only the OP knows this as only _he_ knows what hardware his code is running on – Jabberwocky Sep 11 '20 at 14:57
  • [This SO article](https://stackoverflow.com/questions/14785639/may-accesses-to-volatiles-be-reordered) is interesting – Jabberwocky Sep 11 '20 at 15:00
  • 1
    @Jabberwocky; The spi must be set with the data first because 0x54 is the sync field of the Data protocol. After that the configured DMA sent the rest of the transaction. – makurisan Sep 11 '20 at 17:37