-
Notifications
You must be signed in to change notification settings - Fork 1
/
Nvm.cpp
124 lines (111 loc) · 3.52 KB
/
Nvm.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "Nvm.hpp"
#include "Dma.hpp"
#include "Irq.hpp"
#include "Sys.hpp"
enum : uint32_t {
NVMCON = 0xBF80F400, //WR locked
WR = 15,
WREN = 14,
WRERR = 13,
LVDERR = 12,
LVDSTAT = 11,
NVMOP_SHIFT = 0, NVMOP_CLR = 15,
NOP = 0,
PGMWORD = 1,
PGMROW = 3,
ERASEPAGE = 4,
//PGMERASE = 5
NVMKEY = 0xBF80F410,
MAGIC1 = 0xAA996655,
MAGIC2 = 0x556699AA,
NVMADDR = 0xBF80F420, //physical address
NVMDATA = 0xBF80F430,
NVMSRCADDR = 0xBF80F440, //physical address
};
//-----------------------------------------------------------------private-----
static auto
unlock () -> void
{
//use Sys:: function to prevent irq/dma interruption of these
//two writes (although a sys unlock not needed)
uint8_t idstat = Sys::unlock_wait();
Reg::val(NVMKEY, MAGIC1);
Reg::val(NVMKEY, MAGIC2);
Sys::lock(idstat);
}
//-----------------------------------------------------------------private-----
static auto
lock () -> void
{
Reg::val(NVMKEY, 0);
}
//-----------------------------------------------------------------private-----
static auto
do_wr () -> void
{
unlock();
Reg::setbit(NVMCON, 1<<WR);
lock();
while(Reg::anybit(NVMCON, 1<<WR));
}
//-----------------------------------------------------------------private-----
static auto
do_op (uint8_t v) -> void
{
Reg::clrbit(NVMCON, NVMOP_CLR bitor (1<<WREN));
Reg::setbit(NVMCON, v bitor (1<<WREN));
do_wr();
Reg::clrbit(NVMCON, NVMOP_CLR bitor (1<<WREN));
}
//-----------------------------------------------------------------private-----
static auto
address (uint32_t v) -> void
{
//0 based values to kseg0
v or_eq Nvm::BASEFLASH;
//kseg0 values to physical
Reg::val(NVMADDR, Reg::k2phys(v));
}
//-----------------------------------------------------------------private-----
static auto
error () -> uint8_t
{
uint8_t err = (Reg::val16(NVMCON)>>12) bitand 3;
if(err) do_op(NOP);
return err;
}
//=============================================================================
auto Nvm::
mem_size () -> uint32_t
{
//32K << 1,2,3 = 64k,128k,256k
return Sys::flash_size();
}
//=============================================================================
auto Nvm::
write_word (uint32_t addr, uint32_t w) -> uint8_t
{
address(addr);
val(NVMDATA, w);
do_op(PGMWORD);
return error();
}
//=============================================================================
auto Nvm::
write_row (uint32_t src, uint32_t dst) -> uint8_t
{
//flash (dst may be 0 based, OR kseg0 flash addr)
address(dst);
val(NVMSRCADDR, k2phys(src)); //sram
do_op(PGMROW);
return error();
}
//=============================================================================
auto Nvm::
page_erase (uint32_t v) -> uint8_t
{
//flash (v may be 0 based, OR kseg0 flash addr)
address(v);
do_op(ERASEPAGE);
return error();
}