|
The Wind River's VxWorks Real Time operating system generally is used
in the mid-to-high size embedded systems with the considerable hardware resources (a few
megabytes of the RAM, networking, etc).
The VxWorks port for the LPC2106 ARM microprocessor shows an ability to use the VxWorks
in the minimal configuration (a LPC2106 has 128 KBytes internal FLASH and 64 KBytes
internal RAM).
A Tornado 2.2/VxWorks 5.5 for ARM has been used for the BSP (board support package) development
and a test project.
1. Minimal configuration
In the file config.h (part of the LPC2106 BSP), all VxWorks's components, enabled in
the system's file configAll.h, should be disabled. A Tornado's BSP/project creator
automatically includes in the project minimal set of the components for the system (kernel)
functionality (see the file prjComps.h in the test project directory):
/* minimal set of components - includes automatically*/
#define INCLUDE_DLL
#define INCLUDE_EXC_HANDLING
#define INCLUDE_EXC_TASK
#define INCLUDE_KERNEL
#define INCLUDE_MEMORY_CONFIG
#define INCLUDE_MEM_MGR_BASIC
#define INCLUDE_MSG_Q
#define INCLUDE_SEM_BINARY
#define INCLUDE_SYSCLK_INIT
#define INCLUDE_SYSHW_INIT
#define INCLUDE_SYS_START
#define INCLUDE_USER_APPL
#define INCLUDE_VXEVENTS
|
2. Memory map
A projects with the LPC2106 BSP use only the default_romResident build configuration (the system
code are in the FLASH, a data segment is copied into the RAM)
A BSP's memory configuration is described in the files Makefile and config.h (both are in the LPC2106 BSP's
directory):
- in the Makefile:
ROM_TEXT_ADRS = 00000000 # ROM entry address ROM_WARM_ADRS = 00000048 # ROM warm entry address ROM_SIZE = 00020000 # number of bytes of ROM space
RAM_LOW_ADRS = 40000600 # RAM text/data address () RAM_HIGH_ADRS = 40000F00 # RAM text/data address (is not used)
|
- in the config.h :
/*-------------- lpc2106base BSP configuration -----------------------*/
#undef ROOT_STACK_SIZE /* was 0x4000 */
#define ROOT_STACK_SIZE 0x800
#undef LOCAL_MEM_AUTOSIZE /* run-time memory sizing */
#define LOCAL_MEM_SIZE 0x10000 /* 64k */
#define USER_RESERVED_MEM 0x4000 /* 16k */
#define ROM_BASE_ADRS 0x00000000 #define ROM_TEXT_ADRS 0x00000000 /* code start addr in ROM */
#define ROM_SIZE 0x00020000 /* 128K */
#define ROM_COPY_SIZE ROM_SIZE #define ROM_SIZE_TOTAL 0x00020000 /* total size of ROM */
#define RAM_LOW_ADRS 0x40000600 /* VxWorks image entry point */
#define RAM_HIGH_ADRS 0x40000F00 /* RAM address for ROM boot - is not used */
#define LOCAL_MEM_LOCAL_ADRS 0x40000000 /* LPC21XX RAM start addr*/
#define LOCAL_MEM_BUS_ADRS 0x00000000
#undef INT_MODE
#define INT_MODE INT_NON_PREEMPT_MODEL
#undef ISR_STACK_SIZE
#define ISR_STACK_SIZE 0x400 /* size of ISR stack, in bytes */
#define BUS BUS_TYPE_NONE #define NV_RAM_SIZE NONE
|
3.
Interrupts vectors
After the hardware reset,
the LPC2106 starts from the address 0x0 (a FLASH
first address). Other exceptions vectors are placed at the addresses 0x04 - 0x1C.
For
the ARM architecture, a VxWorks expects that an exception pointers are placed (finally) at addreses 0x100-0x1C0 in the RAM.
To set an exceptions vectors in the RAM, the romInit() function
(an entry point for the VxWorks in the ROM/FLASH; a file romInit.s in the BSP
directory) contains an exceptions redirection code:
_romInit:
ldr pc, L$_reset_handler_address ldr pc, L$_undef_handler_address ldr pc, L$_swi_handler_address ldr pc, L$_pabort_handler_address ldr pc, L$_dabort_handler_address .long 0xB8A06F58 /* LPC2XXX specific, 0 - (sum of other vectors instructions) */
ldr pc, L$_irq_handler_address ldr pc, L$_fiq_handler_address
L$_reset_handler_address: .long reset_handler L$_undef_handler_address: .long LOCAL_MEM_LOCAL_ADRS + 0x04 /*undef_handler*/
L$_swi_handler_address: .long LOCAL_MEM_LOCAL_ADRS + 0x08 /*swi_handler*/
L$_pabort_handler_address: .long LOCAL_MEM_LOCAL_ADRS + 0x0C /*pabort_handler*/
L$_dabort_handler_address: .long LOCAL_MEM_LOCAL_ADRS + 0x10 /*dabort_handler*/
.long 0x00 L$_irq_handler_address: .long LOCAL_MEM_LOCAL_ADRS + 0x18 /*irq_isr_handler*/
L$_fiq_handler_address: .long reset_handler /* FIQ is not processed*/
reset_handler: b cold
cold: MOV r0, #BOOT_COLD /* fall through to warm boot entry */
warm:
B start
...
|
In the file sysLib.c (the BSP's directory), the lpc2106IntVectSet()
function is added to make a final exception vectors remapping. This function's call should
be placed inside the sysHwInit() function (to initialize the CPU board
hardware).
/* This is a VxWorks's internal interrupt handling routines prototypes */
extern void excEnterUndef(void); extern void excEnterSwi(void); extern void excEnterPrefetchAbort(void); extern void excEnterDataAbort(void); extern void intEnt(void);
...
void lpc2106IntVectSet(void) { unsigned int * ptr;
#define RAM_VECTORS_BASE (LOCAL_MEM_LOCAL_ADRS + 0x100)
/*--- Set instruction to call handlers ---*/
ptr = (unsigned int *)(LOCAL_MEM_LOCAL_ADRS + 0x04); /*undef_handler */
*ptr = 0xE59FF0F8; /* ldr pc[pc,0xF8] -> pc = pc + 0x100 */
ptr = (unsigned int *)(LOCAL_MEM_LOCAL_ADRS + 0x08); /*swi_handler */
*ptr = 0xE59FF0F8; /* ldr pc[pc,0xF8] -> pc = pc + 0x100 */
ptr = (unsigned int *)(LOCAL_MEM_LOCAL_ADRS + 0x0C); /*pabort_handler */
*ptr = 0xE59FF0F8; /* ldr pc[pc,0xF8] -> pc = pc + 0x100 */
ptr = (unsigned int *)(LOCAL_MEM_LOCAL_ADRS + 0x10); /*dabort_handler */
*ptr = 0xE59FF0F8; /* ldr pc[pc,0xF8] -> pc = pc + 0x100 */
ptr = (unsigned int *)(LOCAL_MEM_LOCAL_ADRS + 0x18); /*irq_isr_handler */
*ptr = 0xE59FF0F8; /* ldr pc[pc,0xF8] -> pc = pc + 0x100 */
/*--- Set handlers ---*/
ptr = (unsigned int *)(RAM_VECTORS_BASE + 0x04); *ptr = (unsigned int)&excEnterUndef;
ptr = (unsigned int *)(RAM_VECTORS_BASE + 0x08); /* you can use ptr++ instead */
*ptr = (unsigned int)&excEnterSwi;
ptr = (unsigned int *)(RAM_VECTORS_BASE + 0x0C); *ptr = (unsigned int)&excEnterPrefetchAbort;
ptr = (unsigned int *)(RAM_VECTORS_BASE + 0x10); *ptr = (unsigned int)&excEnterDataAbort;
ptr = (unsigned int *)(RAM_VECTORS_BASE + 0x18); *ptr = (unsigned int)&intEnt; }
|
VxWorks has the own internal
function to initialize exception vectors -
excVecInit(). This function has been written on
the assumption that a RAM (not a ROM) is placed at the address 0x0. Using this
function in the LPC2106 BSP will crash a system.
A problem here (to avoid this function's using) is that the Tornado's BSP/project
creator automatically includes this
function into the usrInit() function
(a file prjConfig.c; the project
directory) after each
rebuilding of the project.
A simple (and, probably, not the best) way to cancel this automatic including
is to set as a comment name of the
excVecInit() function in the file /target/config/comps/vxWorks/00vxWorks.cdf:
Component INCLUDE_EXC_HANDLING {
NAME exception handling
MODULES excArchLib.o
INIT_RTN /* excVecInit (); */
HDR_FILES excLib.h
}
|
4. Interrupts
controller
An interrupts
controller's routines for the LPC2106 are very similar to the VxWorks's
example /target/src/drv/intrCtl/ambaIntrCtl.c.
For the LPC2106,
- AMBA_INT_CSR_ENB (the "Enable Set"
register) is a VICIntEnable register (address-0xFFFFF010)
- AMBA_INT_CSR_DIS (the "Enable Clear" register) is a VICIntEnClear
register (address-0xFFFFF014)
- AMBA_INT_CSR_PEND
(the "Interrupt Request" register) is a VICIRQStatus register (address-0xFFFFF000)
5. System Clocks
A VxWorks in the minimal
configuration needs only the system clock. In the LPC2106 BSP,
a Timer 0 is used as a system clock's interrupt source. In
the
sysClkInt()
function the interrupt source should be cleared:
void sysClkInt (void) { rTIMER0_IR = 0xFF; /* clear interrupt source */
/* call system clock service routine */
if(sysClkRoutine != NULL) (* sysClkRoutine) (sysClkArg); }
|
This is an example of the Timer 0 configuration (the sysClkEnable() function):
void sysClkEnable (void) { if(!sysClkRunning) { /* Prscaler register and prescaler counter */
rTIMER0_PR = 0;
rTIMER0_PC = 0;
/* Timer counter - to 0 */
rTIMER0_TC = 0;
/* Period */
rTIMER0_MR0 = PRC_CLK / sysClkTicksPerSecond;
/* clear Timer 0 interrupt source */
rTIMER0_IR = 0xFF;
rTIMER0_MCR = 2; /* bit 1=1 - Reset on MR0 */
/* Enable Register MR0 Interrupt in the timer */
rTIMER0_MCR |= 1; /* bit 0=1 -int on MR0 */
/* Enable the timer(run) */
rTIMER0_TCR = 1;
/* enable Timer 0 interrupt in interrupt controller */
intEnable(INT_LVL_TIMER_0);
sysClkRunning = TRUE;
}
}
|
6. User
application
For the BSP's framework debugging, a very simple user task is
used. This task performs just the LED blinking (the file usrAppInit.c in the project directory):
void tLEDBlink(void) { for(;;) { taskDelay(10); rGPIO_IOCLR |= LED_MSK; taskDelay(10); rGPIO_IOSET |= LED_MSK; } }
void usrAppInit (void) {
#ifdef USER_APPL_INIT USER_APPL_INIT; /* for backwards compatibility */
#endif
int tid;
tid = taskCreat("tLEDBlink",255, 0, 2048,(FUNCPTR)tLEDBlink,0,0,0,0,0,0,0,0,0,0);
taskActivate(tid);
}
|
7. FLASH and RAM
using
For the test project (LPC2106 in ARM mode, VxWorks 5.5, Tornado 2.2 GNU (GCC 2.9) Compiler):
- The overall FLASH using is ~81 KBytes (no optimization), ~77 KBytes (optimization: 2)
- The RAM using (without the malloc() pool) is ~11 KBytes
|