You are here: Home DOCUMENTATION NanoCore12 NanoCore12 ImageCraft C Tutorial

Technological Arts Inc.

Your Shopping Cart

Your Cart is currently empty.

NanoCore12 ImageCraft C Tutorial


It is assumed that you have already installed ICC7 for CPU12, found at before proceeding with this tutorial.

Before starting, you’ll need to set up your compiler settings, as follows:
Program Memory = 0x4000.0x7FFF:0xC000.0xFFFF
Data Memory = 0x3800 (use 0x3000 if using a ‘C128 module)
Stack Pointer = 0x3FC0

Note that the Data Memory and Stack Pointer addresses shown are valid only for a device with the resident monitor active (i.e. in Load mode), since the monitor remaps the RAM following reset.  If you don't need to actively debug using the monitor, and intend to run your program directly from reset (i.e in Run mode), or aif you are writing software for a completely blank chip, and loading it in via a BDM pod, you can change these values to what works best for you (see the MCU data sheet).

//Blinks Docking Module or School Board LED D2 twice a second
//Time delay implemented via Real-time Interrupt

#include <hcs12c32.h>

#define DUMMY_ENTRY    (void (*)(void))0xFFFF

#pragma nonpaged_function _start

extern void _start(void);    /* entry point in crt12.s */

void main(){
INTR_ON();          //to support debugging via the SerialMonitor
DDRT = 0x01;         //Enable LED port (use 0x04 for NC12MAX)
RTICTL = 0x7F;    //Set RTI divider for 4Hz time base
CRGFLG |= 0x80;      //Clear the RTI Flag
CRGINT |= 0x80;      //Enable the RTI }

#pragma interrupt_handler rti_handler
void rti_handler(){
  CRGFLG |= 0x80; // Clear the RTI Flag
  PTT ^= 0x01; //Toggle LED (use 0x04 for NC12MAX)
  INTR_ON(); //Enable Interrupts

#pragma abs_address:0xFFF0

void (*interrupt_vectors[])(void) =
  rti_handler, /*Real Time Interrupt*/
  DUMMY_ENTRY, /*Unimplemented Instruction Trap*/
  DUMMY_ENTRY, /*COP failure reset*/
  DUMMY_ENTRY, /*Clock monitor fail reset*/
  _start, /*Reset*/


Because the register addresses have changed from what they were in the older HC12 chips (meaning the header file is different for the 9S12C), some library files in ICC will need to be re-compiled, using the new header file, if you want to use them.  Of course, if you’re not using library functions, or you are using functions that don’t involve registers, then there won’t be a problem with the existing versions.  Some  modified functions are included in our Support Library, to get you started.
To use the SCI, make sure to include C32_iochar.c and C32_serial.c.  Also, you’ll need the complete vector file for S12C, which is called s12c_vectors.c.  Make sure to place s12c_Vectors.c in the same folder as your project, and add it to you project via the “add file menu item”.  (By the way, the same files work for the C128.)


No introduction to using C with a microcontroller would be complete without demonstrating how to implement the standard "Hello World!" program. First of all, create a new project from the Project menu. Then create a new file and save it as HelloWorld.c   Add it to the Project by right clicking in the Project Panel and using Add Files to add it to the Files section.

Next type into the helloworld.c file the following code:

#define _SCI
#include <hcs12c32.h>

#pragma nonpaged_function _start
extern void _start(void);    /* entry point in crt12.s */
extern int _textmode;
int putchar(char c)
    if (_textmode && c == ‘\n’)
    while ((SC0SR1 & TDRE) == 0);
    SC0DRL = c;
    return c;

void main(){
    INTR_ON();          //need to enable interrupts for the SerialMonitor
    SCI0BD = 26; //9600 Baud
    SCI0CR2 = 0x0C; /* enable transmitter and receiver */
    puts(“Hello, World!”);    
#pragma abs_address:0xFFFE
void (*interrupt_vectors[])(void) =
    _start, /*Reset*/

Since puts calls putchar, we define putchar before invoking puts in main. Main has an implicit _Start entry point, which is called after the setup by CRT12.o, which is a module that the ICC12 linker links in as the starting point of the program.  Besides initializing the stack and other system features, it initializes memory, initialized variables and constants before transferring control to the Main.
Compile and link the program, fixing any syntax errors that may have cropped up.  Ensure that the Project Options | Device Configuration drop down box points to the 9S12C32 Flash Mode.  This sets the link address to start the code section at 0x4000 and the stack at top of RAM (0x4000).


You may have to convert the s-record file to get it into the proper format for your BDM pod to load correctly.  Your s-records must contain an even number of bytes, and begin on an even address boundary if you’re going to “burn” them into flash.  Some assemblers will generate this format for you but others (such as AS12) don’t.  In the latter case, you’ll need to use the Freescale utility called SRECCVT.  ICC12 has a nice feature at Project->Options->Compiler->ExecuteCommandAfterBuild where you can add the SRECCVT command.    Use the following command line:
        sreccvt.exe -m C0000 FFFFF 32 -lp -o outfile.s2 infile.s19
where infile refers to the file you are converting and outfile is the result.


If you have a BDM pod, you can erase the resident monitor program completely.  This will free up all the MCU resources for your program (most importantly, the SCI).  Without the monitor in place, the RAM will be at the default location following reset, so make sure to use the correct compiler/linker settings if you want to move the RAM so that it doesn't overlap the register block.  Also, keep in mind that the PLL won’t be enabled, so the bus speed will be 4 MHz.