1 /*
2 * Copyright (c) 2013-2022 ARM Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <string.h>
20 #include <stdint.h>
21 #include "Driver_Flash.h"
22 #include "platform_retarget.h"
23 #include "RTE_Device.h"
24
25 #ifndef ARG_UNUSED
26 #define ARG_UNUSED(arg) ((void)arg)
27 #endif
28
29 /* Driver version */
30 #define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 1)
31 #define ARM_FLASH_DRV_ERASE_VALUE 0xFF
32
33 /**
34 * Data width values for ARM_FLASH_CAPABILITIES::data_width
35 * \ref ARM_FLASH_CAPABILITIES
36 */
37 enum {
38 DATA_WIDTH_8BIT = 0u,
39 DATA_WIDTH_16BIT,
40 DATA_WIDTH_32BIT,
41 DATA_WIDTH_ENUM_SIZE
42 };
43
44 static const uint32_t data_width_byte[DATA_WIDTH_ENUM_SIZE] = {
45 sizeof(uint8_t),
46 sizeof(uint16_t),
47 sizeof(uint32_t),
48 };
49
50 /*
51 * ARM FLASH device structure
52 *
53 * There is no real flash memory for code on MPS2 board. Instead a code SRAM is
54 * used for code storage: ZBT SSRAM1. This driver just emulates a flash
55 * interface and behaviour on top of the SRAM memory.
56 */
57 struct arm_flash_dev_t {
58 const uint32_t memory_base; /*!< FLASH memory base address */
59 ARM_FLASH_INFO *data; /*!< FLASH data */
60 };
61
62 /* Flash Status */
63 static ARM_FLASH_STATUS FlashStatus = {0, 0, 0};
64
65 /* Driver Version */
66 static const ARM_DRIVER_VERSION DriverVersion = {
67 ARM_FLASH_API_VERSION,
68 ARM_FLASH_DRV_VERSION
69 };
70
71 /* Driver Capabilities */
72 static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
73 0, /* event_ready */
74 0, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
75 1 /* erase_chip */
76 };
77
is_range_valid(struct arm_flash_dev_t * flash_dev,uint32_t offset)78 static int32_t is_range_valid(struct arm_flash_dev_t *flash_dev,
79 uint32_t offset)
80 {
81 uint32_t flash_limit = 0;
82 int32_t rc = 0;
83
84 flash_limit = (flash_dev->data->sector_count * flash_dev->data->sector_size)
85 - 1;
86
87 if (offset > flash_limit) {
88 rc = -1;
89 }
90 return rc;
91 }
92
is_write_aligned(struct arm_flash_dev_t * flash_dev,uint32_t param)93 static int32_t is_write_aligned(struct arm_flash_dev_t *flash_dev,
94 uint32_t param)
95 {
96 int32_t rc = 0;
97
98 if ((param % flash_dev->data->program_unit) != 0) {
99 rc = -1;
100 }
101 return rc;
102 }
103
is_sector_aligned(struct arm_flash_dev_t * flash_dev,uint32_t offset)104 static int32_t is_sector_aligned(struct arm_flash_dev_t *flash_dev,
105 uint32_t offset)
106 {
107 int32_t rc = 0;
108
109 if ((offset % flash_dev->data->sector_size) != 0) {
110 rc = -1;
111 }
112 return rc;
113 }
114
is_flash_ready_to_write(const uint8_t * start_addr,uint32_t cnt)115 static int32_t is_flash_ready_to_write(const uint8_t *start_addr, uint32_t cnt)
116 {
117 int32_t rc = 0;
118 uint32_t i;
119
120 for (i = 0; i < cnt; i++) {
121 if(start_addr[i] != ARM_FLASH_DRV_ERASE_VALUE) {
122 rc = -1;
123 break;
124 }
125 }
126
127 return rc;
128 }
129
130 #if (RTE_FLASH0)
131 static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = {
132 .sector_info = NULL, /* Uniform sector layout */
133 .sector_count = FLASH0_SIZE / FLASH0_SECTOR_SIZE,
134 .sector_size = FLASH0_SECTOR_SIZE,
135 .page_size = FLASH0_PAGE_SIZE,
136 .program_unit = FLASH0_PROGRAM_UNIT,
137 .erased_value = ARM_FLASH_DRV_ERASE_VALUE};
138
139 static struct arm_flash_dev_t ARM_FLASH0_DEV = {
140 #if (__DOMAIN_NS == 1)
141 .memory_base = FLASH0_BASE_NS,
142 #else
143 .memory_base = FLASH0_BASE_S,
144 #endif /* __DOMAIN_NS == 1 */
145 .data = &(ARM_FLASH0_DEV_DATA)};
146
147 struct arm_flash_dev_t *FLASH0_DEV = &ARM_FLASH0_DEV;
148
149 /*
150 * Functions
151 */
152
ARM_Flash_GetVersion(void)153 static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
154 {
155 return DriverVersion;
156 }
157
ARM_Flash_GetCapabilities(void)158 static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
159 {
160 return DriverCapabilities;
161 }
162
ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)163 static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
164 {
165 ARG_UNUSED(cb_event);
166
167 if (FLASH0_PROGRAM_UNIT % data_width_byte[DriverCapabilities.data_width] ||
168 DriverCapabilities.data_width >= DATA_WIDTH_ENUM_SIZE) {
169 return ARM_DRIVER_ERROR;
170 }
171 /* Nothing to be done */
172 return ARM_DRIVER_OK;
173 }
174
ARM_Flash_Uninitialize(void)175 static int32_t ARM_Flash_Uninitialize(void)
176 {
177 /* Nothing to be done */
178 return ARM_DRIVER_OK;
179 }
180
ARM_Flash_PowerControl(ARM_POWER_STATE state)181 static int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state)
182 {
183 switch (state) {
184 case ARM_POWER_FULL:
185 /* Nothing to be done */
186 return ARM_DRIVER_OK;
187 break;
188
189 case ARM_POWER_OFF:
190 case ARM_POWER_LOW:
191 default:
192 return ARM_DRIVER_ERROR_UNSUPPORTED;
193 }
194 }
195
ARM_Flash_ReadData(uint32_t addr,void * data,uint32_t cnt)196 static int32_t ARM_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt)
197 {
198 uint32_t start_addr = FLASH0_DEV->memory_base + addr;
199 int32_t rc = 0;
200
201 /* CMSIS ARM_FLASH_ReadData API requires the `addr` data type size aligned.
202 * Data type size is specified by the data_width in ARM_FLASH_CAPABILITIES.
203 */
204 if (addr % data_width_byte[DriverCapabilities.data_width] != 0) {
205 return ARM_DRIVER_ERROR_PARAMETER;
206 }
207
208 /* Conversion between data items and bytes */
209 cnt *= data_width_byte[DriverCapabilities.data_width];
210
211 /* Check flash memory boundaries */
212 rc = is_range_valid(FLASH0_DEV, addr + cnt);
213 if (rc != 0) {
214 return ARM_DRIVER_ERROR_PARAMETER;
215 }
216
217 /* Flash interface just emulated over SRAM, use memcpy */
218 memcpy(data, (void *)start_addr, cnt);
219
220 /* Conversion between bytes and data items */
221 cnt /= data_width_byte[DriverCapabilities.data_width];
222
223 return cnt;
224 }
225
ARM_Flash_ProgramData(uint32_t addr,const void * data,uint32_t cnt)226 static int32_t ARM_Flash_ProgramData(uint32_t addr, const void *data,
227 uint32_t cnt)
228 {
229 uint32_t start_addr = FLASH0_DEV->memory_base + addr;
230 int32_t rc = 0;
231
232 /* Conversion between data items and bytes */
233 cnt *= data_width_byte[DriverCapabilities.data_width];
234
235 /* Check flash memory boundaries and alignment with minimal write size */
236 rc = is_range_valid(FLASH0_DEV, addr + cnt);
237 rc |= is_write_aligned(FLASH0_DEV, addr);
238 rc |= is_write_aligned(FLASH0_DEV, cnt);
239 if (rc != 0) {
240 return ARM_DRIVER_ERROR_PARAMETER;
241 }
242
243 /* Check if the flash area to write the data was erased previously */
244 rc = is_flash_ready_to_write((const uint8_t*)start_addr, cnt);
245
246 /* Flash interface just emulated over SRAM, use memcpy */
247 memcpy((void *)start_addr, data, cnt);
248
249 /* Conversion between bytes and data items */
250 cnt /= data_width_byte[DriverCapabilities.data_width];
251
252 return cnt;
253 }
254
ARM_Flash_EraseSector(uint32_t addr)255 static int32_t ARM_Flash_EraseSector(uint32_t addr)
256 {
257 uint32_t start_addr = FLASH0_DEV->memory_base + addr;
258 uint32_t rc = 0;
259
260 rc = is_range_valid(FLASH0_DEV, addr);
261 rc |= is_sector_aligned(FLASH0_DEV, addr);
262 if (rc != 0) {
263 return ARM_DRIVER_ERROR_PARAMETER;
264 }
265
266 /* Flash interface just emulated over SRAM, use memset */
267 memset((void *)start_addr,
268 FLASH0_DEV->data->erased_value,
269 FLASH0_DEV->data->sector_size);
270 return ARM_DRIVER_OK;
271 }
272
ARM_Flash_EraseChip(void)273 static int32_t ARM_Flash_EraseChip(void)
274 {
275 uint32_t i;
276 uint32_t addr = FLASH0_DEV->memory_base;
277 int32_t rc = ARM_DRIVER_ERROR_UNSUPPORTED;
278
279 /* Check driver capability erase_chip bit */
280 if (DriverCapabilities.erase_chip == 1) {
281 for (i = 0; i < FLASH0_DEV->data->sector_count; i++) {
282 /* Flash interface just emulated over SRAM, use memset */
283 memset((void *)addr,
284 FLASH0_DEV->data->erased_value,
285 FLASH0_DEV->data->sector_size);
286
287 addr += FLASH0_DEV->data->sector_size;
288 rc = ARM_DRIVER_OK;
289 }
290 }
291 return rc;
292 }
293
ARM_Flash_GetStatus(void)294 static ARM_FLASH_STATUS ARM_Flash_GetStatus(void)
295 {
296 return FlashStatus;
297 }
298
ARM_Flash_GetInfo(void)299 static ARM_FLASH_INFO * ARM_Flash_GetInfo(void)
300 {
301 return FLASH0_DEV->data;
302 }
303
304 ARM_DRIVER_FLASH Driver_FLASH0 = {
305 ARM_Flash_GetVersion,
306 ARM_Flash_GetCapabilities,
307 ARM_Flash_Initialize,
308 ARM_Flash_Uninitialize,
309 ARM_Flash_PowerControl,
310 ARM_Flash_ReadData,
311 ARM_Flash_ProgramData,
312 ARM_Flash_EraseSector,
313 ARM_Flash_EraseChip,
314 ARM_Flash_GetStatus,
315 ARM_Flash_GetInfo
316 };
317 #endif /* RTE_FLASH0 */
318