How to reset the processor?

paulgcoleman wrote on Monday, April 23, 2012:

I have a scenario whereby I want to reset the processor in response to a fatal error that my code cannot recover from. I’m using an Atmel UC3C with the framework which Atmel provides along with FreeRTOS 7.0.1.

Within the framework is a macro called ResetCPU which is shown at the end. It’s a bit convoluted but basically it just sets a load of registers and does a jump to the _start by setting the program counter to 0x80000000 i.e. the reset vector.

My problem is that it doesn’t work and seems to crash the system and I don’t understand why. FreeRTOS still seems to be running in the background.

I have a fatal error task which is blocked on a semaphore and when the semaphore is signalled I stop some software timers that I create and suspend all the tasks below the fatal error priority and then wait for a switch to open and close before resetting. If I leave out the code which checks the switch it seems to work correctly and reboots the system but when the switch code is in there it just seems to crash. I tried replacing the switch checking code with a delay and it seems that any delay less than about 700ms is okay but more than that and the system crashes.

I’m wondering if it’s something to do with supervisor modes or the like but I don’t know enough about the bowels of FreeRTOS to know where to start.

Has anobody had the same problem or know what else I can try?

Thanks, Paul.

  #define Reset_CPU() \
      __asm__ __volatile__ (\
        “lddpc   r9, 3f\n\t”\
        “mfsr    r8, %\n\t”\
        “bfextu  r8, r8, %, %\n\t”\
        “cp.w    r8, 0b001\n\t”\
        “breq    0f\n\t”\
        “sub     r8, pc, $ - 1f\n\t”\
        “pushm   r8-r9\n\t”\
        “mtsr    %, r9\n”\
        “mov     r0, 0\n\t”\
        “mov     r1, 0\n\t”\
        “mov     r2, 0\n\t”\
        “mov     r3, 0\n\t”\
        “mov     r4, 0\n\t”\
        “mov     r5, 0\n\t”\
        “mov     r6, 0\n\t”\
        “mov     r7, 0\n\t”\
        “mov     r8, 0\n\t”\
        “mov     r9, 0\n\t”\
        “mov     r10, 0\n\t”\
        “mov     r11, 0\n\t”\
        “mov     r12, 0\n\t”\
        “mov     sp, 0\n\t”\
        “stdsp   sp, sp\n\t”\
        “ldmts   sp, sp\n\t”\
        “mov     lr, 0\n\t”\
        “lddpc   pc, 2f\n\t”\
        “.balign 4\n”\
        “.word   0x80000000\n”\
        “.word   %”\
        :  “i” (AVR32_SR),\
           “i” (AVR32_SR_M_OFFSET),\
           “i” (AVR32_SR_M_SIZE),\
           “i” (AVR32_SR_GM_MASK | AVR32_SR_EM_MASK | (AVR32_SR_M_SUP << AVR32_SR_M_OFFSET))\

davedoors wrote on Monday, April 23, 2012:

It sounds like the macro is just jumping back to the start of the program. It is not resetting the CPU, so interrupts will still be executing so probably it is the RTOS tick interrupt that is giving you the problem. I suggest either a hard reset if that is possible from software (watchdog?), so the peripherals are reset too, or stopping the timer that generates the RTOS ticks, or better still stopping all interrupts in case any are trying to talk to FreeRTOS.

paulgcoleman wrote on Monday, April 23, 2012:

Thanks for the reply and suggestions.

I have tried calling a function which disables the interrupts (which is provided by Atmel’s framework for the device) but if I break after the ResetCPU() has executed I seem to end up in the FreeRTOS timers.c source file so I’m not sure how that happens?

davedoors wrote on Monday, April 23, 2012:

I guess the tick interrupt is selecting the timer task to run, and switching to it.

paulgcoleman wrote on Monday, April 23, 2012:

Yes but with interrupts disabled I’m not sure how it does!!

davedoors wrote on Monday, April 23, 2012:

Does the start up re-enable interrupts. Have you tried disabling the timer that generates the interrupts?

paulgcoleman wrote on Monday, April 23, 2012:

I haven’t got a timer generating the tick by the looks of it. The default seesm to use the CPU cycle counter as I have the following in my FreeRTOSConfig.h…
/* configTICK_USE_TC is a boolean indicating whether to use a Timer Counter or
   the CPU Cycle Counter for the tick generation.
   Both methods will generate an accurate tick.
   0: Use of the CPU Cycle Counter.
   1: Use of the Timer Counter (configTICK_TC_CHANNEL is the TC channel). */
#define configTICK_USE_TC             0
#define configTICK_TC_CHANNEL         2

If I set configTICK_USE_TC to 1 then I get a compiler error saying that it can’t find tc.h which is true as it doesn’t exist. I assume this has to be created for the specific port but I can’t find any mention of it in the documentation.

So I don’t know if this is the source of my problem?

paulgcoleman wrote on Tuesday, April 24, 2012:

I gave up with the soft reset option and got the watchdog timer working in the end for the hardware version.

Now sorted :o)