-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi_memory.cpp
119 lines (106 loc) · 3.38 KB
/
spi_memory.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
#include "kernel.h"
#include "spi_memory.h"
void CKernel::SetWriteEnable() {
m_WEPin.Write(LOW);
}
void CKernel::ResetWriteEnable() {
m_WEPin.Write(HIGH);
}
MemoryStatusRegister CKernel::ParseStatusRegister(const u8 statusRegister) {
return (MemoryStatusRegister){
static_cast<u8>((statusRegister & 0b10000000) >> 7),
static_cast<u8>((statusRegister & 0b01000000) >> 6),
static_cast<u8>((statusRegister & 0b00100000) >> 5),
static_cast<u8>((statusRegister & 0b00001100) >> 2),
static_cast<u8>((statusRegister & 0b00000010) >> 1),
static_cast<u8>((statusRegister & 0b00000001))
};
}
void CKernel::ReadStatusRegister(MemoryStatusRegister* statusRegister) {
constexpr u8 data[] = {ReRAM_RDSR, 0};
u8 reg[] = {0, 0};
constexpr int len = sizeof(data) / sizeof(u8);
if (m_SPIMaster.WriteRead(SPI_CHIP_SELECT, &data, reg, len) != len) {
m_Logger.Write(FromKernel, LogPanic, "SPI write error");
}
*statusRegister = ParseStatusRegister(reg[1]);
}
void CKernel::SetWriteEnableLatch(const bool check_register) {
constexpr u8 data[] = {ReRAM_WREN};
constexpr int data_len = sizeof(data) / sizeof(u8);
// Only needed for WRSR: SetWriteEnable();
if (m_SPIMaster.Write(SPI_CHIP_SELECT, data, data_len) != data_len) {
m_Logger.Write(FromKernel, LogPanic, "SPI write error");
}
// Only needed for WRSR: ResetWriteEnable();
if (check_register) {
MemoryStatusRegister statusRegister;
do {
ReadStatusRegister(&statusRegister);
} while (statusRegister.WriteInProgressBit != 1);
}
}
MeasurementResult CKernel::WIPPollingCycles(u64& cycles, const int timeout) {
MemoryStatusRegister statusRegister;
for (u64 i = 1; timeout < 0 || i < static_cast<u64>(timeout); ++i) {
ReadStatusRegister(&statusRegister);
if (!statusRegister.WriteInProgressBit) {
cycles = i;
return Okay;
}
}
return FailedTotally;
}
void CKernel::MemWrite(u32 adr, u8 value) {
#if MEM_ADR_SEND == 2
u8 write_data[] = {
ReRAM_WR,
static_cast<u8>(adr >> 8 & 0xFF),
static_cast<u8>(adr >> 0 & 0xFF),
value
};
#elif MEM_ADR_SEND == 3
u8 write_data[] = {
ReRAM_WR,
static_cast<u8>(adr >> 16 & 0xFF),
static_cast<u8>(adr >> 8 & 0xFF),
static_cast<u8>(adr >> 0 & 0xFF),
value
};
#endif
constexpr int write_len = sizeof(write_data) / sizeof(u8);
SetWriteEnableLatch(false);
// Only needed for WRSR: SetWriteEnable();
if (m_SPIMaster.Write(SPI_CHIP_SELECT, write_data, write_len) != write_len) {
m_Logger.Write(FromKernel, LogPanic, "SPI write error");
}
// Only needed for WRSR: ResetWriteEnable();
}
u8 CKernel::MemRead(u32 adr) {
#if MEM_ADR_SEND == 2
u8 write_data[] = {
ReRAM_READ,
static_cast<u8>(adr >> 8 & 0xFF),
static_cast<u8>(adr >> 0 & 0xFF),
0
};
#elif MEM_ADR_SEND == 3
u8 write_data[] = {
ReRAM_READ,
static_cast<u8>(adr >> 16 & 0xFF),
static_cast<u8>(adr >> 8 & 0xFF),
static_cast<u8>(adr >> 0 & 0xFF),
0
};
#endif
u8 read_data[1 + MEM_ADR_SEND + 1];
constexpr int len = sizeof(write_data) / sizeof(u8);
if (m_SPIMaster.WriteRead(SPI_CHIP_SELECT, write_data, read_data, len) != len) {
m_Logger.Write(FromKernel, LogPanic, "SPI write error");
}
return read_data[1 + MEM_ADR_SEND];
}
MeasurementResult CKernel::MemWriteAndPoll(u64& cycles, const u32 adr, const u8 value, const int timeout) {
MemWrite(adr, value);
return WIPPollingCycles(cycles, timeout);
}