8 producing a banked hex file, 9 placing interrupts in banked code, 10 calling banked functions via function pointers – Maxim Integrated 71M6534 Energy Meter IC Family Software User Manual

Page 39: Producing a banked hex file, Placing interrupts in banked code, Calling banked functions via function pointers

Advertising
background image

71M653X Software User’s Guide

4.9.8 Producing a Banked Hex File

The BL51 linker and its associated hex converter produce a separate Intel hex file for each bank. These files end with
names such as .H01 for bank 1, .H02 for bank 2, etc. The emulator and the production programmer expect a single
Intel 386 hex file with a .HEX ending.

TSC’s demo CD ROM has a utility called bank_merge.exe. It runs in a DOS command window and merges the bank
files from Keil’s hex converter into one Intel-386 hex file. This can be placed in the build automatically. (how?)

Another manual solution is to erase the flash, load the .abs file to an emulator, and then use the file->save range: All
menu selection to save a copy of flash as an Intel hex file.

When using Keil’s Lx51 advanced linker, the output dialog contains a pull-down list of hex formats. Select the “i386”
hex file option.

The emulator’s verification option is a convenient way to verify that the .abs and .hex file have the same content. To
use it, invoke the menu File->Load, then check the verify box, but not the load box.

4.9.9 Placing Interrupts in Banked Code

The interrupts must start in the common code. TSC starts most interrupts from a “trampoline” routine that saves and
restores the bank register. The demo code’s trampoline routines are in Meter\io653x.c, with the stub interrupts and
decoded interrupts. An example of a trampoline is this serial interrupt from Meter\io653x.c, used to service UART0:

#pragma save

#pragma REGISTERBANK (ES0_BANK)

void es0_trampoline (void) small reentrant interrupt ES0_IV using ES0_BANK

{

uint8_t my_fl_bank = FL_BANK; // save the bank register

FL_BANK = BANK_DEFAULT; // BANK_DEFAULT is 1

es0_isr();

FL_BANK = my_fl_bank; // restore the bank register

}

#pragma restore

This is clumsy and slow. Why do this?

A trampoline lets most interrupt code be in bank-switched code space with other code from the same file. This may
make the code easier to read. It also leaves more space in common memory, and permits a larger system to exist.
The penalty is a few tens of microseconds per interrupt.

Very frequent interrupts should not use trampoline routines. In TSC’s demo code, the CE code, Meter\ce.c has an
interrupt that runs every 396 microseconds (ce_busy_isr()). ce.c is placed in the common area, and ce_busy’s
trampoline is disabled (in Meter\io653x.c).

If an interrupt calls code in a bank, as above, it must save and restore the bank-switching register, FL_BANK.

Keil’s Lx51 advanced linker has an option to automatically save and restore the bank register in an interrupt. TSC’s
L51_bank.a51 code provides the necessary symbols.

4.9.10

Calling Banked Functions via Function Pointers

In a banking system, functions placed in function pointers cannot have the word “static” in front of their definition. They
must be global.

Also, the linker must be informed of the actual caller of the function in the function pointers. For example, in the
TERIDIAN Demo Code, the software timer module (Util\stm.c) calls many routines. There is also an interrupt for
hardware timer 1 that calls the software timer’s interrupt code. This linker dialogue tells the linker the true relationship.
The command to the linker is “caller ! callee” or “caller ! (callee_1, callee_2, …)” (See the linker command figure, 0-3).

Why do this? If a function pointer points at a function’s entry in the page table, the function pointer can be executed
from any bank, at any time. So, in theory, function pointers are supported via the page table.

v1.1v1.1

TERIDIAN Proprietary

39 of 116

© Copyright 2005-2008 TERIDIAN Semiconductor Corporation

Advertising
This manual is related to the following products: