1 /** mbed Microcontroller Library
2 ******************************************************************************
3 * @file flash_api.c
4 * @author
5 * @version V1.0.0
6 * @date 2016-08-01
7 * @brief This file provides mbed API for flash.
8 ******************************************************************************
9 * @attention
10 *
11 * This module is a confidential and proprietary property of RealTek and
12 * possession or use of this module requires written permission of RealTek.
13 *
14 * Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved.
15 ******************************************************************************
16 */
17
18
19
20 #include "objects.h"
21 #include "PinNames.h"
22
23
24 #include "pinmap.h"
25
26 #include "ameba_soc.h"
27 #include "flash_api.h"
28
29 extern u32 ConfigDebugInfo;
30
31 /** @addtogroup AmebaD_Mbed_API
32 * @{
33 */
34
35 /** @defgroup MBED_FLASH
36 * @brief MBED_FLASH driver modules.
37 * @{
38 */
39
40 /** @defgroup MBED_FLASH_Exported_Functions MBED_FLASH Exported Functions
41 * @{
42 */
43
44 /**
45 * @brief Control the flash chip write protect enable/disable.
46 * @param obj: Flash object define in application software.
47 * @param protect: This parameter can be 1 or 0.
48 * @arg 1: Protect the whole chip from being programmed/erased.
49 * @arg 0: Unprotect the whole chip from being programmed/erased.
50 * @retval none
51 */
flash_write_protect(flash_t * obj,u32 protect)52 void flash_write_protect(flash_t *obj, u32 protect)
53 {
54 /* To avoid gcc warnings */
55 ( void ) obj;
56
57 FLASH_Write_Lock();
58 FLASH_SetStatusBits(0x1c, protect);
59 FLASH_Write_Unlock();
60 }
61
62 /**
63 * @brief Set Status register to enable desired operation
64 * @param obj: Flash object define in application software.
65 * @param data: Specifies which bit users like to set.
66 * ex: if users want to set the third bit, data = 0x8.
67 * @retval 1: Success or Others: Failure.
68 * @note Please refer to the datatsheet of flash for more details of the content of status register.
69 * The block protected area and the corresponding control bits are provided in the flash datasheet.
70 */
flash_set_status(flash_t * obj,u32 data)71 int flash_set_status(flash_t *obj, u32 data)
72 {
73 /* To avoid gcc warnings */
74 ( void ) obj;
75
76 u8 status[2];
77 u8 StatusLen = 1;
78
79 status[0] = (u8)data;
80 FLASH_Write_Lock();
81
82 /* check if status2 */
83 if (flash_init_para.FLASH_Status2_exist) {
84 StatusLen = 2;
85 FLASH_RxCmd(flash_init_para.FLASH_cmd_rd_status2, 1, &status[1]);
86 }
87
88 if(!flash_init_para.FLASH_cmd_wr_status2){
89 FLASH_SetStatus(flash_init_para.FLASH_cmd_wr_status, StatusLen, status);
90 } else {
91 FLASH_SetStatus(flash_init_para.FLASH_cmd_wr_status, 1, &status[0]);
92 FLASH_SetStatus(flash_init_para.FLASH_cmd_wr_status2, 1, &status[1]);
93 }
94 FLASH_Write_Unlock();
95
96 return 1;
97 }
98
99 /**
100 * @brief This function aims to reset the status register to 0, please make sure the operation is appropriate.
101 * @param obj: Flash object define in application software.
102 * @retval none
103 * @note Also reset the value of status register2 to 0 if flash chip has status register2
104 */
flash_reset_status(flash_t * obj)105 void flash_reset_status(flash_t *obj)
106 {
107 flash_set_status(obj, 0);
108 return;
109 }
110
111
112 /**
113 * @brief Get the value of status register1
114 * @param obj: Flash object define in application software.
115 * @retval : The value of status register1.
116 */
flash_get_status(flash_t * obj)117 int flash_get_status(flash_t *obj)
118 {
119 /* To avoid gcc warnings */
120 ( void ) obj;
121
122 int data;
123
124 FLASH_Write_Lock();
125 FLASH_RxCmd(flash_init_para.FLASH_cmd_rd_status, 1, (u8*)&data);
126 FLASH_Write_Unlock();
127
128 return data;
129 }
130
131 /**
132 * @brief Erase flash sector(4KB)
133 * @param obj: Flash object define in application software.
134 * @param address: Specifies the starting address to be erased. LSB 12bits will be masked.
135 * @retval none
136 */
flash_erase_sector(flash_t * obj,u32 address)137 void flash_erase_sector(flash_t *obj, u32 address)
138 {
139 /* To avoid gcc warnings */
140 ( void ) obj;
141
142 FLASH_Write_Lock();
143 FLASH_Erase(EraseSector, address);
144
145 DCache_Invalidate(SPI_FLASH_BASE + address, 0x1000);
146 FLASH_Write_Unlock();
147 }
148
149 /**
150 * @brief Erase flash block(64KB)
151 * @param obj: Flash object define in application software.
152 * @param address: Specifies the starting address to be erased. LSB 16bits will be masked.
153 * @retval none
154 */
flash_erase_block(flash_t * obj,u32 address)155 void flash_erase_block(flash_t *obj, u32 address)
156 {
157 /* To avoid gcc warnings */
158 ( void ) obj;
159
160 FLASH_Write_Lock();
161 FLASH_Erase(EraseBlock, address);
162
163 DCache_Invalidate(SPI_FLASH_BASE + address, 0x10000);
164 FLASH_Write_Unlock();
165 }
166
167 /**
168 * @brief Erase the whole flash chip
169 * @param obj: Flash object define in application software.
170 * @retval none
171 */
flash_erase_chip(flash_t * obj)172 void flash_erase_chip(flash_t *obj)
173 {
174 /* To avoid gcc warnings */
175 ( void ) obj;
176
177 FLASH_Write_Lock();
178 FLASH_Erase(EraseChip, 0);
179 Cache_Flush();
180 FLASH_Write_Unlock();
181 }
182
183 /**
184 * @brief Read a word from specified address
185 * @param obj: Flash object define in application software.
186 * @param address: Specifies the address to read from.
187 * @param data: Specified the address to save the readback data.
188 * @retval 1: Success or Others: Failure.
189 * @note auto mode read is ok, because we have flash cache
190 */
flash_read_word(flash_t * obj,u32 address,u32 * data)191 int flash_read_word(flash_t *obj, u32 address, u32 * data)
192 {
193 /* To avoid gcc warnings */
194 ( void ) obj;
195
196 // FLASH_RxData(0, address, 4, data);
197 assert_param(data != NULL);
198
199 u32 offset_to_align = address & 0x03;
200 u32 read_data;
201 u32 temp;
202 u32 i = 4 - offset_to_align;
203
204 if(offset_to_align){
205 address -= offset_to_align;
206 temp = HAL_READ32(SPI_FLASH_BASE, address);
207 read_data= temp >> (offset_to_align * 8);
208
209 address += 4;
210 temp = HAL_READ32(SPI_FLASH_BASE, address);
211 read_data |= (temp << (i * 8));
212
213 *data = read_data;
214 }else{
215 * data = HAL_READ32(SPI_FLASH_BASE, address);
216 }
217
218 return 1;
219 }
220
221 /**
222 * @brief Write a word to specified address
223 * @param obj: Flash object define in application software.
224 * @param address: Specifies the address to be programmed to.
225 * @param data: Specified the data to be programmed.
226 * @retval 1: Success or Others: Failure.
227 * @note user mode write used
228 */
flash_write_word(flash_t * obj,u32 address,u32 data)229 int flash_write_word(flash_t *obj, u32 address, u32 data)
230 {
231 /* To avoid gcc warnings */
232 ( void ) obj;
233
234 // Disable write protection
235 // flash_unlock();
236
237 u32 write_word = data;
238 u32 offset_to_align = address & 0x03;
239 u32 temp;
240 u32 i = 4 - offset_to_align;
241
242 FLASH_Write_Lock();
243 if(offset_to_align){
244 address -= offset_to_align;
245 temp = HAL_READ32(SPI_FLASH_BASE, address);
246 temp = (temp << (i * 8))>>(8*i) | write_word << (8 * offset_to_align);
247 FLASH_TxData12B(address, 4, (u8*)&temp);
248
249 address += 4;
250 temp = HAL_READ32(SPI_FLASH_BASE, address);
251 temp = (temp >> (offset_to_align * 8)) << (offset_to_align * 8) | write_word >>(8*i);
252 FLASH_TxData12B(address, 4, (u8*)&temp);
253 }else{
254 FLASH_TxData12B(address, 4, (u8*)&write_word);
255 }
256
257 DCache_Invalidate(SPI_FLASH_BASE + address, 4);
258 FLASH_Write_Unlock();
259
260 // Enable write protection
261 // flash_lock();
262 return 1;
263 }
264
265
266 /**
267 * @brief Read a stream of data from specified address
268 * @param obj: Flash object define in application software.
269 * @param address: Specifies the starting address to read from.
270 * @param len: Specifies the length of the data to read.
271 * @param data: Specified the address to save the readback data.
272 * @retval 1: Success or Others: Failure.
273 * @note auto mode is ok, because we have flash cache
274 */
flash_stream_read(flash_t * obj,u32 address,u32 len,u8 * data)275 int flash_stream_read(flash_t *obj, u32 address, u32 len, u8 * data)
276 {
277 /* To avoid gcc warnings */
278 ( void ) obj;
279
280 assert_param(data != NULL);
281
282 u32 offset_to_align;
283 u32 i;
284 u32 read_word;
285 u8 *ptr;
286 u8 *pbuf;
287
288 offset_to_align = address & 0x03;
289 pbuf = data;
290 if (offset_to_align != 0) {
291 /* the start address is not 4-bytes aligned */
292 read_word = HAL_READ32(SPI_FLASH_BASE, (address - offset_to_align));
293 ptr = (u8*)&read_word + offset_to_align;
294 offset_to_align = 4 - offset_to_align;
295 for (i=0;i<offset_to_align;i++) {
296 *pbuf = *(ptr+i);
297 pbuf++;
298 len--;
299 if (len == 0) {
300 break;
301 }
302 }
303 }
304
305 /* address = next 4-bytes aligned */
306 address = (((address-1) >> 2) + 1) << 2;
307
308 ptr = (u8*)&read_word;
309 if ((u32)pbuf & 0x03) {
310 while (len >= 4) {
311 read_word = HAL_READ32(SPI_FLASH_BASE, address);
312 for (i=0;i<4;i++) {
313 *pbuf = *(ptr+i);
314 pbuf++;
315 }
316 address += 4;
317 len -= 4;
318 }
319 } else {
320 while (len >= 4) {
321 *((u32 *)pbuf) = HAL_READ32(SPI_FLASH_BASE, address);
322 pbuf += 4;
323 address += 4;
324 len -= 4;
325 }
326 }
327
328 if (len > 0) {
329 read_word = HAL_READ32(SPI_FLASH_BASE, address);
330 for (i=0;i<len;i++) {
331 *pbuf = *(ptr+i);
332 pbuf++;
333 }
334 }
335
336 return 1;
337 }
338
339 /**
340 * @brief Write a stream of data to specified address
341 * @param obj: Flash object define in application software.
342 * @param address: Specifies the starting address to write to.
343 * @param len: Specifies the length of the data to write.
344 * @param data: Pointer to a byte array that is to be written.
345 * @retval 1: Success or Others: Failure.
346 */
flash_stream_write(flash_t * obj,u32 address,u32 len,u8 * data)347 int flash_stream_write(flash_t *obj, u32 address, u32 len, u8 * data)
348 {
349 /* To avoid gcc warnings */
350 ( void ) obj;
351
352 // Check address: 4byte aligned & page(256bytes) aligned
353 u32 page_begin = address & (~0xff);
354 u32 page_end = (address + len) & (~0xff);
355 u32 page_cnt = ((page_end - page_begin) >> 8) + 1;
356
357 u32 addr_begin = address;
358 u32 addr_end = (page_cnt == 1) ? (address + len) : (page_begin + 0x100);
359 u32 size = addr_end - addr_begin;
360 u8 *buffer = data;
361 u8 write_data[12];
362
363 u32 offset_to_align;
364 u32 read_word;
365 u32 i;
366
367 FLASH_Write_Lock();
368 while(page_cnt){
369 offset_to_align = addr_begin & 0x3;
370
371 if(offset_to_align != 0){
372 read_word = HAL_READ32(SPI_FLASH_BASE, addr_begin - offset_to_align);
373 for(i = offset_to_align;i < 4;i++){
374 read_word = (read_word & (~(0xff << (8*i)))) |( (*buffer) <<(8*i));
375 size--;
376 buffer++;
377 if(size == 0)
378 break;
379 }
380 FLASH_TxData12B(addr_begin - offset_to_align, 4, (u8*)&read_word);
381 #ifdef MICRON_N25Q00AA
382 FLASH_ReadFlagStatusReg();
383 #endif
384 }
385
386 addr_begin = (((addr_begin-1) >> 2) + 1) << 2;
387 for(;size >= 12 ;size -= 12){
388 _memcpy(write_data, buffer, 12);
389 FLASH_TxData12B(addr_begin, 12, write_data);
390 #ifdef MICRON_N25Q00AA
391 FLASH_ReadFlagStatusReg();
392 #endif
393 buffer += 12;
394 addr_begin += 12;
395 }
396
397 for(;size >= 4; size -=4){
398 _memcpy(write_data, buffer, 4);
399 FLASH_TxData12B(addr_begin, 4, write_data);
400 #ifdef MICRON_N25Q00AA
401 FLASH_ReadFlagStatusReg();
402 #endif
403 buffer += 4;
404 addr_begin += 4;
405 }
406
407 if(size > 0){
408 read_word = HAL_READ32(SPI_FLASH_BASE, addr_begin);
409 for( i = 0;i < size;i++){
410 read_word = (read_word & (~(0xff << (8*i)))) | ((*buffer) <<(8*i));
411 buffer++;
412 }
413 FLASH_TxData12B(addr_begin, 4, (u8*)&read_word);
414 #ifdef MICRON_N25Q00AA
415 FLASH_ReadFlagStatusReg();
416 #endif
417 }
418
419 page_cnt--;
420 addr_begin = addr_end;
421 addr_end = (page_cnt == 1) ? (address + len) : (((addr_begin>>8) + 1)<<8);
422 size = addr_end - addr_begin;
423 }
424
425 DCache_Invalidate(SPI_FLASH_BASE + address, len);
426 FLASH_Write_Unlock();
427
428 return 1;
429 }
430
431 /**
432 * @brief It is the same with flash_stream_write function which is used to write a stream of data to specified address.
433 * @param obj: Flash object define in application software.
434 * @param address: Specifies the starting address to write to.
435 * @param len: Specifies the length of the data to write.
436 * @param data: Pointer to a byte array that is to be written.
437 * @retval 1: Success or Others: Failure.
438 */
flash_burst_write(flash_t * obj,u32 address,u32 Length,u8 * data)439 int flash_burst_write(flash_t *obj, u32 address ,u32 Length, u8 * data)
440 {
441 flash_stream_write(obj, address, Length, data);
442 return 1;
443 }
444
445 /**
446 * @brief It is the same with flash_stream_read function which is used to read a stream of data from specified address
447 * @param obj: Flash object define in application software.
448 * @param address: Specifies the starting address to read from.
449 * @param len: Specifies the length of the data to read.
450 * @param data: Specified the address to save the readback data.
451 * @retval 1: Success or Others: Failure.
452 */
flash_burst_read(flash_t * obj,u32 address,u32 Length,u8 * data)453 int flash_burst_read(flash_t *obj, u32 address, u32 Length, u8 * data)
454 {
455 flash_stream_read(obj, address, Length, data);
456 return 1;
457 }
458
459
460 /**
461 * @brief This function is only for Micron 128MB flash to access beyond 16MB by switching between eight 16MB-area(segment).
462 * Please refer to flash datasheet for more information about memory mapping.
463 * @param obj: Flash object define in application software.
464 * @param data: Specified which segment to choose.
465 * @retval 1: Success or Others: Failure.
466 */
flash_set_extend_addr(flash_t * obj,u32 data)467 int flash_set_extend_addr(flash_t *obj, u32 data)
468 {
469 /* To avoid gcc warnings */
470 ( void ) obj;
471
472 /*Write Extended Address Register to select operating segment*/
473 u8 segnum = (u8)(data & 0x07);
474
475 FLASH_Write_Lock();
476 FLASH_SetStatus(0xC5, 1, &segnum);
477 FLASH_Write_Unlock();
478 return 1;
479 }
480
481 /**
482 * @brief This function is only for Micron 128MB flash to read from Extended Address Register, which shows the current segment.
483 * Please refer to flash datasheet for more information about memory mapping.
484 * @param obj: Flash object define in application software.
485 * @retval : The value of current Extended Address Register.
486 */
flash_get_extend_addr(flash_t * obj)487 int flash_get_extend_addr(flash_t *obj)
488 {
489 /* To avoid gcc warnings */
490 ( void ) obj;
491
492 u8 temp = 0;
493
494 FLASH_Write_Lock();
495 FLASH_RxCmd(0xC8, 1, &temp);
496 FLASH_Write_Unlock();
497 return temp;
498 }
499
500 /**
501 * @brief This function is to read flash id.
502 * @param obj: Flash object define in application software.
503 * @param buf: Specified the address to save the readback data.
504 * @param len: Specifies the length of the flash id to read.
505 * @retval : The length of the flash id.
506 */
flash_read_id(flash_t * obj,uint8_t * buf,uint8_t len)507 int flash_read_id(flash_t *obj, uint8_t *buf, uint8_t len)
508 {
509 /* To avoid gcc warnings */
510 ( void ) obj;
511
512 assert_param(buf != NULL);
513 assert_param(len >= 3);
514
515 FLASH_Write_Lock();
516 FLASH_RxCmd(flash_init_para.FLASH_cmd_rd_id, len, buf);
517 FLASH_Write_Unlock();
518
519 return len;
520 }
521 /**
522 * @}
523 */
524
525 /**
526 * @}
527 */
528
529 /**
530 * @}
531 */