1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-12-5 SummerGift first version
9 * 2019-3-2 jinsheng add Macro judgment
10 * 2020-1-6 duminmin support single bank mode
11 * 2020-5-17 yufanyufan77 support support H7
12 * 2021-3-3 zhuyf233 fix some bugs
13 */
14
15 #include <rtconfig.h>
16 #include <rtdef.h>
17
18 #ifdef BSP_USING_ON_CHIP_FLASH
19 #include "drv_config.h"
20 #include "drv_flash.h"
21 #include <board.h>
22
23 #if defined(RT_USING_FAL)
24 #include "fal.h"
25 #endif
26
27 //#define DRV_DEBUG
28 #define LOG_TAG "drv.flash"
29 #include <drv_log.h>
30
31 /**
32 * Read data from flash.
33 * @note This operation's units is word.
34 *
35 * @param addr flash address
36 * @param buf buffer to store read data
37 * @param size read bytes size
38 *
39 * @retval The length of bytes that have been read
40 */
stm32_flash_read(rt_uint32_t addr,rt_uint8_t * buf,size_t size)41 int stm32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
42 {
43 size_t i;
44
45 if ((addr + size - 1) > FLASH_END)
46 {
47 LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
48 return -RT_ERROR;
49 }
50
51 for (i = 0; i < size; i++, buf++, addr++)
52 {
53 *buf = *(rt_uint8_t *) addr;
54 }
55
56 return size;
57 }
58
59 /**
60 * Write data to flash.
61 * @note This operation's units is word.
62 * @note This operation must after erase. @see flash_erase.
63 *
64 * @param addr flash address
65 * @param buf the write data buffer
66 * @param size write bytes size
67 *
68 * @return The length of bytes that have been written
69 */
stm32_flash_write(rt_uint32_t addr,const rt_uint8_t * buf,size_t size)70 int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
71 {
72 rt_err_t result = RT_EOK;
73 rt_uint32_t end_addr = addr + size - 1, write_addr;
74 rt_uint32_t write_granularity = FLASH_NB_32BITWORD_IN_FLASHWORD * 4;
75 rt_uint32_t write_size = write_granularity;
76 rt_uint8_t write_buffer[32] = {0};
77
78 if ((end_addr) > FLASH_END)
79 {
80 LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
81 return -RT_EINVAL;
82 }
83
84 if(addr % 32 != 0)
85 {
86 LOG_E("write addr must be 32-byte alignment");
87 return -RT_EINVAL;
88 }
89
90 if (size < 1)
91 {
92 return -RT_EINVAL;
93 }
94
95 HAL_FLASH_Unlock();
96 write_addr = (uint32_t)buf;
97 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR);
98 while (addr < end_addr)
99 {
100 if(end_addr - addr + 1 < write_granularity)
101 {
102 write_size = end_addr - addr + 1;
103 for(size_t i = 0; i < write_size; i++)
104 {
105 write_buffer[i] = *((uint8_t *)(write_addr + i));
106 }
107 write_addr = (uint32_t)((rt_uint32_t *)write_buffer);
108 }
109 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, addr, write_addr) == HAL_OK)
110 {
111 for(rt_uint8_t i = 0; i < write_size; i++)
112 {
113 if (*(rt_uint8_t *)(addr + i) != *(rt_uint8_t *)(write_addr + i))
114 {
115 result = -RT_ERROR;
116 goto __exit;
117 }
118 }
119 addr += write_granularity;
120 write_addr += write_granularity;
121 }
122 else
123 {
124 result = -RT_ERROR;
125 goto __exit;
126 }
127 }
128
129 __exit:
130 HAL_FLASH_Lock();
131
132 if (result != RT_EOK)
133 {
134 return result;
135 }
136
137 return size;
138 }
139
140 /**
141 * Erase data on flash.
142 * @note This operation is irreversible.
143 * @note This operation's units is different which on many chips.
144 *
145 * @param addr flash address
146 * @param size erase bytes size
147 *
148 * @return result
149 */
stm32_flash_erase(rt_uint32_t addr,size_t size)150 int stm32_flash_erase(rt_uint32_t addr, size_t size)
151 {
152 rt_err_t result = RT_EOK;
153 rt_uint32_t SECTORError = 0;
154
155 if ((addr + size - 1) > FLASH_END)
156 {
157 LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
158 return -RT_EINVAL;
159 }
160
161 rt_uint32_t addr_bank1 = 0;
162 rt_uint32_t size_bank1 = 0;
163 #ifdef FLASH_BANK_2
164 rt_uint32_t addr_bank2 = 0;
165 rt_uint32_t size_bank2 = 0;
166 #endif
167
168 if((addr + size) < FLASH_BANK2_BASE)
169 {
170 addr_bank1 = addr;
171 size_bank1 = size;
172 #ifdef FLASH_BANK_2
173 size_bank2 = 0;
174 #endif
175 }
176 else if(addr >= FLASH_BANK2_BASE)
177 {
178 size_bank1 = 0;
179 #ifdef FLASH_BANK_2
180 addr_bank2 = addr;
181 size_bank2 = size;
182 #endif
183 }
184 else
185 {
186 addr_bank1 = addr;
187 size_bank1 = FLASH_BANK2_BASE - addr_bank1;
188 #ifdef FLASH_BANK_2
189 addr_bank2 = FLASH_BANK2_BASE;
190 size_bank2 = addr + size - FLASH_BANK2_BASE;
191 #endif
192 }
193
194 /*Variable used for Erase procedure*/
195 FLASH_EraseInitTypeDef EraseInitStruct;
196 /* Unlock the Flash to enable the flash control register access */
197 HAL_FLASH_Unlock();
198 EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
199 EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
200 SCB_DisableDCache();
201
202 if(size_bank1)
203 {
204 EraseInitStruct.Sector = (addr_bank1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE;
205 EraseInitStruct.NbSectors = (addr_bank1 + size_bank1 -1 - FLASH_BANK1_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
206 EraseInitStruct.Banks = FLASH_BANK_1;
207 if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
208 {
209 result = -RT_ERROR;
210 goto __exit;
211 }
212 }
213
214 #ifdef FLASH_BANK_2
215 if(size_bank2)
216 {
217 EraseInitStruct.Sector = (addr_bank2 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE;
218 EraseInitStruct.NbSectors = (addr_bank2 + size_bank2 -1 - FLASH_BANK2_BASE) / FLASH_SECTOR_SIZE - EraseInitStruct.Sector + 1;
219 EraseInitStruct.Banks = FLASH_BANK_2;
220 if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
221 {
222 result = -RT_ERROR;
223 goto __exit;
224 }
225 }
226 #endif
227
228 __exit:
229
230 SCB_EnableDCache();
231 HAL_FLASH_Lock();
232
233 if (result != RT_EOK)
234 {
235 return result;
236 }
237
238 LOG_D("erase done: addr (0x%p), size %d", (void *)addr, size);
239 return size;
240 }
241
242 #if defined(RT_USING_FAL)
243 static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size);
244 static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size);
245 static int fal_flash_erase_128k(long offset, size_t size);
246 const struct fal_flash_dev stm32_onchip_flash_128k = { "onchip_flash_128k", STM32_FLASH_START_ADRESS, FLASH_SIZE_GRANULARITY_128K, (128 * 1024), {NULL, fal_flash_read_128k, fal_flash_write_128k, fal_flash_erase_128k} };
247
fal_flash_read_128k(long offset,rt_uint8_t * buf,size_t size)248 static int fal_flash_read_128k(long offset, rt_uint8_t *buf, size_t size)
249 {
250 return stm32_flash_read(stm32_onchip_flash_128k.addr + offset, buf, size);
251 }
fal_flash_write_128k(long offset,const rt_uint8_t * buf,size_t size)252 static int fal_flash_write_128k(long offset, const rt_uint8_t *buf, size_t size)
253 {
254 return stm32_flash_write(stm32_onchip_flash_128k.addr + offset, buf, size);
255 }
256
fal_flash_erase_128k(long offset,size_t size)257 static int fal_flash_erase_128k(long offset, size_t size)
258 {
259 return stm32_flash_erase(stm32_onchip_flash_128k.addr + offset, size);
260 }
261
262 #endif
263 #endif /* BSP_USING_ON_CHIP_FLASH */
264