Compare commits
5 Commits
6f9d8bae42
...
5f8d6a6f85
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f8d6a6f85 | |||
| 41f81247ce | |||
| a72bf67b07 | |||
| 3a04b1f488 | |||
| 8979066420 |
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#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>
|
||||||
@ -9,7 +11,10 @@
|
|||||||
|
|
||||||
#include "command.hpp"
|
#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;
|
uart::Uart<uart_interface> serial;
|
||||||
|
|
||||||
struct Message {
|
struct Message {
|
||||||
@ -21,11 +26,26 @@ struct Message {
|
|||||||
uint8_t checksum;
|
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) {
|
constexpr auto MICROSECOND = 1000.0 * 1000;
|
||||||
if (serial.rxByte(data))
|
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;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_delay_us(BYTE_DELAY_US);
|
||||||
|
|
||||||
|
if (--msDelay == 0) {
|
||||||
|
msDelay = NUM_MS_DELAY_STEPS;
|
||||||
|
--timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -42,23 +62,23 @@ static inline uint8_t calcChecksum(const Message &msg)
|
|||||||
return checksum;
|
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;
|
return false;
|
||||||
if (!receiveByte(msg.number))
|
if (!receiveByte(msg.number, timeout))
|
||||||
return false;
|
return false;
|
||||||
if (!receiveByte(*(reinterpret_cast<uint8_t *>(&msg.size) + 1)))
|
if (!receiveByte(*(reinterpret_cast<uint8_t *>(&msg.size) + 1), timeout))
|
||||||
return false;
|
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;
|
return false;
|
||||||
if (!receiveByte(msg.token) || msg.token != TOKEN)
|
if (!receiveByte(msg.token, timeout) || 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]))
|
if (!receiveByte(msg.body[i], timeout))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!receiveByte(msg.checksum) || msg.checksum != calcChecksum(msg))
|
if (!receiveByte(msg.checksum, timeout) || msg.checksum != calcChecksum(msg))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -216,6 +236,8 @@ 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;
|
||||||
}
|
}
|
||||||
@ -299,13 +321,15 @@ 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>(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.body[numBytes + 2] = STATUS_CMD_OK;
|
||||||
|
|
||||||
msg.checksum = calcChecksum(msg);
|
msg.checksum = calcChecksum(msg);
|
||||||
@ -381,17 +405,17 @@ static inline uint32_t getFlashSize()
|
|||||||
return (FLASHEND - bootloaderSize + 1);
|
return (FLASHEND - bootloaderSize + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void performChipErase()
|
static inline void performChipErase(uint16_t flashStartAddress = 0x0000)
|
||||||
{
|
{
|
||||||
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 = []() {
|
constexpr auto eraseFlash = [](const uint16_t &flashStartAddress) {
|
||||||
const auto flashSize = getFlashSize();
|
const auto flashSize = getFlashSize();
|
||||||
|
const auto byteAddress = 2 * flashStartAddress;
|
||||||
for (uint16_t i = 0; i < flashSize; i += SPM_PAGESIZE) {
|
for (uint16_t i = byteAddress; i < flashSize; i += SPM_PAGESIZE) {
|
||||||
boot_page_erase(i);
|
boot_page_erase(i);
|
||||||
boot_spm_busy_wait();
|
boot_spm_busy_wait();
|
||||||
}
|
}
|
||||||
@ -409,7 +433,7 @@ static inline void performChipErase()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
eraseFlash();
|
eraseFlash(flashStartAddress);
|
||||||
eraseEeprom();
|
eraseEeprom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,10 +461,12 @@ 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)
|
||||||
{
|
{
|
||||||
if (addr < getFlashSize())
|
const auto byteAddress = 2 * addr;
|
||||||
writeFlashPage(addr, msg.body + 10);
|
if (byteAddress < getFlashSize())
|
||||||
|
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];
|
||||||
addr += numBytes;
|
const auto numWords = numBytes / 2;
|
||||||
|
addr += numWords;
|
||||||
|
|
||||||
msg.size = 2;
|
msg.size = 2;
|
||||||
msg.body[1] = STATUS_CMD_OK;
|
msg.body[1] = STATUS_CMD_OK;
|
||||||
@ -480,10 +506,12 @@ static inline void formatErrorAnswer(Message &msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class ChipEraseState {
|
enum class ChipEraseState {
|
||||||
NONE = 0b00,
|
NONE = 0,
|
||||||
REQUEST = 0b01,
|
REQUEST = (1 << 1),
|
||||||
RESPONSE = 0b10,
|
RESPONSE = (1 << 2),
|
||||||
PERFORM = 0b11,
|
PERFORM = REQUEST | RESPONSE,
|
||||||
|
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)
|
||||||
@ -497,7 +525,8 @@ constexpr ChipEraseState &operator|=(ChipEraseState &self, const ChipEraseState
|
|||||||
return self;
|
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))
|
if (isSignOn(msg))
|
||||||
formatSignOnAnswer(msg);
|
formatSignOnAnswer(msg);
|
||||||
@ -524,11 +553,13 @@ static inline void handleMessage(Message &msg, uint32_t &addr, ChipEraseState &c
|
|||||||
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);
|
||||||
else if (isProgramEepromIsp(msg))
|
finishEraseAddress = addr;
|
||||||
|
} else if (isProgramEepromIsp(msg))
|
||||||
formatProgramEepromIspAnswer(msg, addr);
|
formatProgramEepromIspAnswer(msg, addr);
|
||||||
else if (isLeaveProgmodeIsp(msg)) {
|
else if (isLeaveProgmodeIsp(msg)) {
|
||||||
chipEraseFlag |= ChipEraseState::RESPONSE;
|
chipEraseFlag |= ChipEraseState::RESPONSE;
|
||||||
@ -537,11 +568,6 @@ static inline void handleMessage(Message &msg, uint32_t &addr, ChipEraseState &c
|
|||||||
formatErrorAnswer(msg);
|
formatErrorAnswer(msg);
|
||||||
|
|
||||||
transmitMessage(msg);
|
transmitMessage(msg);
|
||||||
|
|
||||||
if (chipEraseFlag == ChipEraseState::PERFORM) {
|
|
||||||
performChipErase();
|
|
||||||
chipEraseFlag = ChipEraseState::NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@ -550,11 +576,25 @@ 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)) {
|
if (receiveMessage(msg, timeout)) {
|
||||||
handleMessage(msg, addr, chipEraseFlag);
|
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