Compare commits

..

No commits in common. "5f8d6a6f85e01c060eb636492170747d92f0d181" and "6f9d8bae423ac4c37d7c4fab7badb71626c55f6d" have entirely different histories.

View File

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