1 startup and initialization, 4 basic code architecture, Startup and initialization – Maxim Integrated 71M6534 Energy Meter IC Family Software User Manual

Page 52: Basic code architecture

Advertising
background image

71M653X Software User’s Guide

5.3.1 Startup and Initialization

The top-level functionality of the Demo Board is controlled by the high-level functions. The start-up code and main loop
is in the main() program (in main\main.c). It performs the following steps:

1. Reset watchdog timer

2. Process the pushbutton (PB) when in BROWNOUT mode.

3. Initialize hardware, pointers, metering variables, UART buffers and pointers, CE, restoration of calibration co-

efficients, initialization of LCD w/ “HELLO” message), enabling CE and pulse generators.

4. Execute

the

main_run()

routine in an endless loop. In this loop, the background tasks, such as metering,

processing of timers, etc. are performed. In this loop, if a command is waiting, the command line interface
(CLI) reads it and does it.

Before the MPU gets to execute the main() program, it will execute the startup code contained in the STARTUP.A51
assembly program. This code jumps form the reset vector, at address 0x0000, to C_START, the startof the
initialization code.

After disabligninterrupts, setting the security bit (if needed) and clearing memory, STARTUP.A51 jumps to C_START,
in Keil’s assembly program init.A51 (in Keil/C51/LIB). Init.A51 sets up the 8051 for Keil C and jumps to main(). The
startup files are described in section 5.10 .

The stack is located at 0x80, growing to higher values, while the reentrant stack is located at 0xFF, growing down-
wards.

Once operating, the main() program expects regular interrupts from the CE.

The main() program calls the main_init()and the main_run() routines. main_init() initializes the meter’s
hardware and software. main_run() is the main loop.

5.4 BASIC CODE ARCHITECTURE

The TERIDIAN 71M653X firmware can be divided into two code parts, the main loop (or “background”), and the
interrupts (or “foreground”).

The initialization and main loop takes care of the non time-critical functions. After the meter is initialized, the main loop
runs all the time. The main loop is a small loop near the end of main() in main\main.c.

The main loop performs multitasking by calling a different subroutine for each major system task. The subroutines
called in the main loop are usually either waiting for data, or the data is available and they can process it.

If they are waiting, they test a flag or counter and then return to the main loop, freeing the MPU to call other
subroutines. The meter doesn’t have many tasks, so checking flags is much faster than putting event records in a
queue and then interpreting them. (Queuing is the other common scheme.) It’s also easier to read the code.

These task routines will be discussed more below.

As much code as possible is called from the main loop. This helps the Keil linker to use less RAM when it organizes
the overlays for the temporary variables. Also, code for the main loop is easier to write than interrupt code. For
example, the software timers’ update routine, stm_run() (Util\stm.c) is called from the main loop (see
main_background()

in main\main.c) instead of a timer interrupt, because it reduces the chances that a timer routine

will be called in an unexpected way at an unexpected time.

The meter has to keep running while waiting for serial input or output from the user. So, the main loop has two parts
(see main_run()and main_background() in main\main.c). The serial input and output routines call
main_background()

to keep the meter running while waiting for serial input from or output. For example, see

Serial0_CTx() in cli\ser0cli.c. main_background() calls the task subroutines needed to keep the meter running.
main_run()

calls the serial input and output code (e.g. the command line interface or an AMR system) in addition to

calling main_background() to run the meter. Thus, no routine called from main_background() should perform
serial I/O, because the serial I/O might try to call main_background() and this could cause an infinite recursion that
would overflow the stack. The Keil linker automatically generates a “recursion error” if such code is written.

The second part is the interrupt-driven code (Foreground), such as the CE_BUSY Interrupt, Timer Interrupt, and other
Interrupt service routines. The interrupt service routines (ISRs) get the data, and set a flag or counter to tell the
background routine to stop waiting. These will be discussed more below.

v1.1v1.1

TERIDIAN Proprietary

52 of 116

© Copyright 2005-2008 TERIDIAN Semiconductor Corporation

Advertising
This manual is related to the following products: