Compare commits
5 Commits
6f9d8bae42
...
5f8d6a6f85
Author | SHA1 | Date | |
---|---|---|---|
5f8d6a6f85 | |||
41f81247ce | |||
a72bf67b07 | |||
3a04b1f488 | |||
8979066420 |
@ -2,6 +2,8 @@
|
||||
|
||||
#include "uart/uart.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <avr/boot.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
@ -9,7 +11,10 @@
|
||||
|
||||
#include "command.hpp"
|
||||
|
||||
using uart_interface = uart::Hardware0<uart::Config<115200>, uart::Driven::BLOCKING>;
|
||||
static constexpr auto TIMEOUT = 5000;
|
||||
static constexpr auto BAUD_RATE = 115200;
|
||||
|
||||
using uart_interface = uart::Hardware0<uart::Config<BAUD_RATE>, uart::Driven::BLOCKING>;
|
||||
uart::Uart<uart_interface> serial;
|
||||
|
||||
struct Message {
|
||||
@ -21,11 +26,26 @@ struct Message {
|
||||
uint8_t checksum;
|
||||
};
|
||||
|
||||
static inline bool receiveByte(uint8_t &data, uint32_t timeout = 100000)
|
||||
static inline bool receiveByte(uint8_t &data, uint16_t &timeout)
|
||||
{
|
||||
for (uint32_t i = 0; i < timeout; ++i) {
|
||||
if (serial.rxByte(data))
|
||||
constexpr auto MICROSECOND = 1000.0 * 1000;
|
||||
constexpr auto SYMBOL_SIZE = 9;
|
||||
constexpr auto BYTE_DELAY_US = (SYMBOL_SIZE * MICROSECOND) / BAUD_RATE;
|
||||
constexpr auto NUM_MS_DELAY_STEPS = static_cast<uint16_t>(round(1000 / BYTE_DELAY_US));
|
||||
uint16_t msDelay = NUM_MS_DELAY_STEPS;
|
||||
|
||||
while (timeout) {
|
||||
if (serial.rxByte(data)) {
|
||||
timeout = TIMEOUT;
|
||||
return true;
|
||||
}
|
||||
|
||||
_delay_us(BYTE_DELAY_US);
|
||||
|
||||
if (--msDelay == 0) {
|
||||
msDelay = NUM_MS_DELAY_STEPS;
|
||||
--timeout;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -42,23 +62,23 @@ static inline uint8_t calcChecksum(const Message &msg)
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static inline bool receiveMessage(Message &msg)
|
||||
static inline bool receiveMessage(Message &msg, uint16_t &timeout)
|
||||
{
|
||||
if (!receiveByte(msg.start) || msg.start != MESSAGE_START)
|
||||
if (!receiveByte(msg.start, timeout) || msg.start != MESSAGE_START)
|
||||
return false;
|
||||
if (!receiveByte(msg.number))
|
||||
if (!receiveByte(msg.number, timeout))
|
||||
return false;
|
||||
if (!receiveByte(*(reinterpret_cast<uint8_t *>(&msg.size) + 1)))
|
||||
if (!receiveByte(*(reinterpret_cast<uint8_t *>(&msg.size) + 1), timeout))
|
||||
return false;
|
||||
if (!receiveByte(*reinterpret_cast<uint8_t *>(&msg.size)) || msg.size > sizeof(msg.body))
|
||||
if (!receiveByte(*reinterpret_cast<uint8_t *>(&msg.size), timeout) || msg.size > sizeof(msg.body))
|
||||
return false;
|
||||
if (!receiveByte(msg.token) || msg.token != TOKEN)
|
||||
if (!receiveByte(msg.token, timeout) || msg.token != TOKEN)
|
||||
return false;
|
||||
for (uint16_t i = 0; i < msg.size; ++i) {
|
||||
if (!receiveByte(msg.body[i]))
|
||||
if (!receiveByte(msg.body[i], timeout))
|
||||
return false;
|
||||
}
|
||||
if (!receiveByte(msg.checksum) || msg.checksum != calcChecksum(msg))
|
||||
if (!receiveByte(msg.checksum, timeout) || msg.checksum != calcChecksum(msg))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -216,6 +236,8 @@ static inline void formatGetParameterAnswer(Message &msg)
|
||||
msg.body[2] = 2;
|
||||
} else if (msg.body[1] == PARAM_OSC_CMATCH) {
|
||||
msg.body[2] = 127;
|
||||
} else if (msg.body[1] == PARAM_TOPCARD_DETECT) {
|
||||
msg.body[2] = 0xFF;
|
||||
} else {
|
||||
msg.size = 2;
|
||||
}
|
||||
@ -299,13 +321,15 @@ static inline void formatLoadAddressAnswer(Message &msg)
|
||||
|
||||
static inline void formatReadFlashIspAnswer(Message &msg, uint32_t &addr)
|
||||
{
|
||||
const uint16_t byteAddress = 2 * addr;
|
||||
const uint16_t numBytes = static_cast<uint16_t>(msg.body[1]) << 8 | msg.body[2];
|
||||
msg.size = 3 + numBytes;
|
||||
msg.body[1] = STATUS_CMD_OK;
|
||||
for (uint16_t i = 0; i < numBytes; ++i) {
|
||||
msg.body[i + 2] = pgm_read_byte(static_cast<uint16_t>(addr + i));
|
||||
msg.body[i + 2] = pgm_read_byte(static_cast<uint16_t>(byteAddress + i));
|
||||
}
|
||||
addr += numBytes;
|
||||
const auto numWords = numBytes / 2;
|
||||
addr += numWords;
|
||||
msg.body[numBytes + 2] = STATUS_CMD_OK;
|
||||
|
||||
msg.checksum = calcChecksum(msg);
|
||||
@ -381,17 +405,17 @@ static inline uint32_t getFlashSize()
|
||||
return (FLASHEND - bootloaderSize + 1);
|
||||
}
|
||||
|
||||
static inline void performChipErase()
|
||||
static inline void performChipErase(uint16_t flashStartAddress = 0x0000)
|
||||
{
|
||||
constexpr auto getEepromEraseFuseBit = []() -> bool {
|
||||
constexpr auto EESAVE = 3;
|
||||
return boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & (1 << EESAVE);
|
||||
};
|
||||
|
||||
constexpr auto eraseFlash = []() {
|
||||
constexpr auto eraseFlash = [](const uint16_t &flashStartAddress) {
|
||||
const auto flashSize = getFlashSize();
|
||||
|
||||
for (uint16_t i = 0; i < flashSize; i += SPM_PAGESIZE) {
|
||||
const auto byteAddress = 2 * flashStartAddress;
|
||||
for (uint16_t i = byteAddress; i < flashSize; i += SPM_PAGESIZE) {
|
||||
boot_page_erase(i);
|
||||
boot_spm_busy_wait();
|
||||
}
|
||||
@ -409,7 +433,7 @@ static inline void performChipErase()
|
||||
}
|
||||
};
|
||||
|
||||
eraseFlash();
|
||||
eraseFlash(flashStartAddress);
|
||||
eraseEeprom();
|
||||
}
|
||||
|
||||
@ -437,10 +461,12 @@ static inline void formatReadEepromIspAnswer(Message &msg, uint32_t &addr)
|
||||
|
||||
static inline void formatProgramFlashIspAnswer(Message &msg, uint32_t &addr)
|
||||
{
|
||||
if (addr < getFlashSize())
|
||||
writeFlashPage(addr, msg.body + 10);
|
||||
const auto byteAddress = 2 * addr;
|
||||
if (byteAddress < getFlashSize())
|
||||
writeFlashPage(byteAddress, msg.body + 10);
|
||||
const uint16_t numBytes = static_cast<uint16_t>(msg.body[1]) << 8 | msg.body[2];
|
||||
addr += numBytes;
|
||||
const auto numWords = numBytes / 2;
|
||||
addr += numWords;
|
||||
|
||||
msg.size = 2;
|
||||
msg.body[1] = STATUS_CMD_OK;
|
||||
@ -480,10 +506,12 @@ static inline void formatErrorAnswer(Message &msg)
|
||||
}
|
||||
|
||||
enum class ChipEraseState {
|
||||
NONE = 0b00,
|
||||
REQUEST = 0b01,
|
||||
RESPONSE = 0b10,
|
||||
PERFORM = 0b11,
|
||||
NONE = 0,
|
||||
REQUEST = (1 << 1),
|
||||
RESPONSE = (1 << 2),
|
||||
PERFORM = REQUEST | RESPONSE,
|
||||
PROGRAM = (1 << 3),
|
||||
FINISH = REQUEST | RESPONSE | PROGRAM,
|
||||
};
|
||||
|
||||
constexpr ChipEraseState operator|(const ChipEraseState &self, const ChipEraseState &other)
|
||||
@ -497,7 +525,8 @@ constexpr ChipEraseState &operator|=(ChipEraseState &self, const ChipEraseState
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void handleMessage(Message &msg, uint32_t &addr, ChipEraseState &chipEraseFlag)
|
||||
static inline void handleMessage(Message &msg, uint32_t &addr, uint16_t &finishEraseAddress,
|
||||
ChipEraseState &chipEraseFlag)
|
||||
{
|
||||
if (isSignOn(msg))
|
||||
formatSignOnAnswer(msg);
|
||||
@ -524,11 +553,13 @@ static inline void handleMessage(Message &msg, uint32_t &addr, ChipEraseState &c
|
||||
else if (isReadEepromIsp(msg))
|
||||
formatReadEepromIspAnswer(msg, addr);
|
||||
else if (isChipEraseIsp(msg)) {
|
||||
chipEraseFlag = ChipEraseState::REQUEST;
|
||||
chipEraseFlag |= ChipEraseState::REQUEST;
|
||||
formatChipEraseIspAnswer(msg);
|
||||
} else if (isProgramFlashIsp(msg))
|
||||
} else if (isProgramFlashIsp(msg)) {
|
||||
chipEraseFlag |= ChipEraseState::PROGRAM;
|
||||
formatProgramFlashIspAnswer(msg, addr);
|
||||
else if (isProgramEepromIsp(msg))
|
||||
finishEraseAddress = addr;
|
||||
} else if (isProgramEepromIsp(msg))
|
||||
formatProgramEepromIspAnswer(msg, addr);
|
||||
else if (isLeaveProgmodeIsp(msg)) {
|
||||
chipEraseFlag |= ChipEraseState::RESPONSE;
|
||||
@ -537,11 +568,6 @@ static inline void handleMessage(Message &msg, uint32_t &addr, ChipEraseState &c
|
||||
formatErrorAnswer(msg);
|
||||
|
||||
transmitMessage(msg);
|
||||
|
||||
if (chipEraseFlag == ChipEraseState::PERFORM) {
|
||||
performChipErase();
|
||||
chipEraseFlag = ChipEraseState::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -550,11 +576,25 @@ int main()
|
||||
|
||||
Message msg;
|
||||
uint32_t addr = 0x0000;
|
||||
uint16_t finishEraseAddress = 0x0000;
|
||||
ChipEraseState chipEraseFlag = ChipEraseState::NONE;
|
||||
uint16_t timeout = TIMEOUT;
|
||||
|
||||
while (true) {
|
||||
if (receiveMessage(msg)) {
|
||||
handleMessage(msg, addr, chipEraseFlag);
|
||||
if (receiveMessage(msg, timeout)) {
|
||||
handleMessage(msg, addr, finishEraseAddress, chipEraseFlag);
|
||||
}
|
||||
|
||||
if (timeout == 0) {
|
||||
timeout = TIMEOUT;
|
||||
|
||||
if (chipEraseFlag == ChipEraseState::PERFORM) {
|
||||
performChipErase();
|
||||
chipEraseFlag = ChipEraseState::NONE;
|
||||
} else if (chipEraseFlag == ChipEraseState::FINISH) {
|
||||
performChipErase(finishEraseAddress);
|
||||
chipEraseFlag = ChipEraseState::NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user