2 #include "../regs/cm4.h" 3 #include "../regs/flash.h" 12 void DFUInterface::StatusData::push(Channel *
c)
const {
14 c->push(m_bwPollTimeout[2]);
15 c->push(m_bwPollTimeout[1]);
16 c->push(m_bwPollTimeout[0]);
21 void DFUInterface::StateData::push(Channel *
c)
const {
28 if (request->
wValue() == 0) {
30 switch (transferBuffer[0]) {
31 case (
uint8_t) DFUDownloadCommand::SetAddressPointer:
32 setAddressPointerCommand(request, transferBuffer, *transferBufferLength);
34 case (
uint8_t) DFUDownloadCommand::Erase:
35 eraseCommand(transferBuffer, *transferBufferLength);
38 m_state = State::dfuERROR;
39 m_status = Status::errSTALLEDPKT;
43 if (request->
wValue() == 1) {
51 memcpy(m_largeBuffer, transferBuffer, *transferBufferLength);
52 m_largeBufferLength = *transferBufferLength;
53 m_state = State::dfuDNLOADSYNC;
61 if (m_state == State::dfuMANIFEST) {
64 }
else if (m_state == State::dfuDNBUSY) {
65 if (m_largeBufferLength != 0) {
69 changeAddressPointerIfNeeded();
70 eraseMemoryIfNeeded();
71 m_state = State::dfuDNLOADIDLE;
81 case (
uint8_t) DFURequest::Detach:
84 case (
uint8_t) DFURequest::Download:
85 return processDownloadRequest(request->
wLength(), transferBufferLength);
86 case (
uint8_t) DFURequest::Upload:
87 return processUploadRequest(request, transferBuffer, transferBufferLength, transferBufferMaxLength);
88 case (
uint8_t) DFURequest::GetStatus:
89 return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength);
90 case (
uint8_t) DFURequest::ClearStatus:
91 return clearStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength);
92 case (
uint8_t) DFURequest::GetState:
93 return getState(transferBuffer, transferBufferLength, transferBufferMaxLength);
94 case (
uint8_t) DFURequest::Abort:
95 return dfuAbort(transferBufferLength);
100 bool DFUInterface::processDownloadRequest(
uint16_t wLength,
uint16_t * transferBufferLength) {
101 if (m_state != State::dfuIDLE && m_state != State::dfuDNLOADIDLE) {
102 m_state = State::dfuERROR;
103 m_status = Status::errNOTDONE;
109 m_state = State::dfuMANIFESTSYNC;
113 m_state = State::dfuDNLOADSYNC;
118 bool DFUInterface::processUploadRequest(SetupPacket * request,
uint8_t * transferBuffer,
uint16_t * transferBufferLength,
uint16_t transferBufferMaxLength) {
119 if (m_state != State::dfuIDLE && m_state != State::dfuUPLOADIDLE) {
123 if (request->wValue() == 0) {
130 }
else if (request->wValue() == 1) {
140 uint16_t copySize = min(transferBufferMaxLength, request->wLength());
141 memcpy(transferBuffer, (
void *)readAddress, copySize);
142 *transferBufferLength = copySize;
144 m_state = State::dfuUPLOADIDLE;
148 void DFUInterface::setAddressPointerCommand(SetupPacket * request,
uint8_t * transferBuffer,
uint16_t transferBufferLength) {
149 assert(transferBufferLength == 5);
151 m_potentialNewAddressPointer = transferBuffer[1]
152 + (transferBuffer[2] << 8)
153 + (transferBuffer[3] << 16)
154 + (transferBuffer[4] << 24);
155 m_state = State::dfuDNLOADSYNC;
158 void DFUInterface::changeAddressPointerIfNeeded() {
159 if (m_potentialNewAddressPointer == 0) {
164 m_addressPointer = m_potentialNewAddressPointer;
165 m_potentialNewAddressPointer = 0;
166 m_state = State::dfuDNLOADIDLE;
167 m_status = Status::OK;
170 void DFUInterface::eraseCommand(
uint8_t * transferBuffer,
uint16_t transferBufferLength) {
173 if (transferBufferLength == 1) {
175 m_erasePage = k_flashMemorySectorsCount;
178 assert(transferBufferLength == 5);
181 uint32_t sectorAddresses[k_flashMemorySectorsCount] = {
195 uint32_t eraseAddress = transferBuffer[1]
196 + (transferBuffer[2] << 8)
197 + (transferBuffer[3] << 16)
198 + (transferBuffer[4] << 24);
199 m_erasePage = k_flashMemorySectorsCount + 1;
200 for (
uint8_t i = 0; i < k_flashMemorySectorsCount; i++) {
201 if (sectorAddresses[i] == eraseAddress) {
206 if (m_erasePage == k_flashMemorySectorsCount + 1) {
207 m_state = State::dfuERROR;
208 m_status = Status::errTARGET;
212 m_state = State::dfuDNLOADSYNC;
216 void DFUInterface::eraseMemoryIfNeeded() {
217 if (m_erasePage == k_flashMemorySectorsCount + 1) {
227 if (m_erasePage == k_flashMemorySectorsCount) {
233 FLASH.
CR()->setSNB(m_erasePage);
241 lockFlashMemoryAndPurgeCaches();
245 m_erasePage = k_flashMemorySectorsCount + 1;
246 m_state = State::dfuDNLOADIDLE;
247 m_status = Status::OK;
250 void DFUInterface::writeOnMemory() {
251 if (m_writeAddress >= k_flashStartAddress && m_writeAddress <= k_flashEndAddress) {
266 *destination++ = *source++;
272 lockFlashMemoryAndPurgeCaches();
273 }
else if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) {
276 memcpy((
void *)m_writeAddress, m_largeBuffer, m_largeBufferLength);
279 m_largeBufferLength = 0;
280 m_state = State::dfuERROR;
281 m_status = Status::errTARGET;
286 m_largeBufferLength = 0;
288 m_state = State::dfuDNLOADIDLE;
289 m_status = Status::OK;
292 void DFUInterface::unlockFlashMemory() {
306 void DFUInterface::lockFlashMemoryAndPurgeCaches() {
321 bool DFUInterface::getStatus(SetupPacket * request,
uint8_t * transferBuffer,
uint16_t * transferBufferLength,
uint16_t transferBufferMaxLength) {
323 if (m_state == State::dfuMANIFESTSYNC) {
324 m_state = State::dfuMANIFEST;
325 }
else if (m_state == State::dfuDNLOADSYNC) {
326 m_state = State::dfuDNBUSY;
329 *transferBufferLength = StatusData(m_status, m_state).copy(transferBuffer, transferBufferMaxLength);
333 bool DFUInterface::clearStatus(SetupPacket * request,
uint8_t * transferBuffer,
uint16_t * transferBufferLength,
uint16_t transferBufferMaxLength) {
334 m_status = Status::OK;
335 m_state = State::dfuIDLE;
336 return getStatus(request, transferBuffer, transferBufferLength, transferBufferMaxLength);
340 *transferBufferLength = StateData(m_state).copy(transferBuffer, maxSize);
344 bool DFUInterface::dfuAbort(
uint16_t * transferBufferLength) {
345 m_status = Status::OK;
346 m_state = State::dfuIDLE;
347 *transferBufferLength = 0;
351 void DFUInterface::leaveDFUAndReset() {
void wholeDataSentCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override
void clearForOutTransactions(uint16_t wLength)
void set(Register< T > value) volatile
void wholeDataReceivedCallback(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength) override
static constexpr int MaxTransferSize
bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override
bool processSetupInRequest(SetupPacket *request, uint8_t *transferBuffer, uint16_t *transferBufferLength, uint16_t transferBufferMaxLength) override
void setResetOnDisconnect(bool reset)
void * memcpy(void *dst, const void *src, size_t n)