1 /**
2   *********************************************************************************
3   *
4   * @file    ald_flash.c
5   * @brief   FLASH module driver.
6   *
7   * @version V1.0
8   * @date    17 Jun 2019
9   * @author  AE Team
10   * @note
11   *          Change Logs:
12   *          Date            Author          Notes
13   *          17 Jun 2019     AE Team         The first version
14   *
15   * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
16   *
17   * SPDX-License-Identifier: Apache-2.0
18   *
19   * Licensed under the Apache License, Version 2.0 (the License); you may
20   * not use this file except in compliance with the License.
21   * You may obtain a copy of the License at
22   *
23   * www.apache.org/licenses/LICENSE-2.0
24   *
25   * Unless required by applicable law or agreed to in writing, software
26   * distributed under the License is distributed on an AS IS BASIS, WITHOUT
27   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28   * See the License for the specific language governing permissions and
29   * limitations under the License.
30   **********************************************************************************
31   * @verbatim
32   ==============================================================================
33                     ##### FLASH Peripheral features #####
34   ==============================================================================
35   [..]
36   Base address is 0x00000000
37 
38   [..]
39   FLASH have just one programme mode , word programme.
40   word programme can programme 8 bytes once ;
41 
42   ==============================================================================
43                         ##### How to use this driver #####
44   ==============================================================================
45   [..]
46   This driver provide private functions for ald_flash_ext.c to use
47   @endverbatim
48   */
49 
50 #include "ald_conf.h"
51 
52 
53 /** @addtogroup ES32FXXX_ALD
54   * @{
55   */
56 
57 /** @defgroup FLASH FLASH
58   * @brief FLASH module driver
59   * @{
60   */
61 
62 #ifdef ALD_FLASH
63 
64 #if defined ( __ICCARM__ )
65 #define __RAMFUNC       __ramfunc
66 #else
67 #define __RAMFUNC
68 #endif
69 
70 /** @defgroup Flash_Private_Variables Flash Private Variables
71   * @{
72   */
73 /* global variable*/
74 static op_cmd_type OP_CMD = OP_FLASH;
75 /**
76   * @}
77   */
78 
79 /** @defgroup Flash_Private_Functions Flash Private Functions
80   *  @brief   Flash Private functions
81   * @{
82   */
83 /**
84   * @brief  Unlock the flash.
85   * @retval Status, see @ref ald_status_t.
86   */
flash_unlock(void)87 __RAMFUNC static ald_status_t flash_unlock(void)
88 {
89 	uint16_t i;
90 	uint16_t op_cmd = OP_CMD;
91 
92 	if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_BUSY_MSK))
93 		return ERROR;
94 
95 	FLASH_REG_UNLOCK();
96 	FLASH_IAP_ENABLE();
97 	FLASH_REQ();
98 
99 	for (i = 0; i < 0xFFFF; i++) {
100 		if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_FLASHACK_MSK))
101 			break;
102 	}
103 
104 	return i == 0xFFFF ? ERROR : OK;
105 }
106 
107 /**
108   * @brief  Lock the flash.
109   * @retval Status, see @ref ald_status_t.
110   */
flash_lock(void)111 __RAMFUNC static ald_status_t flash_lock(void)
112 {
113 	uint16_t i;
114 	uint16_t op_cmd = OP_CMD;
115 
116 	FLASH_REG_UNLOCK();
117 	WRITE_REG(MSC->FLASHCR, 0x0);
118 
119 	for (i = 0; i < 0xFFFF; i++) {
120 		if (!(READ_BIT(MSC->FLASHSR, MSC_FLASHSR_FLASHACK_MSK)))
121 			break;
122 	}
123 
124 	return i == 0xFFFF ? ERROR : OK;
125 }
126 
127 /**
128   * @brief  Erase one page.
129   * @param  addr: The erased page's address
130   * @retval Status, see @ref ald_status_t.
131   */
flash_page_erase(uint32_t addr)132 __RAMFUNC ald_status_t flash_page_erase(uint32_t addr)
133 {
134 	uint32_t i;
135 	uint16_t op_cmd = OP_CMD;
136 
137 	if (flash_unlock() != OK)
138 		goto end;
139 
140 	if (op_cmd == OP_FLASH) {
141 		CLEAR_BIT(MSC->FLASHADDR, MSC_FLASHADDR_IFREN_MSK);
142 		MODIFY_REG(MSC->FLASHADDR, MSC_FLASHADDR_ADDR_MSK, FLASH_PAGE_ADDR(addr) << MSC_FLASHADDR_ADDR_POSS);
143 	}
144 	else {
145 		SET_BIT(MSC->FLASHADDR, MSC_FLASHADDR_IFREN_MSK);
146 		MODIFY_REG(MSC->FLASHADDR, MSC_FLASHADDR_ADDR_MSK, INFO_PAGE_ADDR(addr) << MSC_FLASHADDR_ADDR_POSS);
147 	}
148 
149 	WRITE_REG(MSC->FLASHCMD, FLASH_CMD_PE);
150 
151 	for (i = 0; i < 0xFFFF; i++) {
152 		if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_BUSY_MSK))
153 			continue;
154 		if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_ADDR_OV_MSK))
155 			goto end;
156 		if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_WRP_FLAG_MSK))
157 			goto end;
158 		if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_SERA_MSK))
159 			break;
160 	}
161 
162 	if (i == 0xFFFF)
163 		goto end;
164 
165 	if (flash_lock() == ERROR)
166 		goto end;
167 
168 	return OK;
169 end:
170 	flash_lock();
171 	return ERROR;
172 }
173 
174 /**
175   * @brief  Programme a word.
176   * @param  addr: The word's address, it is must word align.
177   * @param  data: The 8 bytes data be write.
178   * @param  len: The number of data be write.
179   * @param  fifo: Choose if use fifo.
180   * @retval Status, see @ref ald_status_t.
181   */
flash_word_program(uint32_t addr,uint32_t * data,uint32_t len,uint32_t fifo)182 __RAMFUNC ald_status_t flash_word_program(uint32_t addr, uint32_t *data, uint32_t len, uint32_t fifo)
183 {
184 	uint16_t i = 0;
185 	uint16_t prog_len;
186 	uint32_t *p_data = data;
187 	uint16_t op_cmd = OP_CMD;
188 
189 	if (flash_unlock() != OK)
190 		goto end;
191 
192 	if (op_cmd == OP_FLASH)
193 		CLEAR_BIT(MSC->FLASHADDR, MSC_FLASHADDR_IFREN_MSK);
194 	else
195 		SET_BIT(MSC->FLASHADDR, MSC_FLASHADDR_IFREN_MSK);
196 
197 	MODIFY_REG(MSC->FLASHADDR, MSC_FLASHADDR_ADDR_MSK, addr << MSC_FLASHADDR_ADDR_POSS);
198 	MODIFY_REG(MSC->FLASHCR, MSC_FLASHCR_FIFOEN_MSK, fifo << MSC_FLASHCR_FIFOEN_POS);
199 
200 	for (prog_len = 0; prog_len < len; prog_len++) {
201 		if (fifo) {
202 			WRITE_REG(MSC->FLASHFIFO, p_data[0]);
203 			WRITE_REG(MSC->FLASHFIFO, p_data[1]);
204 		}
205 		else {
206 			WRITE_REG(MSC->FLASHDL, p_data[0]);
207 			WRITE_REG(MSC->FLASHDH, p_data[1]);
208 			WRITE_REG(MSC->FLASHCMD, FLASH_CMD_WP);
209 		}
210 
211 		p_data += 2;
212 
213 		for (i = 0; i < 0xFFFF; i++) {
214 			if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_BUSY_MSK))
215 				continue;
216 			if (READ_BIT(MSC->FLASHSR, MSC_FLASHSR_PROG_MSK))
217 				break;
218 		}
219 	}
220 	if (i == 0xFFFF)
221 		goto end;
222 
223 	if (flash_lock() == ERROR)
224 		goto end;
225 
226 	return OK;
227 end:
228 	flash_lock();
229 	return ERROR;
230 }
231 /**
232   * @}
233   */
234 
235 #endif
236 
237 /**
238   * @}
239   */
240 
241 /**
242   * @}
243   */
244