AnsweredAssumed Answered

Using the backup watchdog (coldfire v2) in MQX with a bootloader causes a freeze?

Question asked by Stephen Maloney on Apr 6, 2011
Latest reply on Nov 21, 2011 by Raul Palencia

Hello everyone,

 

The problem: when the backup watchdog is 'exercised' to confirm that it is operating properly, it causes a system freeze that is not recoverable unless I cycle power. Obviously I desired it to cause the system to reset.

 

The setup: (a bit convoluted) I have a codewarrior pre-ecliple project that is a bootloader; suffice to say that I start up the backup watchdog in this bootloader, and have test it to successfully cause a reboot. Once the system jumps from this code into my main code, which is a Codewarrior 10 project w/MQX, I continue to feed the watchdog during normal operation using identical code to that present in the bootloader:

 

//------------------------------------------------------------------------------
// watchdog_task.c
//
// Task to control the hardware watchdog; will force a reset of the system if
// something causes this task to crash.
//------------------------------------------------------------------------------
#include <mqx.h>
#include <bsp.h>

#include "task_template.h"
#include "watchdog_task.h"

//------------------------------------------------------------------------------
// private defines
//------------------------------------------------------------------------------
// point directly at the watchdog registers. For some reason MQX does not supply
// a way to access these particular registers within the IPSBAR
//#define WATCHDOG_TASK_WCR (*(volatile uint_16 *)(0x40140000))
//#define WATCHDOG_TASK_WMR (*(volatile uint_16 *)(0x40140002))
//#define WATCHDOG_TASK_WSR (*(volatile uint_16 *)(0x40140006))

//------------------------------------------------------------------------------
// global variables
//------------------------------------------------------------------------------
extern FILE_PTR g_ittyb_fptr;

//------------------------------------------------------------------------------
// watchdog_task
//
// Handles setting up and feeding the watchdog.
//------------------------------------------------------------------------------
void watchdog_task(uint_32 parameter) {
    VMCF5225_STRUCT_PTR mcf5225_ptr;
    VMCF5225_WATCHDOG_STRUCT_PTR w_ptr;
    
    _int_disable();
    
    // initialize the watchdog registers - grab IPSBAR
    mcf5225_ptr = _PSP_GET_IPSBAR();
    w_ptr = (VMCF5225_WATCHDOG_STRUCT_PTR)0x40140000;
    
    // set BWCR register with proper values for the clock source
    mcf5225_ptr->CLK.BWCR = (0 << 0);    // the source for the BWT is half the system frequency
    
    // determine the desired timeout period and write it to WMR
    // tau = 25 nS
    // T = [(WM + 1) * 4096 + 4] * tau = 5 seconds
    w_ptr->WMR = 0xBEBB;
    //WATCHDOG_TASK_WMR = 0xBEBB;
    
    // watch-dog timer control register
    //WATCHDOG_TASK_WCR =    (1 << 4) |    // stop on STOP mode
    w_ptr->WCR =        (1 << 4) |    // stop on STOP mode
                        (1 << 3) |    // stop on WAIT mode
                        (1 << 2) |     // stop on DOZE mode
                        (1 << 0);    // enable BACKUP_WATCHDOG_TIMER
    
    while(TRUE) {
        _int_disable();
        
        // feed the watch-dog
        w_ptr->WSR = 0x5555;
        w_ptr->WSR = 0xAAAA;
        //WATCHDOG_TASK_WSR = 0x5555;    
        //WATCHDOG_TASK_WSR = 0xAAAA;
        
        _int_enable();
        
        // wait
        fprintf(g_ittyb_fptr, "fed\n");
        _time_delay(2000);
    }
}
//------------------------------------------------------------------------------

 

I was experimenting with enabling/disabling interrupts, and using the w_ptr instead of the directly accessed registers, but I get the same results either way.

 

Anyway, what I think the problem may be, is that when the system tries to reset once it is in the main code, it jumps somewhere incorrectly to reset; ie the reset vector is not set up properly. I don't know where this is set or how to check or change it.

 

Here is my linker command file for the MQX project:


MEMORY
{
## intflash    (RX): ORIGIN = 0x00000000, LENGTH = 0x00080000
## sram        (RW): ORIGIN = 0x20000000, LENGTH = 0x00010000
   vectorrom   (RX): ORIGIN = 0x00008000, LENGTH = 0x00000400
   cfmprotrom  (RX): ORIGIN = 0x00008400, LENGTH = 0x00000020
   tramp        (RX): ORIGIN = 0x00008420, LENGTH = 0x00000020    
   rom         (RX): ORIGIN = 0x00008440, LENGTH = 0x00077B00  # Code + Const data   
   ram         (RW): ORIGIN = 0x20000000, LENGTH = 0x00010000  # SRAM - RW data

   # kernel space starts after RAM variables (Location of MQX Kernel data + MQX heap)
   end_of_kd   (RW): ORIGIN = 0x2000FFF0, LENGTH = 0x00000000
   
   # Boot stack reused by MQX Kernel data
   bstack      (RW): ORIGIN = 0x2000FA00, LENGTH = 0x00000200  # Boot stack
   end_bstack  (RW): ORIGIN = 0x2000FBFF, LENGTH = 0x00000000
}

KEEP_SECTION { .vectors_rom, .vectors_ram, .cfmconfig, .trampoline }

SECTIONS
{
   ___INTERNAL_SRAM_BASE  = 0x20000000;
   ___INTERNAL_SRAM_SIZE  = 0x00010000;
   ___INTERNAL_FLASH_BASE = 0x00000000;
   ___INTERNAL_FLASH_SIZE = 0x00080000;

    ___IPSBAR              = 0x40000000; # Peripherals/FlexCAN
    ___VECTOR_TABLE_START  = 0x20000000; # Runtime vector table in sram

   # MQX link time configurations
   ___DEFAULT_PROCESSOR_NUMBER = 1;
   ___DEFAULT_INTERRUPT_STACK_SIZE = 1024;
   ___KERNEL_DATA_VERIFY_ENABLE = 0;    # Test SDRAM read/write

   # Flashx configurations
   ___FLASHX_SECT_SIZE = 0x1000;

    .vectors :
    {
        ___VECTOR_TABLE_ROM_START = .;        # Runtime vector table in sram
        *(.vectors_rom)
        . = ALIGN (0x4);
    } > vectorrom

    .cfmprotect :
    {
        *(.cfmconfig)
        . = ALIGN (0x4);
    } > cfmprotrom
 
    .trampoline :
    {
        *(.trampoline)
        . = ALIGN (0x4);
    } > tramp
 
  .main_application :
   {
      *(KERNEL)
      *(S_BOOT)
      *(IPSUM)
      *(.text)
      *(.init)
      *(.fini)
      *(.eini)
      *(.ctors)
      *(.dtors)
      .= ALIGN(0x4);
      *(.rodata)
      .= ALIGN(0x4);
      *(.rdata)
      . = ALIGN(0x4);
      *(.exception)
      . = ALIGN(0x4);
      __exception_table_start__ = .;
      EXCEPTION
      __exception_table_end__ = .;
      ___sinit__ = .;
      STATICINIT

      .= ALIGN(0x4);
      __COPY_OF_DATA = .;
   } > rom

   .main_application_data : AT(__COPY_OF_DATA)
   {
        . = ALIGN(0x10000);
        ___VECTOR_TABLE_RAM_START = .;        # Runtime vector table in sram
        *(.vectors_ram)

        . = ALIGN(512);
        __BDT_BASE = .;
        *(.usb_bdt)
        __BDT_END = .;

      __START_DATA = .;
      *(.data)
      __END_DATA = .;

      . = ALIGN(0x4);
      __START_SDATA = .;
      *(.sdata)
      __END_SDATA = .;

      . = ALIGN(0x4);
      __SDA_BASE  = .;
      __SDA_BASE_ = __SDA_BASE;
   } > ram

   .main_application_bss :
   {
      __START_SBSS = .;
      *(.sbss)
      *(SCOMMON)
      __END_SBSS = .;

      __START_BSS = .;
      *(.bss)
      *(COMMON)
      __END_BSS = .;
   } >> ram

    .kernel_data : #AT(ADDR(.main_application_bss) + SIZEOF(.main_application_bss))
   {
      ___KERNEL_DATA_START = ALIGN(0x10);
   }
   .end_of_kernel_data :
   {
      ___KERNEL_DATA_END = .;
   } > end_of_kd

   .boot_stack :
   {
      _stack_end = .;
   } > bstack
   .end_of_boot_stack :
   {
      _stack_addr  = .;
      __SP_INIT    = .;
      ___BOOT_STACK_ADDRESS = .;
   } > end_bstack

   # Locate the ROM copy table into ROM after the initialized data
   _romp_at = __COPY_OF_DATA + SIZEOF(.main_application_data);

   .romp : AT (_romp_at)
   {
      __S_romp = _romp_at;
      WRITEW(__COPY_OF_DATA);   #ROM start address
      WRITEW(ADDR(.main_application_data));      #RAM start address
      WRITEW(SIZEOF(.main_application_data));    #size
      WRITEW(0);
      WRITEW(0);
      WRITEW(0);
   }

    _flashx_start = __COPY_OF_DATA + SIZEOF(.main_application_data) +
                SIZEOF(.romp);

    # flashx working area spans across the whole rest of Flash memory
    ___FLASHX_START_ADDR = (_flashx_start + 0xfff) / 0x1000 * 0x1000;
    ___FLASHX_END_ADDR = ___INTERNAL_FLASH_BASE + ___INTERNAL_FLASH_SIZE;


}

/* EOF */

 

Also, here is my user config:

/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: user_config.h$
* $Version : 3.6.33.0$
* $Date    : Jun-14-2010$
*
* Comments:
*
*   User configuration for MQX components
*
*END************************************************************************/

#ifndef __user_config_h__
#define __user_config_h__

/* mandatory CPU identification */
#define MQX_CPU                 PSP_CPU_MCF52259

/*
** BSP settings - for defaults see mqx\source\bsp\<board_name>\<board_name>.h
*/
#define BSPCFG_ENABLE_RTCDEV     0
#define BSPCFG_ENABLE_TTYA       0
#define BSPCFG_ENABLE_TTYB       0
#define BSPCFG_ENABLE_TTYC       0
#define BSPCFG_ENABLE_ITTYA      1
#define BSPCFG_ENABLE_ITTYB      1
#define BSPCFG_ENABLE_ITTYC      0
#define BSPCFG_ENABLE_I2C0       0
#define BSPCFG_ENABLE_I2C1       0
#define BSPCFG_ENABLE_II2C0      1
#define BSPCFG_ENABLE_II2C1      1
#define BSPCFG_ENABLE_SPI0       0
#define BSPCFG_ENABLE_ISPI0      0
#define BSPCFG_ENABLE_ADC        0
#define BSPCFG_ENABLE_GPIODEV    1
#define BSPCFG_ENABLE_FLASHX     0

#define BSPCFG_RX_RING_LEN       4
#define BSPCFG_TX_RING_LEN       2

// added by SAM for the ADX and HLX projects
#define MQX_TASK_DESTRUCTION     1    // to use _task_abort and exit handlers
#define MQX_EXIT_ENABLED         0    // don't need to use _mqx_exit()
#define MQX_ROM_VECTORS             0     // not using ROM interrupt vectors (relocating into RAM)

/*
** board-specific MQX settings - see for defaults mqx\source\include\mqx_cnfg.h
*/

#define MQX_HAS_TIME_SLICE       1

/*
** board-specific RTCS settings - see for defaults rtcs\source\include\rtcscfg.h
*/

#define RTCSCFG_ENABLE_ICMP      1
#define RTCSCFG_ENABLE_UDP       1
#define RTCSCFG_ENABLE_TCP       1
#define RTCSCFG_ENABLE_STATS     0
#define RTCSCFG_ENABLE_GATEWAYS  1
#define FTPDCFG_USES_MFS         0

#define TELNETDCFG_NOWAIT        FALSE

/*
** include common settings
*/

/* use the rest of defaults from small-RAM-device profile */
#include "small_ram_config.h"

/* and enable verification checks in kernel */
#include "verif_enabled_config.h"

#endif
/* EOF */

 

As you can see, I'm telling MQX not to use ROM vectors, and I have a section 'tramp' which contains the address to jump to for the bootloader.

 

Thanks for any help!

Steve


Outcomes