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   */