weAut_01 / weAutSys    R 2.2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines
Defines | Functions | Variables
Bootloader integration
+ + Bootloader support + +

Overview

The serial AVR109 bootloader is implemented as an integral part of weAutSys / weAut_01. It is designed to be (by fuse setting) the entry point for all reset or restart.

Hence the board should always come with this bootloader in its (upper flash) place and be fused to enter it on reset. All the basic (weAut_01) initialisations are then done anyway by the bootloader. On an external or power on reset this bootloader will after a quite short time without receiving ESC jump to the system/application software start, see Bootloader operation for details and Bootloader support for an overview and further references.

There the initialisation tasks already done may (and will) be omitted from the "normal" system software (according to the value of USE_BOOTLOADER). Additionally functions and constants provided by the integrated bootloader (see file boot109.h) may be linked to and used by system or application software. About building and linking the bootloader see the descriptive part of file boot109.c and download and read
    Albrecht Weinert
    A serial bootloader for weAut_01, ArduinoMega and akin

for more information on re-using bootloader functions in the application software.

Defines

#define FAR_ADD(varHF)
 Generate a far address for high flash memory items.
#define getSerByte()
 Basic function: UART(0) get one byte already received.
#define isSerByteRec()
 Basic function: UART(0) has one byte received.
#define LOW_ADD(varLF)
 Generate a far address for low flash memory items.

Functions

void appMain (uint8_t init) __attribute__((noreturn))
 Jump to application program.
void basicSystemInit (void)
 Initialise system resources.
void bootMain (void) __attribute__((noreturn))
 Jump to the bootloader.
char * copyChars_P (char *dst, ADDR_T src, uint8_t mxLen)
 Copy a string from flash memory to RAM.
void initUART0 (uint32_t baudRate, uint8_t x2, uint8_t parity, uint8_t stopBits, uint8_t useInt)
 Initialise the serial input (UART0)
uint8_t recvErrorState (void)
 Get UART receive error status and flush receiver on error.
uint8_t recvSerByte (void)
 Basic UART receive one byte.
ADDR_T resetCauseText_P (uint8_t resetCauses)
 The reset cause text.
void sendSerByte (uint8_t c)
 Basic UART send one byte (guarded)
void sendSerBytes (char *src)
 Basic UART0 send multiple bytes from RAM.
void sendSerBytes_P (ADDR_T src)
 Basic UART send multiple bytes from flash.
void toHMI8LEDchain (uint8_t val)
 Output to a chain of eight HMI/visible LEDs.
void wait25 (void)
 A very basic delay function keeping the CPU busy for about 25µs.
uint8_t waitSerByte (uint8_t tOut)
 Basic UART wait for a byte received.

Variables

char const bootloaderPlatf []
 Bootloader's platform name and CPU frequency.
char const bootloaderWlc []
 Bootloader's welcome greeting and copyright notice.
char const bootResetCause0 []
 no reset cause: exit from from active bootloader or by command
char const bootResetCause1 []
 reset cause: power on
char const bootResetCause2 []
 reset cause: external
char const bootResetCause4 []
 reset cause: brown out
char const bootResetCause8 []
 reset cause: watchdog
char const bootResetCauseG []
 reset cause: JTAG
char const bootResetCauseN []
 reset cause: not known
char const bootTextReset []
 The text "Reset by:".
char const bootTextRevis []
 The text "Revision:".
char const greetEmptFlash []
 Greeting for empty application flash.

Define Documentation

#define FAR_ADD (   varHF)

Generate a far address for high flash memory items.

avr-gcc is restricted (may say dumb) enough always to deliver 16 bit addresses respectively pointers for variables even if they reside by INFLASH or PROGMEM in higher addresses. Note that the ATmega1284P e.g. has 128K flash memory and the ATmega2560 e.g. has 256Kbyte.

Hence if for example the boatloader flash array timOutCountPatr is finally at address 0x01e20c &timOutCountPatr[1] will (with avr-gcc) be 0x0e20d instead of 0x1e20d.
Using FAR_ADD(timOutCountPatr[1]) supplies both the &-operator and the missing 0x10000 respectively 0x30000, correcting the error described.

For devices with less than 64KByte = 32KWords flash memory this macro's value is just &(varHF).

To get a 32 bit address for an item in the lowest 64kbyte of use the macro LOW_ADD instead.
Note that both macros FAR_ADD and LOW_ADD cover all flash of an ATmega1284P but only half of the ATmega2560's flash.
Note: Hopefully in future, avg-gcc will automatically switch to 24bit pointers on larger devices and automatically handle them correctly. What, in the end, we have higher level languages and their compilers for? But, alas, as of end 2015 this is still not the case.

Parameters:
varHFa variable in the highest 64Kbyte flash memory block. This covers any bootloader space.
Do not supply a pointer; the & (i.e. the address operator) will be applied to the parameter.
#define LOW_ADD (   varLF)

Generate a far address for low flash memory items.

This macro provides a 16 or 32 bit address (ADDR_T) for an item (a variable) in lowest 64Kbate segment of the memory. The upper 16 bits of the address provided this way are 0.

Use this macro to make a 16 or 32 bit address (ADDR_T) parameter for e.g. sendSerBytes_P. Giving a (16 bit) pointer here would work by the (correct) automatic cast, also — but with a compiler warning.

Parameters:
varLFa variable in the lowest 64Kbyte flash memory block. This covers the (start of) application space.
Do not supply a pointer; the & (i.e. the address operator) will be applied to the parameter.
See also:
FAR_ADD
Examples:
main.c.
#define isSerByteRec ( )

Basic function: UART(0) has one byte received.

This expression is non-zero if the UART(0) has one received byte ready

#define getSerByte ( )

Basic function: UART(0) get one byte already received.

This is essentially the unguarded version of recvSerByte(void). In other words it has to be guarded by waitSerByte(uint8_t tOut) or by isSerByteRec().


Function Documentation

void basicSystemInit ( void  )

Initialise system resources.

This function does the basic initialisations for the target hardware and runtime. It essentially disables all interrupts and initialises the ports and other resources except the UART (for that see initUART0).
The situations to use are

  • after reset
  • before a system re-initialisation

that is

  • before entering the bootloader
  • before leaving the bootloader (to enter application software)
void toHMI8LEDchain ( uint8_t  val)

Output to a chain of eight HMI/visible LEDs.

If the target hardware has a line of eight LEDs this function sets them according to parameter val. Otherwise nothing is done.
The pre-condition is these eight LEDs being independently controllable by software without any side-effects on I/O to an external process controlled by the target hardware.

With weAut_01 these are the eight green digital input (DI) display LEDs.
With ArduinoMega and easyAVR — assuming above conditions to be met — it might be just one eight bit output port named by the macro CHAIN8LED_PORT. If no setting is made for a chain of 8 independent LEDs and the macro NO_CHAIN8LED is defined an implementation may just do nothing (without compile time warning).

void appMain ( uint8_t  init)

Jump to application program.

First of all this function disables all interrupts and the watchdog and does a basicSystemInit() if init is not 0. Parameter init should only be OFF if a ref basicSystemInit "basic initialisation" has been done and those settings haven't been spoiled.

This function then initialises the UART (0) with or without interrupt usage depending on the platform.

With freshly set zeroReg and stackpointer this function will then go to the normal program's start in the flash memory. Hence it will never return to the caller.

Parameters:
initON: do full basicSystemInit() also
See also:
bootMain
void bootMain ( void  )

Jump to the bootloader.

At first this function disables all interrupts and the watchdog.

With freshly set zeroReg and stackpointer this function will then go to the bootloader's start in the flash memory. Hence this function will never return to the caller.

See also:
appMain
void initUART0 ( uint32_t  baudRate,
uint8_t  x2,
uint8_t  parity,
uint8_t  stopBits,
uint8_t  useInt 
)

Initialise the serial input (UART0)

UART 0 is initialised in asynchronous mode for receiving and transmitting (full duplex). A recommended baudRate is 38400; it's fast enough for communication and even boot loading and still robust enough for critical or long lines.

If in doubt x2 should be OFF. It is needed only for very high baudRates with respect to the CPU clock frequency (F_CPU). And some exotic baudrate F_CPU combinations get higher accuracy with x2 ON.

Parameters:
baudRatethe rate desired (usually 38400)
x2true: double speed (half receive samples)
parity0=false: none; odd , even value: odd, even
stopBits2: 2 stop bits, 1 [default]: 1 stop bit
See also:
uartSetBaudDivide
Parameters:
useInttrue: use UART interrupts
ADDR_T resetCauseText_P ( uint8_t  resetCauses)

The reset cause text.

According to the bits defined for the MCUSR register this function returns a (flash memory) pointer to

  " power on   ", " external reset ", " power (brown) out ",
  " watchdog reset    ", " jtag reset ", " no reset (by command?) "
   or " unknown cause ".
Parameters:
resetCausesThe µC's reset info as by MCUSR
Returns:
a 32 or 16 bit pointer (ADDR_T) to a 0-terminated String in high (bootloader) flash memory
void wait25 ( void  )

A very basic delay function keeping the CPU busy for about 25µs.

Calling this function will keep the CPU busy for 500 cycles (two less for small flash devices) on a 20 MHz platform (weAut_01). That will take 25µs. On slower platforms with e.g. 16 MHz (Arduino) the number of cycles is, of course, proportionally reduced.

char* copyChars_P ( char *  dst,
ADDR_T  src,
uint8_t  mxLen 
)

Copy a string from flash memory to RAM.

This function copies a String

  • from flash memory pointed to by a 32 bit address src
  • to a RAM buffer pointed to by (normal) pointer dst.

The function copies up to mxLen-1 characters from src to dst and appends a trailing 0. Returned is the address of the last character in dst modified (i.e. the 0's address).

Rationale: Besides a variety of functions to handle and output strings in RAM weAutSys features a second (sub-) set of functions to handle / output strings in flash memory, their names usually ending in P or _P. Insofar these functions usually save the trouble of copying strings form flash to RAM (prior to output e.g.). But due to avr-gcc C pointer limitations the standard flash variable handling won't work above 64K byte, as is the case with bootloader variables on large flash devices. A third set of functions for those use cases can hardly be justified. Here the workaround is "copy to an intermediate RAM buffer and use RAM handling functions". That workaround is support by this function.

Parameters:
dstthe destination to modify (in RAM, not null!)
srcthe source (string) to copy from (in flash memory, not null!)
mxLenthe maximum number of characters to modify in dst including the trailing 0 appended. The maximum advance of the return value to parameter dest
Returns:
dst + number of characters modified; NULL only if dst is NULL
See also:
getSomeCharsP(char*, prog_char*, uint8_t)
FAR_ADD
LOW_ADD
resetCauseText_P()
void sendSerByte ( uint8_t  c)

Basic UART send one byte (guarded)

This is a very basic send function for the initialised UART(0). It will wait for the UART being ready to accept the next byte to be transmitted. If the UART is not initialised or handled correctly it may wait endlessly.

This functions uses spin waiting and hence the respective remarks for recvSerByte apply.

Parameters:
cthe character or byte to be sent
void sendSerBytes_P ( ADDR_T  src)

Basic UART send multiple bytes from flash.

This is a very basic send function for the initialised UART. It uses spin waiting and hence the remarks for sendSerByte apply.

Parameters:
srcpointer to the first character or byte to be sent in of the 0-terminated string. Must not be null.
See also:
recvSerByte
FAR_ADD
LOW_ADD
sendSerBytes
Examples:
main.c.
void sendSerBytes ( char *  src)

Basic UART0 send multiple bytes from RAM.

This is a very basic send function for the initialised UART. It uses spin waiting and hence is meant for situations without any threading support (or interrupt), as e.g. early initialisation phases or bootloaders.

Parameters:
srcpointer to the first character or byte to be sent in of the 0-terminated string, must not be null
See also:
recvSerByte
sendSerByte
sendSerBytes_P
uint8_t waitSerByte ( uint8_t  tOut)

Basic UART wait for a byte received.

This is a very basic receive function for the initialised UART. It uses spin waiting for a received byte timeout of tOut/10 seconds.

Cause of this spin waiting this function is meant for situations without any threading support (or interrupt), as e.g. early initialisation phases or bootloaders.

Parameters:
tOuta time out in 100 ms (1..254)
Returns:
0: a byte was received; not 0: timeout
See also:
recvSerByte
uint8_t recvSerByte ( void  )

Basic UART receive one byte.

This is a very basic receive function for the initialised UART. If no received byte is ready it will endlessly wait for it. To avoid this it may be guarded by waitSerByte — in which case the (unguarded) macro getSerByte() may also be used.

This function uses spin waiting and would hence be blocking all other activities. It is meant for situations without any threading support (or interrupts), as e.g. early initialisation phases or in bootloaders. And it is, of course, never to be used with an armed watchdog.

Returns:
the character or byte received
See also:
sendSerByte
uint8_t recvErrorState ( void  )

Get UART receive error status and flush receiver on error.

This function retrieves and returns the error status of an initialised UART(0). If no error occurred 0 is returned and nothing else done.

Otherwise the initialised UART's receiver is flushed.

Returns:
0 on no error or at least one of bits 4 (framing error), 3 (overrun error) or 2 (parity error) is set
See also:
recvSerByte

Variable Documentation

char const bootloaderWlc[]

Bootloader's welcome greeting and copyright notice.

This is a four line text in (high!) flash memory plus three starting and two trailing empty lines. It is meant for display as well as embedded copyright notice.

char const greetEmptFlash[]

Greeting for empty application flash.

This is a one line text in (high!) flash memory plus two starting and one trailing empty lines. It says:
remain in bootloader: application flash empty

char const bootloaderPlatf[]

Bootloader's platform name and CPU frequency.

This is a one line text in (high!) flash memory ending in a linefeed.

char const bootTextRevis[]

The text "Revision:".

This is a text block in (high!) flash memory (0-terminated).

char const bootTextReset[]

The text "Reset by:".

This is a text block in (high!) flash memory (0-terminated).