Add tsb bootloader support

This commit is contained in:
BlackMark 2020-04-01 19:04:27 +02:00
parent 04bcb76382
commit 07be559e94
5 changed files with 102 additions and 4 deletions

46
fantemp/bootloader.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "bootloader.hpp"
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
namespace {
typedef void (*jmp_fn)() __attribute__((noreturn));
jmp_fn boot = reinterpret_cast<jmp_fn>(0x0000);
jmp_fn bootloader = reinterpret_cast<jmp_fn>(0x7E00 / 2);
} // namespace
bool Bootloader::handleReset()
{
wdt_reset();
uint8_t mcuStatus = MCUSR;
MCUSR &= ~(1 << WDRF);
wdt_disable();
return (mcuStatus & (1 << WDRF));
}
void Bootloader::reset()
{
wdt_enable(WDTO_15MS);
while (true)
;
}
bool Bootloader::check()
{
if (pgm_read_byte(reinterpret_cast<uint16_t>(bootloader) * 2) == 0xF8)
return true;
return false;
}
void Bootloader::call()
{
if (check())
bootloader();
else
boot();
}

24
fantemp/bootloader.hpp Normal file
View File

@ -0,0 +1,24 @@
#pragma once
class Bootloader {
public:
template <typename Fn>
static inline void init(Fn callback)
{
if (handleReset()) {
callback();
call();
}
}
static inline void enter()
{
reset();
}
private:
static bool handleReset();
static void reset();
static bool check();
static void call();
};

View File

@ -200,6 +200,12 @@
<Compile Include="adc\hardware.hpp"> <Compile Include="adc\hardware.hpp">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="bootloader.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="bootloader.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="clock.hpp"> <Compile Include="clock.hpp">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>

View File

@ -5,11 +5,14 @@
#define UART0_INT_VECTORS #define UART0_INT_VECTORS
#include "uart/hardware0.hpp" #include "uart/hardware0.hpp"
#include "bootloader.hpp"
#include "controller.hpp" #include "controller.hpp"
#include "terminal.hpp" #include "terminal.hpp"
int main() int main()
{ {
Bootloader::init([]() {});
using serial = uart::Uart0<uart::Config<115200>>; using serial = uart::Uart0<uart::Config<115200>>;
Terminal<serial> terminal; Terminal<serial> terminal;
terminal.init(); terminal.init();

View File

@ -15,6 +15,7 @@ GF(HELP_CMD, "help");
GF(SHOW_CMD, "show"); GF(SHOW_CMD, "show");
GF(CURVE_CMD, "curve"); GF(CURVE_CMD, "curve");
GF(MONITOR_CMD, "monitor"); GF(MONITOR_CMD, "monitor");
GF(BOOTLOADER_CMD, "bootloader");
constexpr auto BACKSPACE = uint8_t{0x7f}; constexpr auto BACKSPACE = uint8_t{0x7f};
constexpr auto CTRL_C = uint8_t{0x03}; constexpr auto CTRL_C = uint8_t{0x03};
@ -109,6 +110,8 @@ class Terminal {
printCurve(); printCurve();
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(MONITOR_CMD), m_inputSize) == 0) { } else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(MONITOR_CMD), m_inputSize) == 0) {
m_state = State::MONITOR; m_state = State::MONITOR;
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(BOOTLOADER_CMD), m_inputSize) == 0) {
handleBootloader();
} else { } else {
printUnknown(); printUnknown();
} }
@ -124,10 +127,11 @@ class Terminal {
static void printHelp() static void printHelp()
{ {
m_serial << F("FanTemp command overview: ") << ENDL; m_serial << F("FanTemp command overview: ") << ENDL;
m_serial << HELP_CMD << F(" ....: print this help message") << ENDL; m_serial << HELP_CMD << F(" .......: print this help message") << ENDL;
m_serial << SHOW_CMD << F(" ....: shows current temperature and fan speed") << ENDL; m_serial << SHOW_CMD << F(" .......: shows current temperature and fan speed") << ENDL;
m_serial << CURVE_CMD << F(" ...: shows the curve used to map temperature to fan speed") << ENDL; m_serial << CURVE_CMD << F(" ......: shows the curve used to map temperature to fan speed") << ENDL;
m_serial << MONITOR_CMD << F(" .: loops the show command until Ctrl + C is pressed") << ENDL; m_serial << MONITOR_CMD << F(" ....: loops the show command until Ctrl + C is pressed") << ENDL;
m_serial << BOOTLOADER_CMD << F(" .: enters the bootloader after 10 seconds") << ENDL;
} }
static void showState() static void showState()
@ -156,6 +160,21 @@ class Terminal {
} }
} }
static void handleBootloader()
{
for (int8_t i = 10; i >= 0; --i) {
m_serial << i << ENDL;
_delay_ms(1000);
}
m_serial << F("Entering bootloader...") << ENDL;
m_serial.flushTx();
_delay_ms(1000);
Bootloader::enter();
}
static void printUnknown() static void printUnknown()
{ {
m_serial << F("Unknown command \""); m_serial << F("Unknown command \"");