Different behavior of a multithreaded application on DK-S7G2 when running in debugger and running free.

I've an application with a S7G2 (current running on a DK-S7G2) where data coming with 5kHz from CAN have to be analyzed (detect periods), compressed, sorted  and stored in a ringbuffer multithreaded.
All works fine if the application is running within the debugger. But if I close the debugging session to let the application run free the further period detection fails and no more periods are signalized on the LED I implemented for control purposes. The receive of data continues and no CAN-frames were dropped (also monitored by LED). After reset or power on reset the detection fails from begin.

The HTTP-server and the USB-ports continues the work normally, so there was no breakpoint triggered.
I don't use printf or other debug outputs.

So my questions: what's the main difference of running an application within a debugger and free run. Where should I look for programming failures at first?

  • Remove your call to initiate semihosting or relink without semihosting (iar).
  • Remove your call to initiate semihosting or relink without semihosting (iar).
  • In reply to larry_c_not_Renesas:

    Hi larry,

    after disabling the semihosting-option the linker is missing some functions and does not finish the build:

    Error[Li005]: no definition for "__write" [referenced from fflush.o(dl7M_tlf.a)] 
    Error[Li005]: no definition for "__lseek" [referenced from xfspos.o(dl7M_tlf.a)]
    Error[Li005]: no definition for "__close" [referenced from fclose.o(dl7M_tlf.a)]
    Error[Li005]: no definition for "remove" [referenced from fclose.o(dl7M_tlf.a)]
  • After disabling semihosting, you'll have to get rid of the printf's, #if around them, or mod the IAR library call that outputs the print characters to a port like a serial, USB, etc. That is a bit involved but IAR has an appnote on their site with details.
  • In reply to larry_c_not_Renesas:

    I didn't use printf or other debugging outputs.
    But I implemented dummy-functions for the missing functions to be able to finish the build.
    With semihosting disabled the behavior is the same than with enabled semihosting. Running well within debugger and stops cycle-detection when running free.
    Network and USB continuously working within and outside of the debugger.
  • In reply to 4711:

    So some things work and some things not? What does "stops cycle-detection when running free" mean?
    Any "blinky" thread?
    The build issue meant something is wrong.
    lc
  • In reply to larry_c_not_Renesas:

    Correct, all parts are working except the cycle detection.
    Cycle detection means: measured data are received by CAN with 5kHz. They contains a measured waveform having periodic maxima and minima.The CAN-ISR for CAN_EVENT_RX_COMPLETE separates the received data. I added the activation of a LED to see if the frames are still received in free run (they do so):

                case CANDAT_SWING:
                    {
                         uint8_t lcnt, acnt = (*(uint8_t*) (&rx_frame[sensor].data));

                        g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_07, IOPORT_LEVEL_HIGH); //todo remove
                        lcnt = datacount[sensor];
                        if(firstframe[sensor])
                        {
                            firstframe[sensor] = false;
                        }
                        else
                        {
                            if((acnt - lcnt) > 1)
                                dropped[sensor] += (acnt - lcnt);
                        }

                        for(; lcnt != acnt; lcnt++)
                        {
                            *datwptr[sensor] = *((int16_t*) (&rx_frame[sensor].data[3]));
                            *(datwptr[sensor] + SENS_BUFSIZE) = *((int16_t*) (&rx_frame[sensor].data[1]));
                            if(sensor == g_swing_master)
                            {
                                calculate_frequency(sensor, cycles);
                            }
                            ++datwptr[sensor];
                            if(datwptr[sensor] >= ((int16_t*)(&sensbuf[sensor]) + SENS_BUFSIZE))
                            {
                                datwptr[sensor] = (int16_t*)(&sensbuf[sensor]);
                            }
                        }
                        datacount[sensor] = acnt;
     
                        g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_07, IOPORT_LEVEL_LOW); //todo remove
                    }
                    break;

    Than it calls a function which is recording the min-max-values and calculating the frequency of the current detected cycles.
    This function sets a volatile flag protected by a mutex to signalize a running analysis thread that there are a new cycle is available.
    Additionally is sets two LED to see outside of the debugger that a new cycle was detected.

    void calculate_frequency(uint8_t sensor, uint32_t cycles)
    {
        int i;

        if(*datwptr[sensor] > calc_valmax)
        {
            calc_valmax = *datwptr[sensor];
            for(i = 0; i < SENS_NUM_EXT_SENSORS; i++)
                calc_posmax[i] = datwptr[i];
            calc_timemax = datwptr[sensor] - (int16_t*)(&sensbuf[sensor]);
            calc_timemax = cycles;
            if(*datwptr[sensor] > (-32768 + CALC_POSITION_HYTSRESIS))
                calc_valmin = *datwptr[sensor] - CALC_POSITION_HYTSRESIS;
            else
                calc_valmin = -32768;
            if(calc_last_posmin != calc_posmin)
            {
                for(i = 0; i < SENS_NUM_EXT_SENSORS; i++)
                    calc_last_posmin[i] = calc_posmin[i];
            }
        }
        else if(*datwptr[sensor] < calc_valmin)
        {
            calc_valmin = *datwptr[sensor];
            for(i = 0; i < SENS_NUM_EXT_SENSORS; i++)
                calc_posmin[i] = datwptr[i];
            //                            calc_timemin = datwptr[sensor] - (int16_t*)(&sensbuf[sensor]);
            calc_timemin = cycles;
            if(calc_last_timemax != calc_timemax)
            {
                if(calc_last_timemax)
                {
                    static uint32_t difftime;

                    difftime = get_difftime_ms(calc_last_timemax, calc_timemax);
                    g_calc_frequency = 600000L / difftime;
                }
                calc_last_timemax = calc_timemax;
                calc_valmax /= 10;
                g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_09, IOPORT_LEVEL_HIGH); //todo remove
                tx_mutex_get (&g_newswing_mutex, TX_WAIT_FOREVER);
                g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_10, IOPORT_LEVEL_HIGH); //todo remove
                g_calc_newswing++;
                tx_mutex_put (&g_newswing_mutex);
            }
        }
    }

    The analysis thread works with the new data and resets afterwards the new-cycle-flag and the LED.

    void analysis_thread_entry(void)
    {
    ...

        while(1)
        {
            if(g_calc_newswing)
            {
    ...

                tx_mutex_get (&g_newswing_mutex, TX_WAIT_FOREVER);
                --g_calc_newswing;
                tx_mutex_put (&g_newswing_mutex);
                g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_09, IOPORT_LEVEL_LOW);
                g_ioport.p_api->pinWrite(IOPORT_PORT_08_PIN_10, IOPORT_LEVEL_LOW);
            }
            tx_thread_sleep(nx_ms_to_ticks(2));
        }
    }

    As said, all works fine when running in debugger. But after closing the debugger the LED for a detected cycle doesn't flash furthermore and stay off.

  • So back to the original issues, those are all part of the IAR low level IO routines that should be defined in the startup code, but somehow you've asked that they be omitted. It must be one of the link options, where you turned off semi-hosting. What is the state of " "With I/O emulation modules" in there? Can you try flipping it and omit you're dummy code.

    You mentioned "closing the debugger" - when you run w/o the debugger, do you just download the code, unplug the debugger and then reset/power cycle the board to run it?
  • In reply to 4711:

    Are you trying to use mutexes in the CAN ISR callback? Tx_mutex_get() and tx_mutex_put() are only allowed from Initialization and threads and timers, not from ISR.
  • In reply to larry_c_not_Renesas:

    Hi larry,
    I doesn't find the option "With I/O emulation modules" in my settings. Neither in the library configuration nor in the linker output settings.

    I download the code with "Download and Debug" and start the main function with F5. So all modules works. Then I close the debugger by clicking the red cross "Stop Debugging" in the menu bar. From this moment no more cycle is detected but CAN, http-server and USB are continues to work. I also downloaded the project by "Project->Download->Download active application" and make a power cycle or reset on the eval-board. In this case all other modules are working but no cycle is detected from begin.

  • In reply to Jeremy:

    Hi Jeremy,

    Thanks for the hint. I removed the mutexes but have the same behavior like with the mutexes.

  • I found and fixed the reason for this behavior.
    I use the DWT->CYCCNT register for detection and calculation of the cycles periods of the signal. But the DWT-system is disabled by default when shutting down the debugger or start without connected debugger.
    May be that I'm blind but for renesas synergy I didn't found any kind of information how to enable the DWT-system without debugger.
    Finally I found a hint on stackoverflow.com regarding a similar problem with a STM32. I adapted the Structures and registers for the renesas-controller and now the signal-detection runs even without connected debugger.
    My solution: I inserted in my startup-thread at the begin

        CoreDebug->DEMCR |= 0x01000000;
        ITM->LAR = 0xC5ACCE55;
        DWT->CYCCNT = 0;
        DWT->CTRL |= 1;

    If anyone has more detailled informations about the usage of the DWT-system with renesas synergy and SCC I would be grateful.