dfu_interface.h
5.47 KB
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
#ifndef ION_DEVICE_USB_DFU_INTERFACE_H
#define ION_DEVICE_USB_DFU_INTERFACE_H
#include <assert.h>
#include <stddef.h>
#include "stack/device.h"
#include "stack/interface.h"
#include "stack/endpoint0.h"
#include "stack/setup_packet.h"
#include "stack/streamable.h"
namespace Ion {
namespace USB {
namespace Device {
class DFUInterface : public Interface {
public:
DFUInterface(Device * device, Endpoint0 * ep0, uint8_t bInterfaceAlternateSetting) :
Interface(ep0),
m_device(device),
m_status(Status::OK),
m_state(State::dfuIDLE),
m_addressPointer(0),
m_potentialNewAddressPointer(0),
m_erasePage(-1),
m_largeBuffer{0},
m_largeBufferLength(0),
m_writeAddress(0),
m_bInterfaceAlternateSetting(bInterfaceAlternateSetting)
{
}
void wholeDataReceivedCallback(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength) override;
void wholeDataSentCallback(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength) override;
protected:
void setActiveInterfaceAlternative(uint8_t interfaceAlternativeIndex) override {
assert(interfaceAlternativeIndex == m_bInterfaceAlternateSetting);
}
uint8_t getActiveInterfaceAlternative() override {
return m_bInterfaceAlternateSetting;
}
bool processSetupInRequest(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength) override;
private:
// DFU Request Codes
enum class DFURequest {
Detach = 0,
Download = 1,
Upload = 2,
GetStatus = 3,
ClearStatus = 4,
GetState = 5,
Abort = 6
};
// DFU Download Commmand Codes
enum class DFUDownloadCommand {
GetCommand = 0x00,
SetAddressPointer = 0x21,
Erase = 0x41,
ReadUnprotect = 0x92
};
enum class Status : uint8_t {
OK = 0x00,
errTARGET = 0x01,
errFILE = 0x02,
errWRITE = 0x03,
errERASE = 0x04,
errCHECK_ERASED = 0x05,
errPROG = 0x06,
errVERIFY = 0x07,
errADDRESS = 0x08,
errNOTDONE = 0x09,
errFIRMWARE = 0x0A,
errVENDOR = 0x0B,
errUSBR = 0x0C,
errPOR = 0x0D,
errUNKNOWN = 0x0E,
errSTALLEDPKT = 0x0F
};
enum class State : uint8_t {
appIDLE = 0,
appDETACH = 1,
dfuIDLE = 2,
dfuDNLOADSYNC = 3,
dfuDNBUSY = 4,
dfuDNLOADIDLE = 5,
dfuMANIFESTSYNC = 6,
dfuMANIFEST = 7,
dfuMANIFESTWAITRESET = 8,
dfuUPLOADIDLE = 9,
dfuERROR = 10
};
class StatusData : public Streamable {
public:
StatusData(Status status, State state, uint32_t pollTimeout = 1) :
/* We put a default pollTimeout value of 1ms: if the device is busy, the
* host has to wait 1ms before sending a getStatus Request. */
m_bStatus((uint8_t)status),
m_bwPollTimeout{uint8_t((pollTimeout>>16) & 0xFF), uint8_t((pollTimeout>>8) & 0xFF), uint8_t(pollTimeout & 0xFF)},
m_bState((uint8_t)state),
m_iString(0)
{
}
protected:
void push(Channel * c) const override;
private:
uint8_t m_bStatus; // Status resulting from the execution of the most recent request
uint8_t m_bwPollTimeout[3]; // m_bwPollTimeout is 24 bits
uint8_t m_bState; // State of the device immediately following transmission of this response
uint8_t m_iString;
};
class StateData : public Streamable {
public:
StateData(State state) : m_bState((uint8_t)state) {}
protected:
void push(Channel * c) const override;
private:
uint8_t m_bState; // Current state of the device
};
/* The Flash and SRAM addresses are in flash.ld. However, dfu_interface is
* linked with dfu.ld, so we cannot access the values. */
constexpr static uint32_t k_flashStartAddress = 0x08000000;
constexpr static uint32_t k_flashEndAddress = 0x08100000;
constexpr static uint32_t k_sramStartAddress = 0x20000000;
constexpr static uint32_t k_sramEndAddress = 0x20040000;
// Download and upload
bool processDownloadRequest(uint16_t wLength, uint16_t * transferBufferLength);
bool processUploadRequest(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength);
// Address pointer
void setAddressPointerCommand(SetupPacket * request, uint8_t * transferBuffer, uint16_t transferBufferLength);
void changeAddressPointerIfNeeded();
// Access memory
void eraseCommand(uint8_t * transferBuffer, uint16_t transferBufferLength);
void eraseMemoryIfNeeded();
void writeOnMemory();
void unlockFlashMemory();
void lockFlashMemoryAndPurgeCaches();
// Status
bool getStatus(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength);
bool clearStatus(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength);
// State
bool getState(uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t maxSize);
// Abort
bool dfuAbort(uint16_t * transferBufferLength);
// Leave DFU
void leaveDFUAndReset();
Device * m_device;
Status m_status;
State m_state;
uint32_t m_addressPointer;
uint32_t m_potentialNewAddressPointer;
int32_t m_erasePage;
uint8_t m_largeBuffer[Endpoint0::MaxTransferSize];
uint16_t m_largeBufferLength;
uint32_t m_writeAddress;
uint8_t m_bInterfaceAlternateSetting;
};
}
}
}
#endif