1 /*!
2 \file dfu_mal.c
3 \brief USB DFU device media access layer functions
4
5 \version 2020-08-04, V1.1.0, firmware for GD32VF103
6 */
7
8 /*
9 Copyright (c) 2020, GigaDevice Semiconductor Inc.
10
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 1. Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 3. Neither the name of the copyright holder nor the names of its contributors
20 may be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34
35 #include "dfu_mal.h"
36 #include "flash_if.h"
37 #include "drv_usb_hw.h"
38 #include "usbd_transc.h"
39
40 extern usb_core_driver usb_dfu_dev;
41
42 extern struct {
43 uint8_t buf[TRANSFER_SIZE];
44 uint16_t data_len;
45 uint16_t block_num;
46 uint32_t base_addr;
47 } prog;
48
49 dfu_mal_prop* tMALTab[MAX_USED_MEMORY_MEDIA] = {
50 &DFU_Flash_cb
51 };
52
53 /* The list of memory interface string descriptor pointers. This list
54 can be updated whenever a memory has to be added or removed */
55 const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] =
56 {
57 (const uint8_t *)FLASH_IF_STRING
58 };
59
60 static uint8_t dfu_mal_checkaddr (uint32_t addr);
61
62 /*!
63 \brief initialize the memory media on the GD32
64 \param[in] none
65 \param[out] none
66 \retval MAL_OK
67 */
dfu_mal_init(void)68 uint8_t dfu_mal_init (void)
69 {
70 uint32_t mem_index = 0U;
71
72 /* initialize all supported memory medias */
73 for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) {
74 /* check if the memory media exists */
75 if (NULL != tMALTab[mem_index]->mal_init) {
76 tMALTab[mem_index]->mal_init();
77 }
78 }
79
80 return MAL_OK;
81 }
82
83 /*!
84 \brief deinitialize the memory media on the GD32
85 \param[in] none
86 \param[out] none
87 \retval MAL_OK
88 */
dfu_mal_deinit(void)89 uint8_t dfu_mal_deinit (void)
90 {
91 uint32_t mem_index = 0U;
92
93 /* deinitializes all supported memory medias */
94 for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) {
95 /* check if the memory media exists */
96 if (NULL != tMALTab[mem_index]->mal_deinit) {
97 tMALTab[mem_index]->mal_deinit();
98 }
99 }
100
101 return MAL_OK;
102 }
103
104 /*!
105 \brief erase a memory sector
106 \param[in] addr: memory sector address/code
107 \param[out] none
108 \retval MAL_OK
109 */
dfu_mal_erase(uint32_t addr)110 uint8_t dfu_mal_erase (uint32_t addr)
111 {
112 uint32_t mem_index = dfu_mal_checkaddr(addr);
113
114 /* check if the address is in protected area */
115 if (IS_PROTECTED_AREA(addr)) {
116 return MAL_FAIL;
117 }
118
119 if (mem_index < MAX_USED_MEMORY_MEDIA) {
120 /* check if the operation is supported */
121 if (NULL != tMALTab[mem_index]->mal_erase) {
122 return tMALTab[mem_index]->mal_erase(addr);
123 } else {
124 return MAL_FAIL;
125 }
126 } else {
127 return MAL_FAIL;
128 }
129 }
130
131 /*!
132 \brief write data to sectors of memory
133 \param[in] buf: the data buffer to be write
134 \param[in] addr: memory sector address/code
135 \param[in] len: data length
136 \param[out] none
137 \retval MAL_OK
138 */
dfu_mal_write(uint8_t * buf,uint32_t addr,uint32_t len)139 uint8_t dfu_mal_write (uint8_t *buf, uint32_t addr, uint32_t len)
140 {
141 uint32_t mem_index = dfu_mal_checkaddr(addr);
142
143 /* check if the address is in protected area */
144 if (IS_PROTECTED_AREA(addr)) {
145 return MAL_FAIL;
146 }
147
148 if (mem_index < MAX_USED_MEMORY_MEDIA) {
149 /* check if the operation is supported */
150 if (NULL != tMALTab[mem_index]->mal_write) {
151 return tMALTab[mem_index]->mal_write(buf, addr, len);
152 } else {
153 return MAL_FAIL;
154 }
155 } else {
156 return MAL_FAIL;
157 }
158 }
159
160 /*!
161 \brief read data from sectors of memory
162 \param[in] buf: the data buffer to be write
163 \param[in] addr: memory sector address/code
164 \param[in] len: data length
165 \param[out] none
166 \retval pointer to buffer
167 */
dfu_mal_read(uint8_t * buf,uint32_t addr,uint32_t len)168 uint8_t* dfu_mal_read (uint8_t *buf, uint32_t addr, uint32_t len)
169 {
170 uint32_t mem_index = 0U;
171
172 if (OB_RDPT != addr) {
173 mem_index = dfu_mal_checkaddr(addr);
174 }
175
176 if (mem_index < MAX_USED_MEMORY_MEDIA) {
177 /* check if the operation is supported */
178 if (NULL != tMALTab[mem_index]->mal_read) {
179 return tMALTab[mem_index]->mal_read(buf, addr, len);
180 } else {
181 return buf;
182 }
183 } else {
184 return buf;
185 }
186 }
187
188 /*!
189 \brief get the status of a given memory and store in buffer
190 \param[in] addr: memory sector address/code
191 \param[in] cmd: 0 for erase and 1 for write
192 \param[in] buffer: pointer to the buffer where the status data will be stored
193 \param[out] none
194 \retval MAL_OK if all operations are OK, MAL_FAIL else
195 */
dfu_mal_getstatus(uint32_t addr,uint8_t cmd,uint8_t * buffer)196 uint8_t dfu_mal_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer)
197 {
198 uint32_t mem_index = dfu_mal_checkaddr(addr);
199
200 if (mem_index < MAX_USED_MEMORY_MEDIA) {
201 if (cmd & 0x01U) {
202 SET_POLLING_TIMEOUT(tMALTab[mem_index]->write_timeout);
203 } else {
204 SET_POLLING_TIMEOUT(tMALTab[mem_index]->erase_timeout);
205 }
206
207 return MAL_OK;
208 } else {
209 return MAL_FAIL;
210 }
211 }
212
213 /*!
214 \brief check the address is supported
215 \param[in] addr: memory sector address/code
216 \param[out] none
217 \retval index of the addressed memory
218 */
dfu_mal_checkaddr(uint32_t addr)219 static uint8_t dfu_mal_checkaddr (uint32_t addr)
220 {
221 uint8_t mem_index = 0U;
222
223 /* check with all supported memories */
224 for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) {
225 /* if the check address is supported, return the memory index */
226 if (MAL_OK == tMALTab[mem_index]->mal_checkaddr(addr)) {
227 return mem_index;
228 }
229 }
230
231 /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */
232 return (MAX_USED_MEMORY_MEDIA);
233 }
234