Important variables in toggle_pin() being optimized out

Discussion in 'Embedded Systems and Microcontrollers' started by Avshi, Jul 27, 2017.

  1. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    Hello, I am using the pio_toggle_pin method and when I step into it, I can see that an important variable is being optimized out. Needless to say the pio_toggle_pin() method doesn't work as expected and the pin stays high. I suspect that it isn't getting initialized, but I copied the code from an atmel example project. Why would the compiler do this? How can I fix it? This happens with normal optimization enabled.
    When I disable optimization the pin stays low and has a quick jump in voltage (my multimeter reads only a few hundred mV), but immediately retreats back to low.
    Thanks.
    I've included the project files.
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,943
    1,816
    Post your code, not a zip file so people can read it.

    If a variable is getting optimized away try declaring it volatile.
     
  3. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    Here is the code contained in the src file. I've arrived at that solution for the ul_status variable. I'm talking about the PIO structure (Pio * p_pio) included in the pio.c for the pin toggle function. When I declare it like this:
    Code (Text):
    1. Pio volatile * p_pio = pio_get_pin_group(ul_pin);
    It still reads as optimized out during debug. If I set optimization to none, the registers
    PIO_ODSR, PIO_CODR, PIO_SODR fail to be evaluated. I'm not sure if this last part is significant or not, it's just what I saw during debug.

    Code (Text):
    1.  
    2. /**
    3. * \file
    4. *
    5. * \brief Empty user application template
    6. *
    7. */
    8.  
    9. /**
    10. * \mainpage User Application template doxygen documentation
    11. *
    12. * \par Empty user application template
    13. *
    14. * Bare minimum empty user application template
    15. *
    16. * \par Content
    17. *
    18. * -# Include the ASF header files (through asf.h)
    19. * -# "Insert system clock initialization code here" comment
    20. * -# Minimal main function that starts with a call to board_init()
    21. * -# "Insert application code here" comment
    22. *
    23. */
    24.  
    25. /*
    26. * Include header files for all drivers that have been imported from
    27. * Atmel Software Framework (ASF).
    28. */
    29. /*
    30. * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
    31. */
    32. #include <asf.h>
    33.  
    34. #define ALM_LGTH 5
    35.  
    36. int x,r;
    37.  
    38. static void configure_rtt(void)
    39. {
    40.     uint32_t ul_previous_time;
    41.  
    42.     /* Configure RTT for a 1 second tick interrupt */
    43.     #if SAM4N || SAM4S || SAM4E || SAM4C || SAM4CP || SAM4CM || SAMV71 || SAMV70 || SAME70 || SAMS70
    44.     rtt_sel_source(RTT, false);
    45.     #endif
    46.     rtt_init(RTT, 32000);
    47.  
    48.     ul_previous_time = rtt_read_timer_value(RTT);
    49.     while (ul_previous_time == rtt_read_timer_value(RTT));
    50.     /* Enable RTT interrupt */
    51.     NVIC_DisableIRQ(RTT_IRQn);
    52.     NVIC_ClearPendingIRQ(RTT_IRQn);
    53.     NVIC_SetPriority(RTT_IRQn, 0);
    54.     NVIC_EnableIRQ(RTT_IRQn);
    55.     rtt_enable_interrupt(RTT, RTT_MR_RTTINCIEN);
    56. }
    57.  
    58. void RTT_Handler(void)
    59. {
    60.     uint32_t volatile ul_status;
    61.  
    62.     /* Get RTT status */
    63.     ul_status = rtt_get_status(RTT);
    64.  
    65.     /* Alarm */
    66.     if ((ul_status & RTT_SR_ALMS) == RTT_SR_ALMS) {
    67.         pio_toggle_pin(PIO_PA4);
    68.         rtt_write_alarm_time(RTT,ALM_LGTH);
    69.         x++;
    70.     }
    71.  
    72. }
    73.  
    74. int main (void)
    75. {
    76.     /* Insert system clock initialization code here (sysclk_init()). */
    77.     sysclk_init();
    78.     board_init();
    79.     configure_rtt();
    80.     rtt_write_alarm_time(RTT,ALM_LGTH);
    81.  
    82.     unsigned char i, j;
    83.     j = 0;
    84.     while(--j) {
    85.         i = 0;
    86.         while(--i)
    87.             asm("");
    88.     }
    89. }
    90.  
     
    Last edited: Jul 28, 2017
  4. WBahn

    Moderator

    Mar 31, 2012
    22,865
    6,828
    I don't see anywhere in the code you posted where you reference the code you are having trouble with. That makes it real hard to offer any suggestions. Maybe I'm just overlooking it. On what line do you use it (using the line numbers in the CODE block of your post)?
     
  5. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    There are many files added by the ASF library so I thought it would be better if you guys could open the full project. Sorry for the trouble.

    Line 753 of pio.c and line 10 in the following code

    I have tried inserting volatile here

    Code (Text):
    1. /**
    2. * \brief Toggle a GPIO pin.
    3. *
    4. * \param ul_pin The pin index.
    5. *
    6. * \note The function \ref pio_configure_pin must be called before.
    7. */
    8. void pio_toggle_pin(uint32_t ul_pin)
    9. {
    10.     Pio * p_pio = pio_get_pin_group(ul_pin);
    11.  
    12.     if (p_pio->PIO_ODSR & (1 << (ul_pin & 0x1F))) {
    13.         /* Value to be driven on the I/O line: 0. */
    14.         p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
    15.     } else {
    16.         /* Value to be driven on the I/O line: 1. */
    17.         p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
    18.     }
    19. }
     
  6. WBahn

    Moderator

    Mar 31, 2012
    22,865
    6,828
    Well, I'm not going to sift through a few thousand lines of code.

    One thing I noticed is that, at least in what you've posted, the toggle function is only called once and it appears to be called with an argument that is a constant. Is it possible that the compiler is inlining your code?
     
  7. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    It could be, but it probably shouldn't be. I'll explore more this weekend.
     
  8. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    It's not clear to me why this happens, but replacing
    Code (Text):
    1. pio_toggle_pin(PIO_PA4);
    with
    Code (Text):
    1. if (pio_get(PIOA, PIO_TYPE_PIO_OUTPUT_0 , PIO_PA4))
    2.     pio_clear(PIOA, PIO_PA4);
    3. else
    4.     pio_set(PIOA, PIO_PA4);
    seems to work just fine.
    I think there may be a bug in the toggle_pin function
     
    Last edited: Aug 2, 2017
  9. Avshi

    Thread Starter Member

    Jan 16, 2015
    47
    1
    Looked into it today and the fix to pio.c was to change

    Code (Text):
    1. void pio_toggle_pin(uint32_t ul_pin)
    2. {
    3.     Pio * p_pio = pio_get_pin_group(ul_pin);
    4.  
    5.     if (p_pio->PIO_ODSR & (1 << (ul_pin & 0x1F))) {
    6.         /* Value to be driven on the I/O line: 0. */
    7.         p_pio->PIO_CODR = 1 << (ul_pin & 0x1F);
    8.     } else {
    9.         /* Value to be driven on the I/O line: 1. */
    10.         p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);
    11.     }
    12. }
    to

    Code (Text):
    1. void pio_toggle_pin(uint32_t ul_pin)
    2. {
    3.     Pio * p_pio = pio_get_pin_group(ul_pin);
    4.  
    5.     if (p_pio->PIO_ODSR & ul_pin) {
    6.         /* Value to be driven on the I/O line: 0. */
    7.         p_pio->PIO_CODR = ul_pin);
    8.     } else {
    9.         /* Value to be driven on the I/O line: 1. */
    10.         p_pio->PIO_SODR = ul_pin);
    11.     }
    12. }
     
Loading...