9 Commits

15 changed files with 995 additions and 244 deletions

3
.gitmodules vendored
View File

@@ -22,3 +22,6 @@
[submodule "stk500v2/flash"] [submodule "stk500v2/flash"]
path = stk500v2/flash path = stk500v2/flash
url = git@git.blackmark.me:avr/flash.git url = git@git.blackmark.me:avr/flash.git
[submodule "blink/io"]
path = blink/io
url = git@git.blackmark.me:avr/io.git

239
blink/blink.cppproj Normal file
View File

@@ -0,0 +1,239 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>{d887fc8e-ee68-4248-8382-92dbc9a54145}</ProjectGuid>
<avrdevice>ATmega328P</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>blink</AssemblyName>
<Name>blink</Name>
<RootNamespace>blink</RootNamespace>
<ToolchainFlavour>avr-g++-9.1.0</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<avrtool>com.atmel.avrdbg.tool.atmelice</avrtool>
<avrtoolserialnumber>J41800099437</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x1E950F</avrdeviceexpectedsignature>
<com_atmel_avrdbg_tool_stk500>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.stk500</ToolType>
<ToolNumber>
</ToolNumber>
<ToolName>STK500</ToolName>
</com_atmel_avrdbg_tool_stk500>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
<AsfFrameworkConfig>
<framework-data xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<com_atmel_avrdbg_tool_atmelice>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
<ToolNumber>J41800099437</ToolNumber>
<ToolName>Atmel-ICE</ToolName>
</com_atmel_avrdbg_tool_atmelice>
<custom>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType>custom</ToolType>
<ToolNumber>
</ToolNumber>
<ToolName>Custom Programming Tool</ToolName>
</custom>
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
<AAFDebugger>
<AAFDebugFiles>
</AAFDebugFiles>
</AAFDebugger>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -std=c11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -std=c11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="bootloader.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="bootloader.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="clock.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="io\io.hpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="main.cpp">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="io" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

46
blink/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>(0x7800 / 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) != 0xFF)
return true;
return false;
}
void Bootloader::call()
{
if (check())
bootloader();
else
boot();
}

24
blink/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();
};

5
blink/clock.hpp Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
//#define F_CPU 18'432'000
#define F_CPU 16'000'000
#include <util/delay.h>

1
blink/io Submodule

Submodule blink/io added at 80de36ee7e

30
blink/main.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "clock.hpp"
#include "io/io.hpp"
#include "bootloader.hpp"
int main()
{
io::Pin<io::P::B5> ledPin;
ledPin.dir(io::Dir::OUT);
ledPin = false;
Bootloader::init([&ledPin]() {
for (uint8_t i = 0; i < 10; ++i) {
ledPin = true;
_delay_ms(50);
ledPin = false;
_delay_ms(50);
}
});
for (uint8_t i = 0; i < 10; ++i) {
ledPin.toggle();
_delay_ms(1000);
}
Bootloader::enter();
return 0;
}

View File

@@ -7,6 +7,8 @@ Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "tsb", "tsb\tsb.cppproj", "{
EndProject EndProject
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "stk500v2", "stk500v2\stk500v2.cppproj", "{19798CCE-5D96-40E9-B769-D209715DCE0C}" Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "stk500v2", "stk500v2\stk500v2.cppproj", "{19798CCE-5D96-40E9-B769-D209715DCE0C}"
EndProject EndProject
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "blink", "blink\blink.cppproj", "{D887FC8E-EE68-4248-8382-92DBC9A54145}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AVR = Debug|AVR Debug|AVR = Debug|AVR
@@ -21,6 +23,10 @@ Global
{19798CCE-5D96-40E9-B769-D209715DCE0C}.Debug|AVR.Build.0 = Debug|AVR {19798CCE-5D96-40E9-B769-D209715DCE0C}.Debug|AVR.Build.0 = Debug|AVR
{19798CCE-5D96-40E9-B769-D209715DCE0C}.Release|AVR.ActiveCfg = Release|AVR {19798CCE-5D96-40E9-B769-D209715DCE0C}.Release|AVR.ActiveCfg = Release|AVR
{19798CCE-5D96-40E9-B769-D209715DCE0C}.Release|AVR.Build.0 = Release|AVR {19798CCE-5D96-40E9-B769-D209715DCE0C}.Release|AVR.Build.0 = Release|AVR
{D887FC8E-EE68-4248-8382-92DBC9A54145}.Debug|AVR.ActiveCfg = Debug|AVR
{D887FC8E-EE68-4248-8382-92DBC9A54145}.Debug|AVR.Build.0 = Debug|AVR
{D887FC8E-EE68-4248-8382-92DBC9A54145}.Release|AVR.ActiveCfg = Release|AVR
{D887FC8E-EE68-4248-8382-92DBC9A54145}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#define F_CPU 18'432'000 //#define F_CPU 18'432'000
#define F_CPU 16'000'000
#include <util/delay.h> #include <util/delay.h>

View File

@@ -1,5 +1,7 @@
#include "clock.hpp" #include "clock.hpp"
#include "stk500v2.hpp"
#include "uart/uart.hpp" #include "uart/uart.hpp"
#include <math.h> #include <math.h>
@@ -570,8 +572,62 @@ static inline void handleMessage(Message &msg, uint32_t &addr, uint16_t &finishE
transmitMessage(msg); transmitMessage(msg);
} }
static inline void interfaceTest()
{
constexpr auto onSignOn = []() {};
constexpr auto onSetParam = []() {};
constexpr auto onGetParam = [](stk500v2::Param param, uint8_t &result) {
using stk500v2::Param;
switch (param) {
case Param::HW_VER:
result = 1;
break;
case Param::SW_MAJOR:
result = 2;
break;
case Param::SW_MINOR:
result = 10;
break;
case Param::SCK_DURATION:
result = 2;
break;
case Param::VADJUST:
result = 25;
break;
case Param::VTARGET:
result = 49;
break;
case Param::OSC_PSCALE:
result = 2;
break;
case Param::OSC_CMATCH:
result = 127;
break;
case Param::TOPCARD_DETECT:
result = 0xFF;
break;
default:
return false;
}
return true;
};
constexpr auto callbacks = stk500v2::Callbacks<onSignOn, onSetParam, onGetParam>();
stk500v2::Stk500v2<uart_interface, TIMEOUT, callbacks> stk500;
stk500.init();
while (stk500.callback())
;
}
int main() int main()
{ {
/*interfaceTest();
return 0;*/
serial.init(); serial.init();
Message msg; Message msg;
@@ -605,7 +661,7 @@ void startup() __attribute__((naked, section(".vectors")));
void startup() void startup()
{ {
asm volatile("clr __zero_reg__"); asm volatile("clr __zero_reg__");
// SP = RAMEND; SP = RAMEND;
SREG = 0; SREG = 0;
asm volatile("jmp main"); asm volatile("jmp main");
} }

View File

@@ -15,7 +15,7 @@
<AssemblyName>stk500v2</AssemblyName> <AssemblyName>stk500v2</AssemblyName>
<Name>stk500v2</Name> <Name>stk500v2</Name>
<RootNamespace>stk500v2</RootNamespace> <RootNamespace>stk500v2</RootNamespace>
<ToolchainFlavour>avr-g++-9.1.0</ToolchainFlavour> <ToolchainFlavour>avr-g++-10.0.1</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning> <KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor> <OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash> <CacheFlash>true</CacheFlash>
@@ -95,17 +95,6 @@
</com_atmel_avrdbg_tool_simulator> </com_atmel_avrdbg_tool_simulator>
<AAFDebugger> <AAFDebugger>
<AAFDebugFiles> <AAFDebugFiles>
<DebugFile>
<path>\Debug\stk500v2.lss</path>
<AAFSetting>
<Label>Lss Files</Label>
<Extention>.lss</Extention>
<Regex>^\s*(?&lt;address&gt;[a-f0-9]*):\s*.*$</Regex>
<DebugEnabled>true</DebugEnabled>
<RegexGroups>address</RegexGroups>
<DebuggerExpression>$pc</DebuggerExpression>
</AAFSetting>
</DebugFile>
</AAFDebugFiles> </AAFDebugFiles>
</AAFDebugger> </AAFDebugger>
</PropertyGroup> </PropertyGroup>
@@ -152,7 +141,7 @@
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum> <avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings> <avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic> <avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags> <avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++20</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.general.NoStartupOrDefaultLibs>True</avrgcccpp.linker.general.NoStartupOrDefaultLibs> <avrgcccpp.linker.general.NoStartupOrDefaultLibs>True</avrgcccpp.linker.general.NoStartupOrDefaultLibs>
<avrgcccpp.linker.libraries.Libraries> <avrgcccpp.linker.libraries.Libraries>
<ListValues> <ListValues>
@@ -169,7 +158,7 @@
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value> <Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues> </ListValues>
</avrgcccpp.assembler.general.IncludePaths> </avrgcccpp.assembler.general.IncludePaths>
</AvrGccCpp> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@@ -217,7 +206,7 @@
<avrgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcccpp.compiler.optimization.DebugLevel> <avrgcccpp.compiler.optimization.DebugLevel>Maximum (-g3)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings> <avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic> <avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++17</avrgcccpp.compiler.miscellaneous.OtherFlags> <avrgcccpp.compiler.miscellaneous.OtherFlags>-fno-threadsafe-statics -Wextra -std=c++20</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.general.NoStartupOrDefaultLibs>True</avrgcccpp.linker.general.NoStartupOrDefaultLibs> <avrgcccpp.linker.general.NoStartupOrDefaultLibs>True</avrgcccpp.linker.general.NoStartupOrDefaultLibs>
<avrgcccpp.linker.libraries.Libraries> <avrgcccpp.linker.libraries.Libraries>
<ListValues> <ListValues>
@@ -235,7 +224,7 @@
</ListValues> </ListValues>
</avrgcccpp.assembler.general.IncludePaths> </avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel> <avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

344
stk500v2/stk500v2.hpp Normal file
View File

@@ -0,0 +1,344 @@
#pragma once
#include <math.h>
#include <stddef.h>
#include <stdint.h>
namespace stk500v2 {
enum class Msg : uint8_t {
START = 0x1B, // ASCII ESC
TOKEN = 0x0E,
};
inline constexpr bool operator==(const Msg &msg, const uint8_t &num)
{
return static_cast<uint8_t>(msg) == num;
}
enum class Cmd : uint8_t {
SIGN_ON = 0x01,
SET_PARAMETER = 0x02,
GET_PARAMETER = 0x03,
SET_DEVICE_PARAMETERS = 0x04,
OSCCAL = 0x05,
LOAD_ADDRESS = 0x06,
FIRMWARE_UPGRADE = 0x07,
};
inline constexpr bool operator==(const Cmd &cmd, const uint8_t &num)
{
return static_cast<uint8_t>(cmd) == num;
}
enum class IspCmd : uint8_t {
ENTER_PROGMODE = 0x10,
LEAVE_PROGMODE = 0x11,
CHIP_ERASE = 0x12,
PROGRAM_FLASH = 0x13,
READ_FLASH = 0x14,
PROGRAM_EEPROM = 0x15,
READ_EEPROM = 0x16,
PROGRAM_FUSE = 0x17,
READ_FUSE = 0x18,
PROGRAM_LOCK = 0x19,
READ_LOCK = 0x1A,
READ_SIGNATURE = 0x1B,
READ_OSCCAL = 0x1C,
SPI_MULTI = 0x1D,
};
enum class PpCmd : uint8_t {
ENTER_PROGMODE = 0x20,
LEAVE_PROGMODE = 0x21,
CHIP_ERASE = 0x22,
PROGRAM_FLASH = 0x23,
READ_FLASH = 0x24,
PROGRAM_EEPROM = 0x25,
READ_EEPROM = 0x26,
PROGRAM_FUSE = 0x27,
READ_FUSE = 0x28,
PROGRAM_LOCK = 0x29,
READ_LOCK = 0x2A,
READ_SIGNATURE = 0x2B,
READ_OSCCAL = 0x2C,
SET_CONTROL_STACK = 0x2D,
};
enum class HvspCmd : uint8_t {
ENTER_PROGMODE = 0x30,
LEAVE_PROGMODE = 0x31,
CHIP_ERASE = 0x32,
PROGRAM_FLASH = 0x33,
READ_FLASH = 0x34,
PROGRAM_EEPROM = 0x35,
READ_EEPROM = 0x36,
PROGRAM_FUSE = 0x37,
READ_FUSE = 0x38,
PROGRAM_LOCK = 0x39,
READ_LOCK = 0x3A,
READ_SIGNATURE = 0x3B,
READ_OSCCAL = 0x3C,
};
enum class Status : uint8_t {
// Success
CMD_OK = 0x00,
// Warnings
CMD_TOUT = 0x80,
RDY_BSY_TOUT = 0x81,
SET_PARAM_MISSING = 0x82,
// Errors
CMD_FAILED = 0xC0,
CKSUM_ERROR = 0xC1,
CMD_UNKNOWN = 0xC9,
};
enum class Param : uint8_t {
BUILD_NUMBER_LOW = 0x80,
BUILD_NUMBER_HIGH = 0x81,
HW_VER = 0x90,
SW_MAJOR = 0x91,
SW_MINOR = 0x92,
VTARGET = 0x94,
VADJUST = 0x95,
OSC_PSCALE = 0x96,
OSC_CMATCH = 0x97,
SCK_DURATION = 0x98,
TOPCARD_DETECT = 0x9A,
STATUS = 0x9C,
DATA = 0x9D,
RESET_POLARITY = 0x9E,
CONTROLLER_INIT = 0x9F,
};
enum class Answer : uint8_t {
CKSUM_ERROR = 0xB0,
};
template <size_t Size>
struct Message {
uint8_t start;
uint8_t number;
uint16_t size;
uint8_t token;
uint8_t body[Size];
uint8_t checksum;
};
template <auto SignOnFn, auto SetParamFn, auto GetParamFn>
struct Callbacks {
static constexpr auto onSignOn = SignOnFn;
static constexpr auto onSetParam = SetParamFn;
static constexpr auto onGetParam = GetParamFn;
};
template <class Uart, uint16_t Timeout, auto CallbackFns>
class Stk500v2 {
public:
inline void init()
{
m_serial.init();
}
inline bool callback()
{
if (receiveMessage()) {
handleMessage();
}
if (m_timeout)
return true;
return false;
}
private:
static constexpr auto MSG_BUFFER_SIZE = 275;
using msg_t = Message<MSG_BUFFER_SIZE>;
msg_t m_msg;
Uart m_serial;
uint16_t m_timeout = Timeout;
inline bool receiveByte(uint8_t &data)
{
constexpr auto MICROSECOND = 1000.0 * 1000;
constexpr auto SYMBOL_SIZE = 9;
constexpr auto BYTE_DELAY_US = (SYMBOL_SIZE * MICROSECOND) / Uart::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 (m_timeout) {
if (m_serial.rxByte(data)) {
m_timeout = Timeout;
return true;
}
_delay_us(BYTE_DELAY_US);
if (--msDelay == 0) {
msDelay = NUM_MS_DELAY_STEPS;
--m_timeout;
}
}
return false;
}
inline uint8_t calcChecksum() const
{
uint8_t checksum = static_cast<uint8_t>(m_msg.start);
for (uint16_t i = 1; i < 5 + m_msg.size; ++i) {
checksum ^= *(reinterpret_cast<const uint8_t *>(&m_msg) + i);
}
return checksum;
}
inline bool receiveMessage()
{
constexpr auto CHECK_MESSAGE_FORMAT = true;
constexpr auto CHECK_MESSAGE_SIZE = true;
constexpr auto CHECK_MESSAGE_CHECKSUM = true;
if (!receiveByte(m_msg.start)) {
return false;
}
if constexpr (CHECK_MESSAGE_FORMAT) {
if (m_msg.start != Msg::START)
return false;
}
if (!receiveByte(m_msg.number))
return false;
if (!receiveByte(*(reinterpret_cast<uint8_t *>(&m_msg.size) + 1)))
return false;
if (!receiveByte(*reinterpret_cast<uint8_t *>(&m_msg.size)))
return false;
if constexpr (CHECK_MESSAGE_SIZE) {
if (m_msg.size > sizeof(m_msg.body))
return false;
}
if (!receiveByte(m_msg.token))
return false;
if constexpr (CHECK_MESSAGE_FORMAT) {
if (m_msg.token != Msg::TOKEN)
return false;
}
for (uint16_t i = 0; i < m_msg.size; ++i) {
if (!receiveByte(m_msg.body[i]))
return false;
}
if (!receiveByte(m_msg.checksum))
return false;
if constexpr (CHECK_MESSAGE_CHECKSUM) {
if (m_msg.checksum != calcChecksum())
return false;
}
return true;
}
inline void transmitMessage() const
{
m_serial.txByte(m_msg.start);
m_serial.txByte(m_msg.number);
m_serial.txByte(m_msg.size >> 8);
m_serial.txByte(m_msg.size & 0xFF);
m_serial.txByte(m_msg.token);
for (uint16_t i = 0; i < m_msg.size; ++i)
m_serial.txByte(m_msg.body[i]);
m_serial.txByte(m_msg.checksum);
}
inline void handleMessage()
{
constexpr auto CHECK_MESSAGE_LENGTH = true;
switch (m_msg.body[0]) {
case static_cast<uint8_t>(Cmd::SIGN_ON): {
if constexpr (CHECK_MESSAGE_LENGTH) {
if (m_msg.size != 1)
break;
}
CallbackFns.onSignOn();
sendReply<static_cast<uint8_t>(Cmd::SIGN_ON)>();
break;
}
case static_cast<uint8_t>(Cmd::SET_PARAMETER): {
if constexpr (CHECK_MESSAGE_LENGTH) {
if (m_msg.size != 3)
break;
}
CallbackFns.onSetParam();
sendReply<static_cast<uint8_t>(Cmd::SET_PARAMETER)>();
break;
}
case static_cast<uint8_t>(Cmd::GET_PARAMETER): {
if constexpr (CHECK_MESSAGE_LENGTH) {
if (m_msg.size != 2)
break;
}
const auto errorOccurred = CallbackFns.onGetParam(static_cast<Param>(m_msg.body[1]), m_msg.body[2]);
sendReply<static_cast<uint8_t>(Cmd::GET_PARAMETER)>(errorOccurred);
break;
}
case static_cast<uint8_t>(Cmd::SET_DEVICE_PARAMETERS):
break;
case static_cast<uint8_t>(Cmd::OSCCAL):
break;
case static_cast<uint8_t>(Cmd::LOAD_ADDRESS):
break;
case static_cast<uint8_t>(Cmd::FIRMWARE_UPGRADE):
break;
}
}
template <uint8_t Command>
inline void sendReply(bool errorOccurred = false)
{
if constexpr (Command == Cmd::SIGN_ON) {
m_msg.size = 3 + 8;
m_msg.body[1] = static_cast<uint8_t>(Status::CMD_OK);
m_msg.body[2] = 8;
m_msg.body[3] = 'S';
m_msg.body[4] = 'T';
m_msg.body[5] = 'K';
m_msg.body[6] = '5';
m_msg.body[7] = '0';
m_msg.body[8] = '0';
m_msg.body[9] = '_';
m_msg.body[10] = '2';
} else if (Command == Cmd::SET_PARAMETER) {
m_msg.size = 2;
m_msg.body[1] = static_cast<uint8_t>(Status::CMD_OK);
} else if (Command == Cmd::GET_PARAMETER) {
if (!errorOccurred) {
m_msg.size = 3;
m_msg.body[1] = static_cast<uint8_t>(Status::CMD_OK);
} else {
m_msg.size = 2;
m_msg.body[1] = static_cast<uint8_t>(Status::CMD_FAILED);
}
}
m_msg.checksum = calcChecksum();
transmitMessage();
}
};
} // namespace stk500v2

View File

@@ -28,9 +28,10 @@
<ResetRule>0</ResetRule> <ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule> <eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey /> <EraseKey />
<avrtool>com.atmel.avrdbg.tool.atmelice</avrtool> <avrtool>
</avrtool>
<avrtoolserialnumber>J41800099437</avrtoolserialnumber> <avrtoolserialnumber>J41800099437</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x1E950F</avrdeviceexpectedsignature> <avrdeviceexpectedsignature>0x1E9705</avrdeviceexpectedsignature>
<com_atmel_avrdbg_tool_stk500> <com_atmel_avrdbg_tool_stk500>
<ToolOptions> <ToolOptions>
<InterfaceProperties> <InterfaceProperties>
@@ -93,11 +94,16 @@
</ToolNumber> </ToolNumber>
<ToolName xmlns="">Simulator</ToolName> <ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator> </com_atmel_avrdbg_tool_simulator>
<AAFDebugger>
<AAFDebugFiles>
</AAFDebugFiles>
</AAFDebugger>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGccCpp> <AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device> <avrgcc.common.Device>-mmcu=atmega1284p</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
@@ -148,13 +154,14 @@
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value> <Value>%24(PackRepoDir)\Atmel\ATmega_DFP\1.4.346\include</Value>
</ListValues> </ListValues>
</avrgcccpp.assembler.general.IncludePaths> </avrgcccpp.assembler.general.IncludePaths>
</AvrGccCpp> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGccCpp> <AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p</avrgcc.common.Device> <avrgcc.common.Device>-mmcu=atmega1284p</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
@@ -208,7 +215,7 @@
</ListValues> </ListValues>
</avrgcccpp.assembler.general.IncludePaths> </avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel> <avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>