Commit 769733d7 authored by Daniel Kampert's avatar Daniel Kampert 👷

Rework bootloader to meet the intel hex file specification

parent 099d84be
......@@ -142,7 +142,7 @@ NVM_EraseApplication:
;--
; Input:
; r24 Word address
; r25:r24 Word address
; r23:r22 Data byte
;
; Return:
......@@ -157,6 +157,7 @@ NVM_LoadFlashBuffer:
; Save the word address
mov ZL, r24
mov ZH, r25
; Perform the address calculation
lsl ZL
......
......@@ -38,7 +38,7 @@ static unsigned char _LineBuffer[PARSER_MAX_DATA_BYTES];
/** @brief Intel hex parser line object.
*/
static Parser_Line_t _Line = {
static Parser_Block_t _Line = {
.pBuffer = _LineBuffer,
};
......@@ -93,7 +93,7 @@ void Bootloader_Init(void)
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_RX);
// Enable and configure the USART interface
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->BAUDCTRLA = BOOTLOADER_BRREG_VALUE;
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->BAUDCTRLA = (BOOTLOADER_BRREG_VALUE & 0xFF) << USART_BSEL_gp;
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->BAUDCTRLB = (BOOTLOADER_SCALE_VALUE << USART_BSCALE_gp) & USART_BSCALE_gm;
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->CTRLB = USART_RXEN_bm | USART_TXEN_bm;
......@@ -106,43 +106,53 @@ void Bootloader_Init(void)
Bool_t Bootloader_Enter(void)
{
Bootloader_PutString("Enter bootloader...\n\r");
uint16_t Word = 0x00;
uint16_t Page = 0x00;
uint8_t Offset = 0x00;
uint16_t Words = 0x00;
Bootloader_PutString("Enter bootloader...\n\r");
do
{
Parser_State_t LineRead = Parser_GetLine(Bootloader_GetChar());
if(LineRead == PARSER_STATE_SUCCESSFULL)
if(Parser_GetByte(Bootloader_GetChar()) == PARSER_STATE_SUCCESSFULL)
{
// Disable the transmitter
Bootloader_PutChar(XOFF);
// Parse a new line
Parser_State_t State = IntelParser_ParseLine(&_Line);
//
if(State == PARSER_STATE_SUCCESSFULL)
// Parsing successfully?
if(Parser_Parse(&_Line) == PARSER_STATE_SUCCESSFULL)
{
if(_Line.Type == PARSER_TYPE_DATA)
switch(_Line.Type)
{
for(uint8_t i = 0x00; i < _Line.Bytes; i += 0x02)
case(PARSER_TYPE_DATA):
{
uint16_t CodeWord = (_LineBuffer[i + 1] << 0x08) | _LineBuffer[i];
NVM_LoadFlashBuffer((_Line.Address + i) >> 0x01, CodeWord);
uint32_t Address = (_Line.Offset + _Line.Address) >> 0x01;
Offset = Address & 0xFF;
Page = (Address & 0x3FF00) >> 0x08;
for(uint8_t i = 0x00; i < _Line.Bytes; i += 0x02)
{
uint16_t CodeWord = (_LineBuffer[i + 1] << 0x08) | _LineBuffer[i];
NVM_LoadFlashBuffer(Offset + (i >> 0x01), CodeWord);
// Write the page when the buffer is full
Words++;
if(Words == (APP_SECTION_PAGE_SIZE / 2))
{
NVM_FlushFlash(Page);
Words = 0x00;
}
}
break;
}
Word += _Line.Bytes;
if(Word == APP_SECTION_PAGE_SIZE)
default:
{
Word = 0x00;
NVM_FlushFlash(Page++);
break;
}
}
}
else if(State == PARSER_STATE_ERROR)
else
{
// Error handling
......@@ -161,8 +171,6 @@ Bool_t Bootloader_Enter(void)
void Bootloader_Exit(void)
{
void (*Main)(void) = 0x0000;
Bootloader_PutString("Leave bootloader...");
// Wait until last transmission finish
......@@ -180,5 +188,9 @@ void Bootloader_Exit(void)
// Clear the extended indirect register and jump to the main application
EIND = 0x00;
Main();
asm volatile("ld %0, Z" "\n\t"
"ijmp" "\n\t"
:: "r" (_Line.StartAddress)
: "r30", "r31"
);
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
*
* Copyright (C) Daniel Kampert, 2018
* Website: www.kampis-elektroecke.de
* File info: Parser for the Intel-Hex file.
* File info: Bootloader parser for the Intel-Hex file.
GNU GENERAL PUBLIC LICENSE:
This program is free software: you can redistribute it and/or modify
......@@ -23,7 +23,7 @@
*/
/** @file Common/Parser/IntelHexParser.c
* @brief Parser for the Intel-Hex file format.
* @brief Bootloader parser for the Intel-Hex file format.
*
* This file contains the implementation for the Intel-Hex file format parser.
*
......@@ -54,6 +54,8 @@ static StateMachine_t _ParserState;
static Bool_t _Active;
/** @brief Current line buffer index.
*/
static uint8_t _Index;
/** @brief
......@@ -98,7 +100,7 @@ void Parser_Init(void)
_Active = FALSE;
}
Parser_State_t Parser_GetLine(const uint8_t Received)
Parser_State_t Parser_GetByte(const uint8_t Received)
{
if(_Active)
{
......@@ -123,6 +125,7 @@ Parser_State_t Parser_GetLine(const uint8_t Received)
}
}
// Wait for the beginning of a new line
if(Received == ':')
{
_Index = 0x00;
......@@ -132,7 +135,7 @@ Parser_State_t Parser_GetLine(const uint8_t Received)
return PARSER_STATE_BUSY;
}
Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
Parser_State_t Parser_Parse(Parser_Block_t* Line)
{
_ParserEngineState = PARSER_STATE_BUSY;
......@@ -198,10 +201,37 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
}
case PARSER_TYPE_ESA:
{
Line->Offset = 0x00;
for(uint8_t i = 0x00; i < 0x02; i++)
{
uint8_t Data = Hex2Num(PARSER_DATA_BYTES);
Line->Offset |= Data;
Line->Offset <<= 0x04;
Line->Checksum += Data;
}
// Multiply the address with 4 (according to the specification)
Line->Offset <<= 0x04;
_ParserState = PARSER_GET_CHECK;
break;
}
case PARSER_TYPE_SSA:
{
Line->StartAddress = 0x00;
for(uint8_t i = 0x00; i < 0x04; i++)
{
uint8_t Data = Hex2Num(PARSER_DATA_BYTES);
Line->StartAddress |= Data;
Line->StartAddress <<= 0x04;
Line->Checksum += Data;
}
_ParserState = PARSER_GET_CHECK;
break;
}
case PARSER_TYPE_ELA:
......
......@@ -133,7 +133,7 @@
</avrgcc.linker.libraries.Libraries>
<avrgcc.linker.memorysettings.Flash>
<ListValues>
<Value>.text=0xFFFF</Value>
<Value>.text=0x10000</Value>
</ListValues>
</avrgcc.linker.memorysettings.Flash>
<avrgcc.assembler.general.IncludePaths>
......
......@@ -51,7 +51,7 @@
* @param Offset Word address
* @param Data Data word
*/
void NVM_LoadFlashBuffer(const uint8_t Offset, const uint16_t Data);
void NVM_LoadFlashBuffer(const uint16_t Offset, const uint16_t Data);
/** @brief Flush the page buffer and write the content into the flash memory.
* @param Page Page address
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) Daniel Kampert, 2018
* Website: www.kampis-elektroecke.de
* File info: Parser for the Intel-Hex file.
* File info: Bootloader parser for the Intel-Hex file.
GNU GENERAL PUBLIC LICENSE:
This program is free software: you can redistribute it and/or modify
......@@ -23,7 +23,8 @@
*/
/** @file Common/Parser/IntelHexParser.h
* @brief Parser for the Intel-Hex file format.
* @brief Bootloader parser for the Intel-Hex file format.
* NOTE: Please check https://en.wikipedia.org/wiki/Intel_HEX for additional information.
*
* This contains the prototypes and definitions for the Intel-Hex file format parser.
*
......@@ -68,33 +69,34 @@
PARSER_TYPE_SLA = 0x05, /**< Start linear address record */
} Parser_Type_t;
/** @brief Intel-Hex file line object
/** @brief Code block object for Intel-Hex file
*/
typedef struct
{
uint8_t Bytes; /**< Byte count */
uint16_t Bytes; /**< Byte count */
uint16_t Address; /**< Address */
uint32_t Offset; /**< Offset address */
uint32_t StartAddress; /**< Start address */
Parser_Type_t Type; /**< Record type */
unsigned char* pBuffer; /**< Pointer to data buffer */
uint16_t Checksum; /**< Checksum */
Bool_t Valid; /**< Valid flag */
} Parser_Line_t;
} Parser_Block_t;
/** @brief Initialize the parser.
*/
void Parser_Init(void);
/** @brief Receive a byte, store it into the line buffer and wait for a complete line.
/** @brief Receive a byte, store it in the line buffer and wait for a complete block.
* @param Received Received byte
* @return #PARSER_STATE_SUCCESSFULL when line end
*/
Parser_State_t Parser_GetLine(const uint8_t Received);
Parser_State_t Parser_GetByte(const uint8_t Received);
/** @brief Parse the line buffer into a #IntelHexParser_Line_t object. Must be called after #IntelHexParser_GetLine.
* @param Line Pointer to line object
* @return Parser state. Must be polled until #PARSER_STATE_SUCCESSFULL or #PARSER_STATE_ERROR is returned
*/
Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line);
Parser_State_t Parser_Parse(Parser_Block_t* Line);
#endif /* INTELHEXPARSER_H_ */
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment