Want to make your application software more reusable? Don't change the hardware, operating system, or your tools. Instead change the architectural framework within which you do your design. Part 3 in the three-part series gives additional elements in the reusable system software architecture.
MICROPORTS.H
Information in the microports.h file would contain bit definitions for the configuration registers and I/O ports. Microcontroller suppliers provide most of this information and in many cases they might even supply a predefined header file for use with the microcontroller. In the example, PORT A is an 8-bit port with bits defined Pax, where x is the bit number from 0 to 7, and a configuration data direction register (DDR) bits DDAx. BITx is defined in a top-level header file where all of the bits in the data type are set to zero except for the xth bit.
// I/O PORT A REGISTER
#define PA7 BIT7
#define PA6 BIT6
#define PA5 BIT5
#define PA4 BIT4
#define PA3 BIT3
#define PA2 BIT2
#define PA1 BIT1
#define PA0 BIT0
// I/O PORT A DATA DIRECTION REGISTER
#define DDA7 BIT7
#define DDA6 BIT6
#define DDA5 BIT5
#define DDA4 BIT4
#define DDA3 BIT3
#define DDA2 BIT2
#define DDA1 BIT1
#define DDA0 BIT0
The following is a truncated structure definition for the ports in a microcontroller. U8 stands for unsigned data type 8-bits long and is a reassignment of the standard C type defined in the COMPILER.H file.
typedef struct {
volatile U8 PORTA; // port A
volatile U8 PORTB; // port B
volatile U8 DDRA; // data direction port A
volatile U8 DDRB; // data direction port B
volatile U8 Reserved1;
volatile U8 Reserved2;
volatile U8 Reserved3;
volatile U8 Reserved4;
volatile U8 PORTE; // port E
volatile U8 DDRE; // data direction port E
volatile U8 PEAR; // port E assignment register
volatile U8 MODE; // mode register
volatile U8 PUCR; // pull-up control register
volatile U8 RDRIV; // reduced drive of I/O lines
volatile U8 Reserved8;
volatile U8 Reserved9;
. . .
. . .
. . .
} D60Regs_t;
VECTORS
A separate file would define the interrupt subroutine vector table. In the following example, the isr_00 label jumps to a routine that has, as its only function, a return from subroutine. The isr_00 label is included at every location in the vector table that doesn't have an associated interrupt subroutine. If for some reason, an interrupt occurs on a channel that is not defined, function is immediately returned to the main processing. The microcontroller supplier usually provides a template of this file.
// INTERRUPT VECTOR TABLE: LOCATED AT $FFC2 // - $FFFF FOR HC12d60
const _vectab[]=
{
isr_00,
// CGM lock and limp home
CAN_transmit_isr,
// MSCAN tranmit
CAN_receive_isr,
// MSCAN receive
CAN_error_isr,
// MSCAN errors
isr_00,
// Pulse Accumulator B overflow
isr_00,
// Modulus down counter underflow
isr_00,
// Key wake-up G or H
CAN_wakeup_isr,
// MSCAN wake-up
isr_00,
// ATD 0 or 1 interrupt
isr_00,
// SCI 1 interrupt
isr_00,
// SCI 0 interrupt
isr_00,
// SPI complete
isr_00,
// Pulse accumulator input
isr_00,
// Pulse accumulator overflow
isr_00,
// Timer overflow interrupt
isr_00,
// Timer channel 7 interrupt
ISR_THREE,
// Timer channel 6 interrupt USED FOR MAIN // LOOP CLOCK
isr_00,
// Timer channel 5 interrupt
isr_00,
// Timer channel 4 interrupt
isr_00,
// Timer channel 3 interrupt
isr_00,
// Timer channel 2 interrupt
isr_00,
// Timer channel 1 interrupt
ISR_TWO,
// Timer channel 0 interrupt 2ms BACKGROUND // LOOP CLOCK
isr_00,
// Real time interrupt
ISR_ONE,
// INTCR IRQ
isr_00,
// External interrupt request
isr_00,
// Software interrupt
isr_00,
// Unimplemented Instruction Trap
isr_00,
// COP failure reset
isr_00,
// Clock monitor fail reset
_stext,
// reset }
The rest of the ECU_HSIS.H would define the hardware to software interface. This file contains the following components:
1. The microcontroller's memory map.
2. System clock frequency defines.
3. Microcontroller peripheral definitions.
MICROCONTROLLER MEMORY MAP
Define the microcontrollers memory map upfront. This will help to quickly redefine the memory map when changing microcontrollers.
#define START_OF_REG_RAM (0x0800)
#define LENGTH_OF_REG_RAM (512)
// Register bytes
#define START_OF_BASE_RAM (0x0000)
#define LENGTH_OF_BASE_RAM (2048)
// RAM bytes
#define START_OF_EEPROM (0x0c00)
#define LENGTH_OF_EEPROM (1024)
// EEprom bytes
#define END_OF_EEPROM (START_OF_EEPROM+LENGTH_OF_EEPROM-1)
#define START_OF_ROM (0x1000)
#define START_OF_VECTOR_TABLE (0xFF00)
// ISR vector table
#define LENGTH_OF_VECTOR_TABLE (0xFF)