-
Notifications
You must be signed in to change notification settings - Fork 1
/
flash_man.cpp
208 lines (188 loc) · 5.99 KB
/
flash_man.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/************************************************************************//**
* \file
*
* \brief Flash Manager.
*
* Handles basic operations on flash chips (Program/Read/Erase) using MDMA
* interface.
*
* \author doragasu
* \date 2017
****************************************************************************/
#include <QApplication>
#include <stdlib.h>
#include "flash_man.h"
#include "util.h"
#include "commands.h"
/********************************************************************//**
* Program a file to the flash chip.
*
* \param[in] filename File name to program.
* \param[in] autoErase Erase the flash range where the file will be
* flashed.
* \param[in] start Word memory addressh where the file will be
* programmed.
* \param[in] len Number of words to write to the flash.
*
* \return A pointer to a buffer containing the file to flash (byte
* swapped) or NULL if the operation fails.
*
* \warning The user is responsible of freeing the buffer calling
* BufFree() when its contents are not needed anymore.
************************************************************************/
uint16_t *FlashMan::Program(const char filename[], bool autoErase,
uint32_t *start, uint32_t *len) {
FILE *rom;
uint16_t *writeBuf;
uint32_t addr;
int toWrite;
uint32_t i;
// Open the file to flash
if (!(rom = fopen(filename, "rb"))) return NULL;
// Obtain length if not specified
if (!(*len)) {
fseek(rom, 0, SEEK_END);
*len = ftell(rom)>>1;
fseek(rom, 0, SEEK_SET);
}
writeBuf = (uint16_t*)malloc(*len<<1);
if (!writeBuf) {
fclose(rom);
return NULL;
}
fread(writeBuf, (*len)<<1, 1, rom);
fclose(rom);
// Do byte swaps
for (i = 0; i < (*len); i++) ByteSwapWord(writeBuf[i]);
// If requested, perform auto-erase
if (autoErase) {
emit StatusChanged("Auto erasing");
QApplication::processEvents();
DelayMs(1);
if (MDMA_range_erase(*start, *len)) {
free(writeBuf);
return NULL;
}
}
emit RangeChanged(0, *len);
emit ValueChanged(0);
emit StatusChanged("Program...");
QApplication::processEvents();
for (i = 0, addr = *start; i < (*len);) {
toWrite = MIN(65536>>1, (*len) - i);
if (MDMA_write(toWrite, addr, writeBuf + i)) {
free(writeBuf);
fclose(rom);
return NULL;
}
// Update vars and draw progress bar
i += toWrite;
addr += toWrite;
emit ValueChanged(i);
QApplication::processEvents();
}
emit ValueChanged(i);
emit StatusChanged("Done!");
QApplication::processEvents();
return writeBuf;
}
/********************************************************************//**
* Read a memory range from the flash chip.
*
* \param[in] start Word memory address to start reading from.
* \param[in] len Number of words to read from flash.
*
* \return A pointer to the buffer containing the data read from the
* flash, or NULL if the read operation has failed.
*
* \warning The user is responsible of freeing the buffer calling
* BufFree() when its contents are not needed anymore.
************************************************************************/
uint16_t *FlashMan::Read(uint32_t start, uint32_t len) {
uint16_t *readBuf;
int toRead;
uint32_t addr;
uint32_t i;
emit RangeChanged(0, len);
emit ValueChanged(0);
emit StatusChanged("Reading");
QApplication::processEvents();
readBuf = (uint16_t*)malloc(len<<1);
if (!readBuf) {
return NULL;
}
for (i = 0, addr = start; i < len;) {
toRead = MIN(65536>>1, len - i);
if (MDMA_read(toRead, addr, readBuf + i)) {
free(readBuf);
return NULL;
}
// Update vars and draw progress bar
i += toRead;
addr += toRead;
emit ValueChanged(i);
QApplication::processEvents();
}
emit ValueChanged(i);
emit StatusChanged("Done");
QApplication::processEvents();
return readBuf;
}
/********************************************************************//**
* Erases a memory range from the flash chip.
*
* \param[in] start Word memory address of the beginning of the range
* to erase.
* \param[in] len Length (in words) of the range to erase.
*
* \return 0 on success, non-zero if erase operation fails.
************************************************************************/
int FlashMan::RangeErase(uint32_t start, uint32_t len) {
if (MDMA_range_erase(start, len)) return -1;
return 0;
}
/********************************************************************//**
* Issues a complete chip erase command to the flash chip.
*
* \return 0 on success, non-zero if erase operation fails.
************************************************************************/
int FlashMan::FullErase(void) {
if (MDMA_cart_erase()) return -1;
return 0;
}
/********************************************************************//**
* Frees a buffer previously allocated by Program() or Read().
*
* \param[in] buf The address of the buffer to free.
************************************************************************/
void FlashMan::BufFree(uint16_t *buf) {
free(buf);
}
/********************************************************************//**
* Obtains the flash chip 16-bit Manufacturer ID code.
*
* \param[out] manId The 16-bit Manufacturer ID of the flash chip.
*
* \return 0 on success, non-zero on error.
************************************************************************/
uint16_t FlashMan::ManIdGet(uint16_t *manId) {
return MDMA_manId_get(manId);
}
/********************************************************************//**
* Obtains the 3 flash chip 16-bit Device ID codes.
*
* \param[out] devIds The 3 16-bit Device IDs of the flash chip.
*
* \return 0 on success, non-zero on error.
************************************************************************/
uint16_t FlashMan::DevIdGet(uint16_t devIds[3]) {
return MDMA_devId_get(devIds);
}
/********************************************************************//**
* Enters DFU bootloader mode.
*
* \return 0 on success, non-zero on error.
************************************************************************/
uint16_t FlashMan::DfuBootloader(void) {
return MDMA_bootloader();
}