Timer agt, debug mode stop on a simple instruction.

Hello everybody !

 

I have another problem with synergy... I hope you can help !

I'm working on a timer application with the objective of creating a 1-wire interface.

The code is really simple, but don't work at all. when I debug, the code block on a single instruction, even without breakpoint.

The instruction should reinitialise the counter for my timer but the code just block here, I don't know why...

 

Thanks in advance,

 

Clément.

  • Hello Clément,

    Not all critical exceptions can be trapped inside Default_Handler (or more specific error handler) - in some cases the CPU will be stopped immediately. Please navigate to "Quick access" box in the top-right corner and type in "Fault Status". Select this widget from the list and it should be added to your debug perspective. It will help you determine the cause of the exception by investigating fault status registers on the Cortex M core.

    Regards
  • In reply to Renesas Karol:

    Hello Karol,

     

    So, I have access to the fault status window but there doesn't seem to be anything wrong...

    I don't really understand that !

     

    Please tell me if I did anything wrong !

     

    Thanks you,

     

    Clément.

  • In reply to Clément:

    OK, I think there is a need for more information.

    Here is my 1-Wire file :

    /****** I N C L U D E S **********************************************************/
    #include "1Wire.h"
    #include "one_wire_thread.h"
    //****** V A R I A B L E S ********************************************************/
    unsigned char macro_delay;
    int timerOW = 0;

    void reset_timer(void)
    {
    ssp_err_t status;
    timerOW = 0;
    status = g_timer0.p_api->reset(g_timer0.p_ctrl);
    if(status != SSP_SUCCESS) while (1);
    }

    void increment_timer(void)
    {
    timerOW++;
    if(timerOW > 10000)
    timerOW = 0;
    }

    int get_timer(void)
    {
    return timerOW;
    }

    /**********************************************************************
    * Function: void drive_OW_low (void)
    * PreCondition: None
    * Input: None
    * Output: None
    * Overview: Configure the OW_PIN as Output and drive the OW_PIN LOW.
    ***********************************************************************/
    void drive_OW_low (void)
    {
    ssp_err_t status;
    status = g_ioport.p_api->pinDirectionSet(OW_PIN, IOPORT_DIRECTION_OUTPUT);
    if(status != SSP_SUCCESS) while (1);
    status = g_ioport.p_api->pinWrite(OW_PIN, IOPORT_LEVEL_LOW);
    if(status != SSP_SUCCESS) while (1);
    }

    /**********************************************************************
    * Function: void drive_OW_high (void)
    * PreCondition: None
    * Input: None
    * Output: None
    * Overview: Configure the OW_PIN as Output and drive the OW_PIN HIGH.
    ***********************************************************************/
    void drive_OW_high (void)
    {
    ssp_err_t status;
    status = g_ioport.p_api->pinDirectionSet(OW_PIN, IOPORT_DIRECTION_OUTPUT);
    if(status != SSP_SUCCESS) while (1);
    status = g_ioport.p_api->pinWrite(OW_PIN, IOPORT_LEVEL_HIGH);
    if(status != SSP_SUCCESS) while (1);
    }

    /**********************************************************************
    * Function: unsigned char read_OW (void)
    * PreCondition: None
    * Input: None
    * Output: Return the status of OW pin.
    * Overview: Configure as Input pin and Read the status of OW_PIN
    ***********************************************************************/
    unsigned char read_OW (void)
    {
    ssp_err_t status;
    ioport_level_t pinValue;

    status = g_ioport.p_api->pinDirectionSet(OW_PIN, IOPORT_DIRECTION_INPUT);
    if(status != SSP_SUCCESS) while (1);
    status = g_ioport.p_api->pinRead(OW_PIN, &pinValue);
    if(status != SSP_SUCCESS) while (1);

    return pinValue;
    }

    /**********************************************************************
    * Function: unsigned char OW_reset_pulse(void)
    * PreCondition: None
    * Input: None
    * Output: Return the Presense Pulse from the slave.
    * Overview: Initialization sequence start with reset pulse.
    * This code generates reset sequence as per the protocol
    ***********************************************************************/
    unsigned char OW_reset_pulse(void)
    {
    unsigned char presence_detect;

    drive_OW_low(); // Drive the bus low
    reset_timer();
    while(timerOW < 480); // delay 480 microsecond (us)
    drive_OW_high (); // Release the bus
    reset_timer();
    while(timerOW < 70); // delay 70 microsecond (us)

    presence_detect = read_OW(); //Sample for presence pulse from slave

    reset_timer();
    while(timerOW < 410); // delay 410 microsecond (us)

    drive_OW_high (); // Release the bus

    return presence_detect;

    }

    /**********************************************************************
    * Function: void OW_write_bit (unsigned char write_data)
    * PreCondition: None
    * Input: Write a bit to 1-wire slave device.
    * Output: None
    * Overview: This function used to transmit a single bit to slave device.
    *
    ***********************************************************************/

    void OW_write_bit (unsigned char write_bit)
    {
    if (write_bit)
    {
    //writing a bit '1'
    drive_OW_low(); // Drive the bus low
    reset_timer();
    while(timerOW < 6); // delay 6 microsecond (us)
    drive_OW_high (); // Release the bus
    reset_timer();
    while(timerOW < 64); // delay 64 microsecond (us)
    }
    else
    {
    //writing a bit '0'
    drive_OW_low(); // Drive the bus low
    reset_timer();
    while(timerOW < 60); // delay 60 microsecond (us)
    drive_OW_high (); // Release the bus
    reset_timer();
    while(timerOW < 10); // delay 10 microsecond for recovery (us)
    }
    }


    /**********************************************************************
    * Function: unsigned char OW_read_bit (void)
    * PreCondition: None
    * Input: None
    * Output: Return the status of the OW PIN
    * Overview: This function used to read a single bit from the slave device.
    *
    ***********************************************************************/

    unsigned char OW_read_bit ()
    {
    unsigned char read_data;
    //reading a bit
    drive_OW_low(); // Drive the bus low
    reset_timer();
    while(timerOW < 6); // delay 6 microsecond (us)
    drive_OW_high (); // Release the bus
    reset_timer();
    while(timerOW < 9); // delay 9 microsecond (us)

    read_data = read_OW(); //Read the status of OW_PIN


    reset_timer();
    while(timerOW <55); // delay 55 microsecond (us)
    return read_data;
    }

    /**********************************************************************
    * Function: void OW_write_byte (unsigned char write_data)
    * PreCondition: None
    * Input: Send byte to 1-wire slave device
    * Output: None
    * Overview: This function used to transmit a complete byte to slave device.
    *
    ***********************************************************************/
    void OW_write_byte (unsigned char write_data)
    {
    unsigned char loop;

    for (loop = 0; loop < 8; loop++)
    {
    OW_write_bit(write_data & 0x01); //Sending LS-bit first
    write_data >>= 1; // shift the data byte for the next bit to send
    }
    }

    /**********************************************************************
    * Function: unsigned char OW_read_byte (void)
    * PreCondition: None
    * Input: None
    * Output: Return the read byte from slave device
    * Overview: This function used to read a complete byte from the slave device.
    *
    ***********************************************************************/

    unsigned char OW_read_byte ()
    {
    unsigned char loop, result=0;

    for (loop = 0; loop < 8; loop++)
    {

    result >>= 1; // shift the result to get it ready for the next bit to receive
    if (OW_read_bit())
    result |= 0x80; // if result is one, then set MS-bit
    }
    return result;
    }


    /***********************************************************************
    * CheckCRC
    *
    * Function called in order to check the data validity of the entire
    * transmition.
    *
    * @param1 : unsigned char* buffer of the entire transmition
    * @param2 : unsigned char length of the buffer
    * @return : unsigned char CRC
    *
    ***********************************************************************/
    unsigned char CheckCRC(unsigned char* buffer, unsigned char length)
    {
    unsigned char CRC = 0,taille=0;
    taille = length;
    CRC = *buffer;
    length--;
    for(;length>0;length--)
    {
    CRC = CRC ^ *(buffer-length+taille);
    }
    return CRC;
    }

    And here is my thread_entry :

     

    #include "one_wire_thread.h"
    #include "1Wire.h"


    unsigned char OW_data[10];
    /* 1-Wire Thread entry function */
    void one_wire_thread_entry(void)
    {
    ssp_err_t status;
    status = g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);
    if(status != SSP_SUCCESS) while (1);

    while (1)
    {
    unsigned char acknowledge = 0, j = 0, i = 0;

    while(!acknowledge && j < 10)
    {
    OW_data[0] = ADD_LIGHT; //Send data to the next light board if there is one
    OW_data[1] = ADD_L1;
    OW_data[2] = CheckCRC(OW_data,2);

    OW_reset_pulse();

    for(i = 0 ; i < 3 ; i ++)
    {
    OW_write_byte(OW_data[i]);
    }

    for(i = 0 ; i < 3 ; i ++)
    {
    OW_data[i] = OW_read_byte();
    }

    if(OW_data[2] == CheckCRC(OW_data,2) && OW_data[1] == ADD_OK && OW_data[0] == ADD_MASTER)
    {
    //The next light received the Can Address, we can continue
    acknowledge = 1;
    }
    else
    j++;
    }
    reset_timer();
    while(get_timer() < 10000)
    {
    tx_thread_sleep (50);
    }

    }
    }

    void timer_callback(timer_callback_args_t * p_args)
    {
    switch(p_args->event)
    {
    case TIMER_EVENT_EXPIRED:
    increment_timer();
    break;
    default:
    break;
    }
    }

     

    My timer is configured to generate an interrupt every 1 µs. During the interrupt, it increment the timerOW variable which I use for the delays in my 1-Wire library.

    I've worked on my side and found that the code is stopped when the device try to access the timerOW variable. I don't know why.

     

    Maybe someone will be able to help ? :)

     

    Thanks in advance,

     

    Clément.

  • In reply to Clément:

    Hi Clément,

    I cannot reproduce such issue. Could you check Breakpoints tab in Debug perspective? Please try to remove all breakpoints and rerun the application.

    Please find the project based on your source code, you may also try running it if you still observe suspensions while accessing timerOW:

    S7_SK_1Wire_GPT_1_2_1.zip

    Regards,
    adboc

  • In reply to adboc:

    Hi abdoc,

    I tested your code and it doesn't work for me too. I put a breakpoint in the code bellow (in red)

     

    unsigned char OW_data[10];
    /* 1-Wire Thread entry function */
    void one_wire_thread_entry(void)
    {
    ssp_err_t status;
    status = g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);
    if(status != SSP_SUCCESS) while (1);

    while (1)
    {
    unsigned char acknowledge = 0, j = 0, i = 0;

    while(!acknowledge && j < 10)
    {
    OW_data[0] = ADD_LIGHT; //Send data to the next light board if there is one
    OW_data[1] = ADD_L1;
    OW_data[2] = CheckCRC(OW_data,2);

    OW_reset_pulse();

    for(i = 0 ; i < 3 ; i ++)
    {
    OW_write_byte(OW_data[i]);
    }

    for(i = 0 ; i < 3 ; i ++)
    {
    OW_data[i] = OW_read_byte();
    }

    if(OW_data[2] == CheckCRC(OW_data,2) && OW_data[1] == ADD_OK && OW_data[0] == ADD_MASTER)
    {
    //The next light received the Can Address, we can continue
    acknowledge = 1;
    }
    else
    j++;
    }
    reset_timer();
    while(get_timer() < 10000)
    {
    tx_thread_sleep (50);
    }

    }
    }

     

    The code never goes to this line and when I pause the debug session, the program is often stuck at the first while in the OW_reset_pulse function. That's strange, the while loop check if timerOW is less than 480 BUT I can see the value of this variable and it stays in the loop altough timerOW's value is often between 1000 and 10000...

    Can you check this behaviour with the same breakpoint ?

     

    Thanks in advance,

     

    Clément. 

  • In reply to Clément:

    Hi Clément,

    As far as I see, this variable is incremented in the timer callback, which is called from the timer ISR. The timer's period is quite small (1 us), so I suppose that's why you observe values larger than 480 after the loop.

    Have you tested the application with the device attached to 1Wire output? I see the application expects some kind of response/acknowledgement.

    Regards,
    adboc
  • In reply to adboc:

    Hi abdoc,

    The problem is not that i observe values larger than 480, it's that even if the values are greater than 480, the program stays in the loop !
    So, there is no possible acknowledgement from another device because nothing is sent. The program just stays in the first while loop which checks the value of timerOW;

    Any idea ?

    Clément.
  • In reply to Clément:

    Hi Clément,

    I suggest changing the optimization level to -O0 or -Og in the project settings: Project > Properties > C/C++ Build > Settings > Tool Settings > Optimization > Optimization Level

    Does it still stay in the while loop after the change?

    Regards,
    adboc
  • In reply to adboc:

    abdoc,

    It seems to work, but can you explain the reason ?

    Thanks a lot ! :)
  • In reply to Clément:

    Hi Clément,

    The default optimization level -O2 allows the compiler to optimize routines, variables etc. For debugging purposes the recommended optimization level is -O0 or -Og, as these will get the most meaningful information.

    Regards,
    adboc
  • In reply to adboc:

    Does this mean that this won't work when in release mode ??!
  • In reply to Clément:

    No, it doesn't mean it won't work in release mode. If you observe different behaviour between -O2 and -O0 optimization levels, there might be some synchronization issues in the source code (as the -O2 code usually runs 'faster').
  • In reply to Clément:

    I think you should declare the global variable timerOW as a volatile :-

    volatile int timerOW = 0;


    Then you should be able to use the compiler optimisation.

    Please see this article for a description of the C volatile keyword :-

    barrgroup.com/.../C-Volatile-Keyword
  • In reply to Jeremy:

    Ahhhhh great ! Thank you very much Jeremy, I learned something great today !
    The code works now so I guess this topic is closed !
    And Thank you as always adboc for taking your time to help !