Porting HCS12 for GCC
I’m going to try to get FreeRTOS running on my C32 DIP module starting from
HCS12 -> MC9S12C32 (small)
http://www.freertos.org/porthcs12.html
The problem is that I am using GCC instead of CodeWarrior. It’s just more available.
Although I feel qualified to port the source for GCC, I wonder if anyone else is working or planning to make an official port to GCC.
Some related links
http://www.technologicalarts.ca/catalog/index.php/cPath/50_36
http://m68hc11.serveftp.org/
Porting HCS12 for GCC
I have not used GCC with this device, but I think the translation should be fairly straight forward. GCC is a very flexible compiler in general and tends to make life easy.
I think the original (unsupported) HCS12 port was configured so it could be built with either CodeWarrior or GCC. It is still available here:
http://www.realtimeengineers.com/hcs12.zip
I should copy the code from the supported port rather than this, but it might be useful for reference to the needed GCC syntax. It assumes the banked memory model.
I have just taken a look at the HCS12 GCC manual. One place to take care is interrupt function prologue and epilogue, and trap (SWI) function prologue and epilogue. They are not the same. Although the processor saves the registers it seems that GCC requires more data to be saved (soft registers). All required data needs saving and restoring in both interrupt and SWI cases.
As a tip to start I suggest setting the scheduler to use cooperative mode as this makes debugging much easier. Then just create a single task that runs at the idle priority and calls portYIELD(). You should then get simply switching between that task and the idle task. When you have that running you can try something more adventurous.
Let us know how you get on.
Regards.
Porting HCS12 for GCC
I didn’t mention before that I was working on the unsupported version before the supported version appeared. I realized that the supported version would be the better base, although I figure it will take some getting used to since 3.0 had significant changes. I will include the patch below (sorry if it’s not very readable).
I felt like my work was ready for a first test, but didn’t test it. Here are some issues with portability:
I addressed some interrupt details as you mentioned. I found that the gcc-m68hc1x port does not support the "naked" attribute, so I can’t tell it not to generate it’s own interrupt code. Also the code would need changed if the number of software registers (such as "._d0") changed
The example is changed for no longer for CodeWarrior. The leftovers might make it hard to read. I tried to keep the port files switchable, but not sure since it’s not tested.
The method of addressing IO ports is from the Ipac port in GEL examples. The file there is "gel-1.6.1/include/asm-m68hc12/arch-Ipac/arch/iodg256b.h". I added some defines to it for some popular bits used.
======== patch =========
Only in FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources: Makefile
diff -r -u FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/port.c FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/port.c
-– FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/port.c 2005-07-01 13:37:45.587354171 -0600
+++ FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/port.c 2005-04-08 14:48:51.000000000 -0600
@@ -1,5 +1,7 @@
/* This file is part of an "unsupported" FreeRTOS port distribution for
* Freescale MC9S12DP256B CPU.
+ *
+ * 2004-04-06 imajeff: modify to work with GCC
*/
/* Scheduler include files. */
@@ -14,7 +16,7 @@
#pragma MESSAGE DISABLE C12053
#include "6812dp256b.h"
#else
– #include "port.h"
+ #include <arch/iodg256b.h>
#endif
volatile unsigned char vPortSchRunning = 0;
@@ -231,7 +233,7 @@
CRGINT = (unsigned char) 0x80;
/* clear overflow interrupt flag */
– CRGFLG_RTIF = 1;
+ CRGFLG = RTIF;
}
/*———————————————————–*/
diff -r -u FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/portmacro.h FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/portmacro.h
-– FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/portmacro.h 2005-07-01 13:37:45.584354465 -0600
+++ FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/portmacro.h 2005-04-19 09:44:36.000000000 -0600
@@ -1,5 +1,7 @@
/* This file is part of an "unsupported" FreeRTOS port distribution for
* Freescale MC9S12DP256B CPU.
+ *
+ * 2005-04-06 gcc fixes, imajeff
*/
#ifndef PORTMACRO_H
@@ -42,7 +44,7 @@
* or a 32 bit value. See documentation on http://www.FreeRTOS.org to decide
* which to use.
*/
-#define USE_16_BIT_TICKS 0
+#define USE_16_BIT_TICKS 1
/*———————————————————–
@@ -72,8 +74,13 @@
#endif
/*———————————————————–*/
+#ifdef __HIWARE__
#define portDISABLE_RTI_INTERRUPT() CRGINT_RTIE = 0
#define portENABLE_RTI_INTERRUPT() CRGINT_RTIE = 1
+#else
+#define portDISABLE_RTI_INTERRUPT() CRGINT &= ~RTIE
+#define portENABLE_RTI_INTERRUPT() CRGINT |= RTIE
+#endif
/*———————————————————–*/
void vPortEnterCritical(void);
void vPortExitCritical(void);
@@ -118,7 +125,7 @@
#define vPortIsrTail()
{
/* reset pending RTI interrupt */
– CRGFLG_RTIF = 1;
+ CRGFLG = RTIF;
__asm__("rti");
}
@@ -126,6 +133,7 @@
/* hardware interrupt handler saves CCR, A, B, X, Y, so there’s no need to save
* them one more time */
+#ifdef __HIWARE__
#define portSAVE_CONTEXT()
{
extern volatile void * pxCurrentTCB;
@@ -144,5 +152,34 @@
__asm__("stab 0x30");
}
+#else /* GNUC */
+#define portSAVE_CONTEXT()
+{
+ __asm__(" n
+ .globl pxCurrentTCB n
+ movw _.frame, 2,-sp n
+ movw _.tmp, 2,-sp n
+ movw _.xy, 2,-sp n
+ movw _.z, 2,-sp n
+ movb 0x30, 1,-sp ; PPAGE n
+ sts pxCurrentTCB n
+ ");
+}
+
+#define portRESTORE_CONTEXT()
+{
+ __asm__(" n
+ .globl pxCurrentTCB n
+ lds pxCurrentTCB n
+ movb 1,+sp, 0x30 ; PPAGE n
+ movw _.z, 2,+sp n
+ movw _.xy, 2,+sp n
+ movw _.tmp, 2,+sp n
+ movw _.frame, 2,+sp n
+ ");
+}
+#endif
+
+
#endif /* PORTMACRO_H */
diff -r -u FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/queue.c FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/queue.c
-– FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/queue.c 2005-07-01 13:37:45.594353485 -0600
+++ FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/queue.c 2005-04-14 12:22:08.000000000 -0600
@@ -109,6 +109,7 @@
void vQueueDelete( xQueueHandle xQueue );
signed portCHAR cQueueSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portCHAR cTaskPreviouslyWoken );
signed portCHAR cQueueReceive( xQueueHandle pxQueue, void *pcBuffer, portTickType xTicksToWait );
+signed portCHAR cQueueReceiveFromISR( xQueueHandle pxQueue, void *pcBuffer, signed portCHAR *pcTaskWoken );
/*
* Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
diff -r -u FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/test.c FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/test.c
-– FreeRTOS-2.6.1/Source/portable/CodeWarrior/HCS12/sources/test.c 2005-07-01 13:37:45.589353975 -0600
+++ FreeRTOS-2.6.1-m/Source/portable/CodeWarrior/HCS12/sources/test.c 2005-04-18 17:22:43.000000000 -0600
@@ -1,36 +1,37 @@
-#include <6812dp256b.h> /* derivative information */
+/*
+ * 2004-04-06 imajeff: modifying to test FreeRTOS with HC12/GCC
+ */
+
+#include <arch/iodg256b.h> /* derivative information */
#include <stddef.h>
#include <stdio.h>
+#include <string.h>
#include "task.h"
#include "semphr.h"
-#pragma MESSAGE DISABLE C4002
-
-const char message[] = "This is a FreeRTOS test program. ";
-const char message2[] = "Semaphore work demonstration. ";
-const char charTable[] = "0123456789abcdef";
+void isrDefault7 (void);
+void testTask (void *);
+void testTask2 (void *);
+void pllConfig (void);
+
+const portCHAR message[] = "This is a FreeRTOS test program. ";
+const portCHAR message2[] = "Semaphore work demonstration. ";
+const portCHAR charTable[] = "0123456789abcdef";
xSemaphoreHandle xSemaphore;
-#pragma CODE_SEG NON_BANKED
-#pragma MESSAGE DISABLE C12053
-/* pay attention to _VECTOR section in PRM file */
-#pragma NO_EXIT
-__interrupt void isrDefault7(void)
+void isrDefault7 (void)
{
vPortIsrHead();
–
+
/* do interrupt stuff… */
– vPortIsrTail();
+ vPortIsrTail();
}
-#pragma MESSAGE DEFAULT C12053
-#pragma CODE_SEG DEFAULT
-
-void testTask(void * p)
+void testTask (void * p)
{
static const char * strMsg = message;
static unsigned int count = 0;
@@ -38,11 +39,6 @@
(void) p;
– /* initialize SCI: baud rate = 115200 with bus clock 16MHz */
– SCI1CR1 = 0x00;
– SCI1CR2 = 0x0c;
– SCI1BD = 0x09;
-
while (cSemaphoreTake(xSemaphore, 100) != pdTRUE)
{
portYIELD();
@@ -50,8 +46,9 @@
for (;;)
{
– while (!SCI1SR1_TDRE)
+ while (!SCI1SR1 & TDRE)
{
+ // waiting for byte on SCI
portYIELD();
}
SCI1DRL = *strMsg;
@@ -60,10 +57,11 @@
if (*strMsg == ‘