-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReset_SAMD21.cpp
102 lines (81 loc) · 2.32 KB
/
Reset_SAMD21.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//
// (c)2019 by Lucky Resistor. See LICENSE for details.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#include "Reset_SAMD21.hpp"
#include "hal-core/Chip.hpp"
#include "hal-core/Segments.h"
namespace lr::Reset {
/// The delay counter for an program erase.
///
volatile uint32_t gEraseDelay = -1; // -1 = disabled.
/// The start of the application.
///
const auto cAppStart = (volatile uint32_t)(&__text_start__) + 4;
/// The start of the NVM.
///
const auto cNvmMemory = ((volatile uint16_t*)0x00000000);
/// Check if the NVM controller is ready.
///
inline bool nvmReady() {
return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY;
}
/// Erase the current application if a boot loader is present.
///
__attribute__((section(".ramfunc"), noreturn))
void erase() {
__disable_irq();
// Only erase the application, if a boot loader is present.
if (cAppStart >= 0x204) {
while (!nvmReady()) {}
// Erase the first block of the application.
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK;
NVMCTRL->ADDR.reg = (uintptr_t)&cNvmMemory[cAppStart/4];
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER|NVMCTRL_CTRLA_CMDEX_KEY;
while (!nvmReady()) {}
}
// Reset the board.
NVIC_SystemReset();
while (true) {};
}
void reset()
{
// Reset the board.
NVIC_SystemReset();
while (true) {};
}
void eraseDelayed(Milliseconds delay)
{
__disable_irq();
gEraseDelay = delay.ticks();
__enable_irq();
}
void cancelErase()
{
__disable_irq();
gEraseDelay = -1;
__enable_irq();
}
void eraseTick()
{
if (gEraseDelay < 0) {
return;
}
if (--gEraseDelay == 0) {
erase();
}
}
}