FreeRTOS on MC9S12XE

Hello,

I am currently setting up FreeRTOS on the MC9S12XEQ384CAG microcontroller. The program compiles without any issues, but during programming and execution, the program stops at vTaskStartScheduler();.

Hi @pezhman
Welcome to the FreeRTOS Community Forums!

Could you please check the following in your application:

  1. Which port and compiler are you using for this MCU application?
  2. How many tasks are you creating before calling the vTaskStartScheduler() ?
  3. Is configASSERT defined in your FreeRTOSConfig.h file ?
  4. Can you put a breakpoint at vTaskStartScheduler(), step through it and see where exactly the program stops or might be stuck in a loop?
  • I’m using the Port.c provided by HCS12 with the CodeWarrior compiler.

  • I’m currently using two tasks.

  • configASSERT is not configured, and I’m not sure how to set it up.

          #ifndef FREERTOS_CONFIG_H
          #define FREERTOS_CONFIG_H
          
          #include <hidef.h>			/* common defines and macros */
          #include "TickTimer.h"
          
          /* This port requires the compiler to generate code for the BANKED memory
          model. */
          #define BANKED_MODEL
          
          /*-----------------------------------------------------------
           * Application specific definitions.
           *
           * These definitions should be adjusted for your particular hardware and
           * application requirements.
           *
           * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
           * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 
           *
           * See http://www.freertos.org/a00110.html
           *----------------------------------------------------------*/
          
          #define configUSE_PREEMPTION		1
          #define configUSE_IDLE_HOOK			1
          #define configUSE_TICK_HOOK			0
          #define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
          #define configMAX_PRIORITIES		( 4 )
          #define configMINIMAL_STACK_SIZE	( ( unsigned short ) 80 )
          #define configTOTAL_HEAP_SIZE		( ( size_t ) ( 10240 ) )
          #define configMAX_TASK_NAME_LEN		( 1 )
          #define configUSE_TRACE_FACILITY	0
          #define configUSE_16_BIT_TICKS		1
          #define configIDLE_SHOULD_YIELD		1
          
          /* Co-routine definitions. */
          #define configUSE_CO_ROUTINES 		0
          #define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
          
          /* This parameter is normally required in order to set the RTOS tick timer.
          This port is a bit different in that hardware setup uses the code generated by 
          the Processor Expert, making this definition obsolete.
          
          #define configCPU_CLOCK_HZ			( ( unsigned long ) 25000000 )
          */
          
          
          /* Set the following definitions to 1 to include the API function, or zero
          to exclude the API function. */
          
          #define INCLUDE_vTaskPrioritySet		1
          #define INCLUDE_uxTaskPriorityGet		1
          #define INCLUDE_vTaskDelete				1
          #define INCLUDE_vTaskCleanUpResources	0
          #define INCLUDE_vTaskSuspend			1
          #define INCLUDE_vTaskDelayUntil			1
          #define INCLUDE_vTaskDelay				1
          
          
          
          
          
          #endif /* FREERTOS_CONFIG_H */
    
  • When I reach this part:
    static BaseType_t xBankedStartScheduler( void )
    {
    /* Configure the timer that will generate the RTOS tick. Interrupts are
    disabled when this function is called. */
    prvSetupTimerInterrupt();

    /* Restore the context of the first task. */
    portRESTORE_CONTEXT();

    /* Simulate the end of an interrupt to start the scheduler off. */
    __asm( “rti” );

    /* Should not get here! */
    return pdFALSE;
    }

What happens when you reach this part? Can you break the code in debugger and see what it is doing when it appears hang? Are you able to step through the assembly and see which instruction is causing it to hang?

The HC12 port needs interrupt handlers in the Timer1 and SWI vectors. The processor expert overrides those handlers with calls to the event system provided by the processor expert. The FreeRTOS HC12 port does not use that system so the vectors must be replaced every time you use processor expert.

In the demo project https://github.com/FreeRTOS/FreeRTOS/tree/main/FreeRTOS/Demo/HCS12_CodeWarrior_banked/CODE you will find a file Copy of Vectors.c This file is in each of the codewarrior HC12 projects.

You need to install vPortTickInterrupt and vPortYield in the correct locations.

How can I send a test project to you for review?

/** ###################################################################
**     THIS COMPONENT MODULE IS GENERATED BY THE TOOL. DO NOT MODIFY IT.
**     Filename  : Vectors.c
**     Project   : OS_Test_Last
**     Processor : MC9S12XEQ384CAG
**     Version   : Component 01.003, Driver 02.06, CPU db: 3.00.038
**     Compiler  : CodeWarrior HCS12X C Compiler
**     Date/Time : 9/5/2023, 9:15 AM
**     Abstract  :
**         This component "MC9S12XEQ512_144" implements properties, methods,
**         and events of the CPU.
**     Settings  :
**
**
**     Copyright : 1997 - 2011 Freescale Semiconductor, Inc. All Rights Reserved.
**     
**     http      : www.freescale.com
**     mail      : support@freescale.com
** ###################################################################*/
#include "Cpu.h"
#include "TickTimer.h"
#include "Byte1.h"

/* ISR prototype */
typedef void (*near tIsrFunc)(void);
/*lint -save  -e950 Disable MISRA rule (1.1) checking. */
static const tIsrFunc _InterruptVectorTable[] @0xFF10U = { /* Interrupt vector table */
/*lint -restore Enable MISRA rule (1.1) checking. */
  /* ISR name                               No.  Address Pri XGATE Name            Description */
  &Cpu_Interrupt,                       /* 0x08  0xFF10   -   -    ivVsi           unused by PE */
  &Cpu_Interrupt,                       /* 0x09  0xFF12   -   -    ivVsyscall      unused by PE */
  &Cpu_Interrupt,                       /* 0x0A  0xFF14   -   -    ivVmpuaccesserr unused by PE */
  &Cpu_Interrupt,                       /* 0x0B  0xFF16   -   no   ivVxsei         unused by PE */
  &Cpu_Interrupt,                       /* 0x0C  0xFF18   1   no   ivVReserved115  unused by PE */
  &Cpu_Interrupt,                       /* 0x0D  0xFF1A   1   no   ivVReserved114  unused by PE */
  &Cpu_Interrupt,                       /* 0x0E  0xFF1C   1   no   ivVReserved113  unused by PE */
  &Cpu_Interrupt,                       /* 0x0F  0xFF1E   1   no   ivVReserved112  unused by PE */
  &Cpu_Interrupt,                       /* 0x10  0xFF20   1   no   ivVReserved111  unused by PE */
  &Cpu_Interrupt,                       /* 0x11  0xFF22   1   no   ivVReserved110  unused by PE */
  &Cpu_Interrupt,                       /* 0x12  0xFF24   1   no   ivVReserved109  unused by PE */
  &Cpu_Interrupt,                       /* 0x13  0xFF26   1   no   ivVReserved108  unused by PE */
  &Cpu_Interrupt,                       /* 0x14  0xFF28   1   no   ivVReserved107  unused by PE */
  &Cpu_Interrupt,                       /* 0x15  0xFF2A   1   no   ivVReserved106  unused by PE */
  &Cpu_Interrupt,                       /* 0x16  0xFF2C   1   no   ivVReserved105  unused by PE */
  &Cpu_Interrupt,                       /* 0x17  0xFF2E   1   no   ivVReserved104  unused by PE */
  &Cpu_Interrupt,                       /* 0x18  0xFF30   1   no   ivVReserved103  unused by PE */
  &Cpu_Interrupt,                       /* 0x19  0xFF32   1   no   ivVReserved102  unused by PE */
  &Cpu_Interrupt,                       /* 0x1A  0xFF34   1   no   ivVReserved101  unused by PE */
  &Cpu_Interrupt,                       /* 0x1B  0xFF36   1   no   ivVReserved100  unused by PE */
  &Cpu_Interrupt,                       /* 0x1C  0xFF38   1   no   ivVReserved99   unused by PE */
  &Cpu_Interrupt,                       /* 0x1D  0xFF3A   1   no   ivVReserved98   unused by PE */
  &Cpu_Interrupt,                       /* 0x1E  0xFF3C   1   no   ivVatd1compare  unused by PE */
  &Cpu_Interrupt,                       /* 0x1F  0xFF3E   1   no   ivVatd0compare  unused by PE */
  &Cpu_Interrupt,                       /* 0x20  0xFF40   1   no   ivVReserved95   unused by PE */
  &Cpu_Interrupt,                       /* 0x21  0xFF42   1   no   ivVReserved94   unused by PE */
  &Cpu_Interrupt,                       /* 0x22  0xFF44   1   no   ivVReserved93   unused by PE */
  &Cpu_Interrupt,                       /* 0x23  0xFF46   1   no   ivVReserved92   unused by PE */
  &Cpu_Interrupt,                       /* 0x24  0xFF48   1   no   ivVReserved91   unused by PE */
  &Cpu_Interrupt,                       /* 0x25  0xFF4A   1   no   ivVReserved90   unused by PE */
  &Cpu_Interrupt,                       /* 0x26  0xFF4C   1   no   ivVReserved89   unused by PE */
  &Cpu_Interrupt,                       /* 0x27  0xFF4E   1   no   ivVReserved88   unused by PE */
  &Cpu_Interrupt,                       /* 0x28  0xFF50   1   no   ivVReserved87   unused by PE */
  &Cpu_Interrupt,                       /* 0x29  0xFF52   1   no   ivVReserved86   unused by PE */
  &Cpu_Interrupt,                       /* 0x2A  0xFF54   1   no   ivVReserved85   unused by PE */
  &Cpu_Interrupt,                       /* 0x2B  0xFF56   1   no   ivVReserved84   unused by PE */
  &Cpu_Interrupt,                       /* 0x2C  0xFF58   1   no   ivVReserved83   unused by PE */
  &Cpu_Interrupt,                       /* 0x2D  0xFF5A   1   no   ivVReserved82   unused by PE */
  &Cpu_Interrupt,                       /* 0x2E  0xFF5C   1   no   ivVReserved81   unused by PE */
  &Cpu_Interrupt,                       /* 0x2F  0xFF5E   1   no   ivVReserved80   unused by PE */
  &Cpu_Interrupt,                       /* 0x30  0xFF60   1   no   ivVReserved79   unused by PE */
  &Cpu_Interrupt,                       /* 0x31  0xFF62   1   no   ivVReserved78   unused by PE */
  &Cpu_Interrupt,                       /* 0x32  0xFF64   1   no   ivVxst7         unused by PE */
  &Cpu_Interrupt,                       /* 0x33  0xFF66   1   no   ivVxst6         unused by PE */
  &Cpu_Interrupt,                       /* 0x34  0xFF68   1   no   ivVxst5         unused by PE */
  &Cpu_Interrupt,                       /* 0x35  0xFF6A   1   no   ivVxst4         unused by PE */
  &Cpu_Interrupt,                       /* 0x36  0xFF6C   1   no   ivVxst3         unused by PE */
  &Cpu_Interrupt,                       /* 0x37  0xFF6E   1   no   ivVxst2         unused by PE */
  &Cpu_Interrupt,                       /* 0x38  0xFF70   1   no   ivVxst1         unused by PE */
  &Cpu_Interrupt,                       /* 0x39  0xFF72   1   no   ivVxst0         unused by PE */
  &Cpu_Interrupt,                       /* 0x3A  0xFF74   1   no   ivVpit3         unused by PE */
  &Cpu_Interrupt,                       /* 0x3B  0xFF76   1   no   ivVpit2         unused by PE */
  &Cpu_Interrupt,                       /* 0x3C  0xFF78   1   no   ivVpit1         unused by PE */
  &Cpu_Interrupt,                       /* 0x3D  0xFF7A   1   no   ivVpit0         unused by PE */
  &Cpu_Interrupt,                       /* 0x3E  0xFF7C   1   -    ivVhti          unused by PE */
  &Cpu_Interrupt,                       /* 0x3F  0xFF7E   1   no   ivVapi          unused by PE */
  &Cpu_Interrupt,                       /* 0x40  0xFF80   1   no   ivVlvi          unused by PE */
  &Cpu_Interrupt,                       /* 0x41  0xFF82   1   no   ivViic1         unused by PE */
  &Cpu_Interrupt,                       /* 0x42  0xFF84   1   no   ivVsci5         unused by PE */
  &Cpu_Interrupt,                       /* 0x43  0xFF86   1   no   ivVsci4         unused by PE */
  &Cpu_Interrupt,                       /* 0x44  0xFF88   1   no   ivVsci3         unused by PE */
  &Cpu_Interrupt,                       /* 0x45  0xFF8A   1   no   ivVsci2         unused by PE */
  &Cpu_Interrupt,                       /* 0x46  0xFF8C   1   no   ivVpwmesdn      unused by PE */
  &Cpu_Interrupt,                       /* 0x47  0xFF8E   1   no   ivVportp        unused by PE */
  &Cpu_Interrupt,                       /* 0x48  0xFF90   1   no   ivVcan4tx       unused by PE */
  &Cpu_Interrupt,                       /* 0x49  0xFF92   1   no   ivVcan4rx       unused by PE */
  &Cpu_Interrupt,                       /* 0x4A  0xFF94   1   no   ivVcan4err      unused by PE */
  &Cpu_Interrupt,                       /* 0x4B  0xFF96   1   no   ivVcan4wkup     unused by PE */
  &Cpu_Interrupt,                       /* 0x4C  0xFF98   1   no   ivVReserved51   unused by PE */
  &Cpu_Interrupt,                       /* 0x4D  0xFF9A   1   no   ivVReserved50   unused by PE */
  &Cpu_Interrupt,                       /* 0x4E  0xFF9C   1   no   ivVReserved49   unused by PE */
  &Cpu_Interrupt,                       /* 0x4F  0xFF9E   1   no   ivVReserved48   unused by PE */
  &Cpu_Interrupt,                       /* 0x50  0xFFA0   1   no   ivVcan2tx       unused by PE */
  &Cpu_Interrupt,                       /* 0x51  0xFFA2   1   no   ivVcan2rx       unused by PE */
  &Cpu_Interrupt,                       /* 0x52  0xFFA4   1   no   ivVcan2err      unused by PE */
  &Cpu_Interrupt,                       /* 0x53  0xFFA6   1   no   ivVcan2wkup     unused by PE */
  &Cpu_Interrupt,                       /* 0x54  0xFFA8   1   no   ivVcan1tx       unused by PE */
  &Cpu_Interrupt,                       /* 0x55  0xFFAA   1   no   ivVcan1rx       unused by PE */
  &Cpu_Interrupt,                       /* 0x56  0xFFAC   1   no   ivVcan1err      unused by PE */
  &Cpu_Interrupt,                       /* 0x57  0xFFAE   1   no   ivVcan1wkup     unused by PE */
  &Cpu_Interrupt,                       /* 0x58  0xFFB0   1   no   ivVcan0tx       unused by PE */
  &Cpu_Interrupt,                       /* 0x59  0xFFB2   1   no   ivVcan0rx       unused by PE */
  &Cpu_Interrupt,                       /* 0x5A  0xFFB4   1   no   ivVcan0err      unused by PE */
  &Cpu_Interrupt,                       /* 0x5B  0xFFB6   1   no   ivVcan0wkup     unused by PE */
  &Cpu_Interrupt,                       /* 0x5C  0xFFB8   1   no   ivVflash        unused by PE */
  &Cpu_Interrupt,                       /* 0x5D  0xFFBA   1   no   ivVflashfd      unused by PE */
  &Cpu_Interrupt,                       /* 0x5E  0xFFBC   1   no   ivVspi2         unused by PE */
  &Cpu_Interrupt,                       /* 0x5F  0xFFBE   1   no   ivVspi1         unused by PE */
  &Cpu_Interrupt,                       /* 0x60  0xFFC0   1   no   ivViic0         unused by PE */
  &Cpu_Interrupt,                       /* 0x61  0xFFC2   1   no   ivVReserved30   unused by PE */
  &Cpu_Interrupt,                       /* 0x62  0xFFC4   1   no   ivVcrgscm       unused by PE */
  &Cpu_Interrupt,                       /* 0x63  0xFFC6   1   no   ivVcrgplllck    unused by PE */
  &Cpu_Interrupt,                       /* 0x64  0xFFC8   1   no   ivVectpabovf    unused by PE */
  &Cpu_Interrupt,                       /* 0x65  0xFFCA   1   no   ivVectmdcu      unused by PE */
  &Cpu_Interrupt,                       /* 0x66  0xFFCC   1   no   ivVporth        unused by PE */
  &Cpu_Interrupt,                       /* 0x67  0xFFCE   1   no   ivVportj        unused by PE */
  &Cpu_Interrupt,                       /* 0x68  0xFFD0   1   no   ivVatd1         unused by PE */
  &Cpu_Interrupt,                       /* 0x69  0xFFD2   1   no   ivVatd0         unused by PE */
  &Cpu_Interrupt,                       /* 0x6A  0xFFD4   1   no   ivVsci1         unused by PE */
  &Cpu_Interrupt,                       /* 0x6B  0xFFD6   1   no   ivVsci0         unused by PE */
  &Cpu_Interrupt,                       /* 0x6C  0xFFD8   1   no   ivVspi0         unused by PE */
  &Cpu_Interrupt,                       /* 0x6D  0xFFDA   1   no   ivVectpaie      unused by PE */
  &Cpu_Interrupt,                       /* 0x6E  0xFFDC   1   no   ivVectpaaovf    unused by PE */
  &Cpu_Interrupt,                       /* 0x6F  0xFFDE   1   no   ivVectovf       unused by PE */
  &Cpu_Interrupt,                       /* 0x70  0xFFE0   1   no   ivVectch7       unused by PE */
  &Cpu_Interrupt,                       /* 0x71  0xFFE2   1   no   ivVectch6       unused by PE */
  &Cpu_Interrupt,                       /* 0x72  0xFFE4   1   no   ivVectch5       unused by PE */
  &Cpu_Interrupt,                       /* 0x73  0xFFE6   1   no   ivVectch4       unused by PE */
  &Cpu_Interrupt,                       /* 0x74  0xFFE8   1   no   ivVectch3       unused by PE */
  &Cpu_Interrupt,                       /* 0x75  0xFFEA   1   no   ivVectch2       unused by PE */
  &Cpu_Interrupt,                       /* 0x76  0xFFEC   1   no   ivVectch1       unused by PE */
  &TickTimer_Interrupt,                 /* 0x77  0xFFEE   4   no   ivVectch0       used by PE */
  &Cpu_Interrupt,                       /* 0x78  0xFFF0   1   no   ivVrti          unused by PE */
  &Cpu_Interrupt,                       /* 0x79  0xFFF2   1   no   ivVirq          unused by PE */
  &Cpu_Interrupt,                       /* 0x7A  0xFFF4   -   -    ivVxirq         unused by PE */
  &Cpu_Interrupt,                       /* 0x7B  0xFFF6   -   -    ivVswi          unused by PE */
  &Cpu_Interrupt                        /* 0x7C  0xFFF8   -   -    ivVtrap         unused by PE */
};

/*lint -save  -e950 Disable MISRA rule (1.1) checking. */
static const tIsrFunc _ResetVectorTable[] @0xFFFAU = { /* Reset vector table */
/*lint -restore Enable MISRA rule (1.1) checking. */
  /* Reset handler name                    Address Name             Description */
  &_EntryPoint,                         /* 0xFFFA  ivVcop           unused by PE */
  &_EntryPoint,                         /* 0xFFFC  ivVclkmon        unused by PE */
  &_EntryPoint                          /* 0xFFFE  ivVreset         used by PE */
};
/*
** ###################################################################
**
**     This file was created by Processor Expert 3.05 [04.46]
**     for the Freescale HCS12X series of microcontrollers.
**
** ###################################################################
*/

When it reaches this part.

    #define portRESTORE_CONTEXT()                                   \
    {                                                               \
        extern volatile void * pxCurrentTCB;                        \
        extern volatile UBaseType_t uxCriticalNesting;  \
                                                                    \
        __asm( "ldx pxCurrentTCB" );                                \
        __asm( "lds 0, x" );                                        \
        __asm( "pula" );                                            \
        __asm( "staa uxCriticalNesting" );                          \
        __asm( "pula" );                                            \
        __asm( "staa 0x30" ); /* 0x30 = PPAGE */                    \
    }

Hi @pezhman
You can put your code in github and share it, so we can download and check the problem.
Else , you can zip all the source and project files, and upload it here , please let us know if you have any problem regarding uploading due to permission.

OS_Test_Last.zip (1.3 MB)

I have gone over your code and I think the root to the problem is your project is for the S12X variant of the HCS12 CPU. The X version has 1 additional byte in the stack frame for the extended condition code register. The HC12 port for FreeRTOS does not support the X version. The stack initialization code does not create the correct interrupt stack frame before starting the scheduler. This makes the first RTI of the scheduler break to invalid memory.

I added the extended CCR to the stack initialization code (line 129 of port.c) and the scheduler started and ran until another unhandled interrupt occurred.

    /* CCR: Note that when the task starts interrupts will be enabled since
    "I" bit of CCR is cleared */
    *pxTopOfStack = ( StackType_t ) 0x00;
    pxTopOfStack--;
    /* Extended CCR: */
    *pxTopOfStack = ( StackType_t ) 0x00;
    pxTopOfStack--;

If you have the hardware and can do additional testing, we would welcome a complete PR for the S12X version.

I neglected to revisit the Vectors.c file. Processor Expert had expertly removed the 2 interrupt vectors needed by FreeRTOS. I added those two vectors and FreeRTOS runs in the simulator.

I have updated your project with these changes and the new version is below.

OS_Test_Last 2.zip (1.8 MB)

In addition to the changes to the port, I also changed the project to static allocation. This is probably not critical to your application but it did allow me to watch the stack frames for each task without locating the frames on the heap.

Good Luck

1 Like

Thank you very much for your guidance.
When I execute the following function
vTaskDelayUntil( &xLastFlashTime, xFlashRate );
an issue arises in this part.

    /* Force a reschedule if xTaskResumeAll has not already done so, we may
             * have put ourselves to sleep. */
            if( xAlreadyYielded == pdFALSE )
            {
                #if ( configNUMBER_OF_CORES == 1 )
                    portYIELD_WITHIN_API();
                #else
                    vTaskYieldWithinAPI();
                #endif
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }

Would you please describe what issue?

I have been studying the vTaskDelayUntil() functionality and it appears that the tick timer is not happening. I will continue to look at it but you should verify that the vPortTickInterrupt() function is actually being called at the correct rate.