Commit 95954683 authored by Daniel Kampert's avatar Daniel Kampert 👷

- Rename some private variables

- Fix some bugs
- Update comments
- Optimize code
parent a95a9be9
......@@ -161,17 +161,16 @@ Bool_t Bootloader_Enter(void)
void Bootloader_Exit(void)
{
Bootloader_PutString("Leave bootloader...");
Bootloader_PutString("Leave bootloader...\n\r");
// Wait until last transmission finish
//while(!(((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->STATUS & USART_DREIF_bm));
// Wait until last transmission has finished
for(uint16_t i = 0x00; i < 0xFFFF; i++);
// Disable the SPM command
NVM_LockSPM();
// Reset the I/O
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_TX);
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_RX);
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_TX) | (0x01 << BOOTLOADER_RX);
// Disable the USART interface
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm);
......
......@@ -49,11 +49,9 @@
; -
;--
NVM_WaitBusy:
NVM_Busy_Loop:
lds r20, NVM_STATUS
sbrc r20, NVM_NVMBUSY_bp
rjmp NVM_Busy_Loop
lds r20, NVM_STATUS
sbrc r20, NVM_NVMBUSY_bp
rjmp NVM_WaitBusy
ret
......@@ -71,7 +69,6 @@ NVM_WaitBusy:
; -
;--
NVM_ExecuteSPM:
; Load the NVM command
sts NVM_CMD, r26
......@@ -99,7 +96,6 @@ NVM_ExecuteSPM:
.section .text
.global NVM_LockSPM
NVM_LockSPM:
; Load the signature register
ldi r18, CCP_IOREG_gc
......@@ -124,7 +120,6 @@ NVM_LockSPM:
.section .text
.global NVM_EraseApplication
NVM_EraseApplication:
; Save RAMPZ
in r18, RAMPZ
......@@ -138,8 +133,6 @@ NVM_EraseApplication:
; Execute SPM command
call NVM_ExecuteSPM
; Busy - wait
call NVM_WaitBusy
; Restore RAMPZ
......@@ -149,31 +142,7 @@ NVM_EraseApplication:
;--
; Input:
; -
;
; Return:
; -
;--
.section .text
.global NVM_ClearFlashBuffer
NVM_ClearFlashBuffer:
; Load NVM command
ldi r26, NVM_CMD_ERASE_FLASH_BUFFER_gc
sts NVM_CTRLA, r26
; Execute command
ldi r26, NVM_CMDEX_bp
sts NVM_CTRLA, r26
; Busy - wait
call NVM_WaitBusy
ret
;--
; Input:
; r24 Word address
; r25:r24 Word address
; r23:r22 Data byte
;
; Return:
......@@ -182,13 +151,13 @@ NVM_ClearFlashBuffer:
.section .text
.global NVM_LoadFlashBuffer
NVM_LoadFlashBuffer:
; Clear the Z pointer
clr ZH
clr ZL
; Save the word address
mov ZL, r24
mov ZH, r25
; Perform the address calculation
lsl ZL
......@@ -218,7 +187,6 @@ NVM_LoadFlashBuffer:
.section .text
.global NVM_FlushFlash
NVM_FlushFlash:
; Save RAMPZ
in r18, RAMPZ
......@@ -236,8 +204,6 @@ NVM_FlushFlash:
; Load NVM command
ldi r26, NVM_CMD_ERASE_WRITE_FLASH_PAGE_gc
call NVM_ExecuteSPM
; Busy - wait
call NVM_WaitBusy
; Restore RAMPZ
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) Daniel Kampert, 2018
* Website: www.kampis-elektroecke.de
* File info: AVR USART bootloader for XMega architecture.
* File info: USART bootloader for XMega architecture.
GNU GENERAL PUBLIC LICENSE:
This program is free software: you can redistribute it and/or modify
......@@ -23,9 +23,9 @@
*/
/** @file Common/Bootloader/Arch/XMega/USART_Bootloader_XMega.c
* @brief AVR USART bootloader for XMega architecture.
* @brief USART bootloader for XMega architecture.
*
* This file contains the implementation for the AVR USART bootloader for XMega architecture.
* This file contains the implementation for the USART bootloader for XMega architecture.
*
* @author Daniel Kampert
*/
......@@ -36,9 +36,9 @@
*/
static unsigned char _LineBuffer[PARSER_MAX_DATA_BYTES];
/** @brief Intel hex parser line object.
/** @brief Data block object for the parsing engine.
*/
static Parser_Line_t _Line = {
static Parser_Block_t _Line = {
.pBuffer = _LineBuffer,
};
......@@ -88,90 +88,98 @@ void Bootloader_Init(void)
: "r16", "r30"
);
// Enable the USART interface
// Configure the I/O for the USART interface
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRSET = (0x01 << BOOTLOADER_TX);
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_RX);
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->BAUDCTRLA = BOOTLOADER_BRREG_VALUE;
// Enable and configure the USART interface
((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;
// Initialize the hex file parser
Parser_Init();
// Disable the targets flow control
// Enable the transmitter by disabling the flow control
Bootloader_PutChar(XON);
}
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_SUCCESSFUL)
{
// Disable the transmitter
Bootloader_PutChar(XOFF);
Parser_State_t State = IntelParser_ParseLine(&_Line);
if(State == PARSER_STATE_SUCCESSFULL)
// Parsing successfully?
if((Parser_Parse(&_Line) == PARSER_STATE_SUCCESSFUL) && _Line.Valid)
{
if(_Line.Type == PARSER_TYPE_DATA)
{
for(uint8_t i = 0x00; i < _Line.Bytes; i = i + 0x02)
{
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;
Word += _Line.Bytes;
if(Word == APP_SECTION_PAGE_SIZE)
for(uint8_t i = 0x00; i < _Line.Length; i += 0x02)
{
Word = 0x00;
NVM_FlushFlash(Page++);
uint16_t CodeWord = (_LineBuffer[i + 1] << 0x08) | _LineBuffer[i];
NVM_LoadFlashBuffer(Offset + (i >> 0x01), CodeWord);
// Write the page when the buffer is full
if(Words++ == (APP_SECTION_PAGE_SIZE / 2))
{
NVM_FlushFlash(Page);
Words = 0x00;
}
}
}
}
else if(State == PARSER_STATE_ERROR)
else
{
// Error handling
return FALSE;
}
// Enable the transmitter
Bootloader_PutChar(XON);
}
} while(_Line.Type != PARSER_TYPE_EOF);
NVM_FlushFlash(Page);
return TRUE;
}
void Bootloader_Exit(void)
{
void (*Main)(void) = 0x0000;
Bootloader_PutString("Leave bootloader...");
// Wait until last transmission finish
while(!(((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->STATUS & USART_DREIF_bm));
Bootloader_PutString("Leave bootloader...\n\r");
// Wait until last transmission has finished
for(uint16_t i = 0x00; i < 0xFFFF; i++);
// Disable the SPM command
NVM_LockSPM();
// Reset the I/O
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_TX);
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_RX);
// Disable the USART
((PORT_t*)(&PORT_NAME(BOOTLOADER_INTERFACE)))->DIRCLR = (0x01 << BOOTLOADER_TX) | (0x01 << BOOTLOADER_RX);
// Disable the USART interface
((USART_t*)(&USART_NAME(BOOTLOADER_INTERFACE)))->CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm);
// Jump to application
// 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.
*
......@@ -39,8 +39,7 @@ typedef enum
PARSER_INIT = 0x00, /**< Initial state */
PARSER_GET_SIZE = 0x01, /**< Get the size from the line */
PARSER_GET_ADDRESS = 0x02, /**< Get the address from the line */
PARSER_GET_TYPE = 0x03, /**< Get the type from the line */
PARSER_GET_DATA = 0x04, /**< Get the data from the line */
PARSER_GET_TYPE = 0x03, /**< Get the type and the data from the line */
PARSER_GET_CHECK = 0x05, /**< Get the checksum from the line */
PARSER_HANDLE_ERROR = 0x06, /**< Error handler */
} StateMachine_t;
......@@ -49,15 +48,19 @@ typedef enum
*/
static uint8_t _ParserBuffer[PARSER_LENGTH_BYTES + PARSER_ADDRESS_BYTES + PARSER_TYPE_BYTES + (PARSER_MAX_DATA_BYTES * PARSER_DATA_BYTES) + PARSER_CHECK_BYTES];
/** @brief Current state for the parsing state machine.
/** @brief Boolean value to flag the parser as active.
*/
static StateMachine_t _ParserState;
static Bool_t _Active;
static Bool_t _IsActive;
/** @brief Current line buffer index.
*/
static uint8_t _Index;
/** @brief
/** @brief Current state for the parser state machine.
*/
static StateMachine_t _ParserState;
/** @brief Current state of the parsing engine.
*/
static Parser_State_t _ParserEngineState;
......@@ -69,11 +72,11 @@ static Parser_State_t _ParserEngineState;
static uint16_t Hex2Num(const uint8_t Length)
{
uint16_t Temp = 0x00;
for(uint8_t i = 0x00; i < Length; i++)
{
uint8_t c = _ParserBuffer[_Index++];
if(c >= '0' && c <= '9')
{
c -= '0';
......@@ -86,7 +89,7 @@ static uint16_t Hex2Num(const uint8_t Length)
{
c -= 'a' - 10;
}
Temp = (Temp << 0x04) + c;
}
......@@ -96,20 +99,20 @@ static uint16_t Hex2Num(const uint8_t Length)
void Parser_Init(void)
{
_ParserState = PARSER_INIT;
_Active = FALSE;
_IsActive = FALSE;
}
Parser_State_t Parser_GetLine(const uint8_t Received)
Parser_State_t Parser_GetByte(const uint8_t Received)
{
if(_Active)
if(_IsActive)
{
if(Received == PARSER_LINE_END)
{
_Index = 0x00;
_Active = FALSE;
_IsActive = FALSE;
_ParserState = PARSER_INIT;
return PARSER_STATE_SUCCESSFULL;
return PARSER_STATE_SUCCESSFUL;
}
if(_Index < sizeof(_ParserBuffer))
......@@ -124,19 +127,20 @@ Parser_State_t Parser_GetLine(const uint8_t Received)
}
}
// Wait for the beginning of a new line
if(Received == ':')
{
_Index = 0x00;
_Active = TRUE;
_IsActive = TRUE;
}
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;
do
{
switch(_ParserState)
......@@ -144,7 +148,7 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
case PARSER_INIT:
{
Line->Checksum = 0x00;
Line->Bytes = 0x00;
Line->Length = 0x00;
_ParserState = PARSER_GET_SIZE;
......@@ -153,7 +157,7 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
case PARSER_GET_SIZE:
{
uint8_t Length = Hex2Num(PARSER_LENGTH_BYTES);
Line->Bytes = Length;
Line->Length = Length;
Line->Checksum += Length;
_ParserState = PARSER_GET_ADDRESS;
......@@ -180,14 +184,64 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
{
case PARSER_TYPE_DATA:
{
_ParserState = PARSER_GET_DATA;
for(uint8_t i = 0x00; i < Line->Length; i++)
{
uint8_t Data = Hex2Num(PARSER_DATA_BYTES);
*(Line->pBuffer + i) = Data;
Line->Checksum += Data;
}
_ParserState = PARSER_GET_CHECK;
break;
}
case PARSER_TYPE_EOF:
{
_ParserState = PARSER_GET_CHECK;
break;
}
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:
{
break;
}
case PARSER_TYPE_SLA:
{
break;
}
default:
......@@ -200,28 +254,15 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
break;
}
case PARSER_GET_DATA:
{
for(uint8_t i = 0x00; i < Line->Bytes; i++)
{
uint8_t Data = Hex2Num(PARSER_DATA_BYTES);
*(Line->pBuffer + i) = Data;
Line->Checksum += Data;
}
_ParserState = PARSER_GET_CHECK;
break;
}
case PARSER_GET_CHECK:
{
uint8_t Checksum_Temp = ~(Line->Checksum & 0xFF) + 0x01;
Line->Checksum = Hex2Num(PARSER_CHECK_BYTES);
if(Line->Checksum == Checksum_Temp)
{
Line->Valid = TRUE;
_ParserEngineState = PARSER_STATE_SUCCESSFULL;
_ParserEngineState = PARSER_STATE_SUCCESSFUL;
}
else
{
......@@ -234,12 +275,12 @@ Parser_State_t IntelParser_ParseLine(Parser_Line_t* Line)
case PARSER_HANDLE_ERROR:
{
_ParserEngineState = PARSER_STATE_ERROR;
break;
}
}
}
while (_ParserEngineState == PARSER_STATE_BUSY);
while(_ParserEngineState == PARSER_STATE_BUSY);
return _ParserEngineState;
}
\ 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