1 /**
2     *****************************************************************************
3     * @file     cmem7_flash.c
4     *
5     * @brief    CMEM7 flash controller source file
6     *
7     *
8     * @version  V1.0
9     * @date     3. September 2013
10     *
11     * @note
12     *
13     *****************************************************************************
14     * @attention
15     *
16     * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
17     * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
18     * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
19     * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
20     * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
21     * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
22     *
23     * <h2><center>&copy; COPYRIGHT 2013 Capital-micro </center></h2>
24     *****************************************************************************
25     */
26 
27 #include "cmem7_flash.h"
28 
29 typedef struct {
30   union {
31     uint16_t  STATUS;                         /*!< status register                     */
32 
33     struct {
34       uint16_t  WIP:  1;                      /*!< in writting                         */
35       uint16_t  WEL:  1;                      /*!< write enable                        */
36       uint16_t  BP:  5;                       /*!< protection region                   */
37       uint16_t  SRP:  2;                      /*!< protection mode                     */
38       uint16_t  QE:  1;                       /*!< Quad mode                           */
39     } STATUS_b;                               /*!< BitSize                             */
40   } INNER;
41 } FLASH_INNER_STATUS;
42 
43 
44 #define NS_IN_A_SECOND                            (1000000000)
45 
46 #define FLASH_MAX_SIZE                            0x800000
47 #define FLASH_PAGE_SIZE                           0x100
48 #define FLASH_SECTOR_SIZE                         0x001000
49 #define FLASH_BLOCK_32K_SIZE                      0x008000
50 #define FLASH_BLOCK_64K_SIZE                      0x010000
51 
52 #define FLASH_CMD_RD_INNER_STATUS_LOW             0x05
53 #define FLASH_CMD_RD_INNER_STATUS_HIGH            0x35
54 
55 #define FLASH_CMD_WR_WRITE_ENABLE                 0x06
56 #define FLASH_CMD_WR_WRITE_DISABLE                0x04
57 
58 #define FLASH_CME_WR_STATUS_REG                   0x01
59 
60 #define FLASH_CME_ERASE_SECTOR                    0x20
61 #define FLASH_CME_ERASE_BLOCK_32K                 0x52
62 #define FLASH_CME_ERASE_BLOCK_64K                 0xD8
63 #define FLASH_CME_ERASE_CHIP                      0xC7
64 
65 #define FLASH_CME_WR_ENTER_DEEP_PD                0xB9
66 #define FLASH_CME_WR_EXIT_DEEP_PD                 0xAB
67 
68 #define FLASH_CME_RD_NORMAL                       0x03
69 #define FLASH_CME_RD_FAST                         0x0B
70 #define FLASH_CME_RD_FAST_DUAL                    0x3B
71 #define FLASH_CME_RD_FAST_QUAD                    0x6B
72 
73 #define FLASH_CME_WR                              0x02
74 
75 typedef void (*WAIT)(void);
76 static WAIT wait;
77 
flash_setClock(uint8_t dividor)78 static void flash_setClock(uint8_t dividor) {
79     dividor = (dividor < 2) ? 2 : dividor;
80     NOR_FLASH->CTRL0_b.DIV = dividor / 2 - 1;
81 }
82 
flash_cleanOperation()83 static void flash_cleanOperation() {
84     NOR_FLASH->TRIGGER_b.OP_CLEAN = TRUE;
85     while (NOR_FLASH->STATUS_b.BUSY);
86 
87     NOR_FLASH->TRIGGER_b.OP_CLEAN = FALSE;
88     while (NOR_FLASH->STATUS_b.BUSY);
89 }
90 
flash_ReadInnerStatusLow()91 static uint8_t flash_ReadInnerStatusLow() {
92     NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 1;
93     NOR_FLASH->CTRL1_b.CMD = FLASH_CMD_RD_INNER_STATUS_LOW;
94     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
95 
96     while (NOR_FLASH->STATUS_b.BUSY);
97 
98     return (uint8_t)NOR_FLASH->DATA;
99 }
100 
flash_ReadInnerStatusHigh()101 static uint8_t flash_ReadInnerStatusHigh() {
102   NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 1;
103     NOR_FLASH->CTRL1_b.CMD = FLASH_CMD_RD_INNER_STATUS_HIGH;
104     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
105 
106     while (NOR_FLASH->STATUS_b.BUSY);
107 
108     return (uint8_t)NOR_FLASH->DATA;
109 }
110 
111 //static void flash_WaitInWritting() {
flash_WaitInWritting(void)112 void flash_WaitInWritting(void) {
113     FLASH_INNER_STATUS s;
114 
115     while (NOR_FLASH->STATUS_b.BUSY);
116 
117     do {
118         s.INNER.STATUS = flash_ReadInnerStatusLow();
119         if (!s.INNER.STATUS_b.WIP) {
120             break;
121         }
122 
123         if (wait) {
124             (*wait)();
125         }
126     } while (1);
127 }
128 
flash_WriteWriteEnable(BOOL enable)129 static void flash_WriteWriteEnable(BOOL enable) {
130   NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 0;
131     NOR_FLASH->CTRL1_b.CMD =
132       enable ? FLASH_CMD_WR_WRITE_ENABLE : FLASH_CMD_WR_WRITE_DISABLE;
133 
134     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
135 
136     flash_WaitInWritting();
137 }
138 
flash_WriteStatusReg(FLASH_INNER_STATUS * s)139 static void flash_WriteStatusReg(FLASH_INNER_STATUS *s) {
140   uint16_t tmp = s->INNER.STATUS;
141 
142     NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 2;
143     NOR_FLASH->CTRL1_b.CMD = FLASH_CME_WR_STATUS_REG;
144     NOR_FLASH->DATA = ((tmp << 8) | (tmp >> 8)) << 16;
145     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
146 
147     flash_WaitInWritting();
148 }
149 
flash_Erase(uint8_t cmd,uint32_t addr)150 static void flash_Erase(uint8_t cmd, uint32_t addr) {
151     NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 0;
152     NOR_FLASH->CTRL1_b.CMD = cmd;
153     NOR_FLASH->CTRL1_b.ADDRESS = addr;
154     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
155 
156     flash_WaitInWritting();
157 }
158 
flash_WriteDeepPowerDownEnable(BOOL enable)159 static void flash_WriteDeepPowerDownEnable(BOOL enable) {
160   NOR_FLASH->CTRL0_b.RW_BYTE_CNT = 0;
161     NOR_FLASH->CTRL1_b.CMD =
162       enable ? FLASH_CME_WR_ENTER_DEEP_PD : FLASH_CME_WR_EXIT_DEEP_PD;
163 
164     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
165 
166     flash_WaitInWritting();
167 }
168 
flash_RwReq(uint8_t cmd,uint32_t addr,uint16_t size)169 static void flash_RwReq(uint8_t cmd, uint32_t addr, uint16_t size) {
170     NOR_FLASH->CTRL0_b.RW_BYTE_CNT = size;
171     NOR_FLASH->CTRL1_b.CMD = cmd;
172     NOR_FLASH->CTRL1_b.ADDRESS = addr;
173 
174     NOR_FLASH->TRIGGER_b.OP_START = TRUE;
175 }
176 
177 //static void flash_WaitReadFifoNotEmpty() {
flash_WaitReadFifoNotEmpty(void)178 void flash_WaitReadFifoNotEmpty(void) {
179     while (NOR_FLASH->STATUS_b.RD_FIFO_EMPTY) {
180         if (wait) {
181             (*wait)();
182         }
183     }
184 }
185 
186 //static uint16_t flash_ReadFifo(uint16_t size, uint8_t* data) {
flash_ReadFifo(uint16_t size,uint8_t * data)187 uint16_t flash_ReadFifo(uint16_t size, uint8_t* data) {
188     uint16_t count = 0;
189 
190     while (!NOR_FLASH->STATUS_b.RD_FIFO_EMPTY && size != 0) {
191     uint32_t d =    NOR_FLASH->DATA;
192         if (size > 3) {
193             *(data + count++) = d >> 24;
194             *(data + count++) = (d & 0x00FF0000) >> 16;
195             *(data + count++) = (d & 0x0000FF00) >> 8;
196             *(data + count++) = (d & 0x000000FF);
197             size -= 4;
198         } else if (size == 3) {
199             *(data + count++) = (d & 0x00FF0000) >> 16;
200             *(data + count++) = (d & 0x0000FF00) >> 8;
201             *(data + count++) = (d & 0x000000FF);
202             size -= 3;
203         } else if (size == 2) {
204             *(data + count++) = (d & 0x0000FF00) >> 8;
205             *(data + count++) = (d & 0x000000FF);
206             size -= 2;
207         } else if (size == 1) {
208             *(data + count++) = (d & 0x000000FF);
209             size -= 1;
210         }
211     }
212 
213     return count;
214 }
215 
flash_WriteFifo(uint16_t size,uint8_t * data)216 static uint16_t flash_WriteFifo(uint16_t size, uint8_t* data) {
217     uint16_t count = 0;
218 
219     while (!NOR_FLASH->STATUS_b.WR_FIFO_FULL && size != 0) {
220         uint32_t d = 0;
221 
222         if (size > 3) {
223             d = *(data + count++) << 24;
224             d |= *(data + count++) << 16;
225             d |= *(data + count++) << 8;
226             d |= *(data + count++);
227             size -= 4;
228         } else if (size == 3) {
229             d = *(data + count++) << 24;
230             d |= *(data + count++) << 16;
231             d |= *(data + count++) << 8;
232             size -= 3;
233         } else if (size == 2) {
234             d = *(data + count++) << 24;
235             d |= *(data + count++) << 16;
236             size -= 2;
237         } else if (size == 1) {
238             d = *(data + count++) << 24;
239             size -= 1;
240         }
241 
242         NOR_FLASH->DATA = d;
243     }
244 
245     return count;
246 }
247 
flash_WritePage(uint32_t addr,uint16_t size,uint8_t * data)248 static uint16_t flash_WritePage(uint32_t addr, uint16_t size, uint8_t* data) {
249     uint16_t actualSize, retSize;
250 
251     flash_WriteWriteEnable(TRUE);
252 
253     actualSize = FLASH_PAGE_SIZE - (addr & (FLASH_PAGE_SIZE - 1));
254     actualSize = (size > actualSize) ? actualSize : size;
255   retSize = actualSize;
256 
257     flash_RwReq(FLASH_CME_WR, addr, actualSize);
258 
259     while (actualSize != 0) {
260         uint8_t count = flash_WriteFifo(actualSize, data);
261 
262         actualSize -= count;
263         data += count;
264     }
265 
266     flash_WaitInWritting();
267 
268     return retSize;
269 }
270 
FLASH_Init(FLASH_InitTypeDef * init)271 void FLASH_Init(FLASH_InitTypeDef* init) {
272     FLASH_INNER_STATUS s;
273 
274     assert_param(init);
275     assert_param(IS_FLASH_PROTECT_MODE(init->FLASH_ProtectMode));
276     assert_param(IS_FLASH_PROTECT_REGION(init->FLASH_ProtectRegion));
277 
278     wait = init->FLASH_Wait;
279     flash_setClock(init->FLASH_ClockDividor);
280 
281     flash_cleanOperation();
282 
283     flash_WaitInWritting();
284 
285     s.INNER.STATUS = flash_ReadInnerStatusLow();
286     s.INNER.STATUS |= ((uint16_t)flash_ReadInnerStatusHigh()) << 8;
287     s.INNER.STATUS_b.BP = init->FLASH_ProtectRegion;
288     s.INNER.STATUS_b.SRP = init->FLASH_ProtectMode;
289     s.INNER.STATUS_b.QE = init->FLASH_QuadEnable;
290 
291     flash_WriteWriteEnable(TRUE);
292     flash_WriteStatusReg(&s);
293 }
294 
FLASH_GetStatus(uint8_t * ProtectMode,uint8_t * ProtectRegion,BOOL * QuadEnable)295 void FLASH_GetStatus(uint8_t* ProtectMode, uint8_t* ProtectRegion, BOOL* QuadEnable) {
296     FLASH_INNER_STATUS s;
297 
298     assert_param(ProtectMode);
299     assert_param(ProtectRegion);
300     assert_param(QuadEnable);
301 
302     flash_WaitInWritting();
303 
304     s.INNER.STATUS = flash_ReadInnerStatusLow();
305     s.INNER.STATUS |= ((uint16_t)flash_ReadInnerStatusHigh()) << 8;
306     *ProtectRegion = s.INNER.STATUS_b.BP;
307     *ProtectMode = s.INNER.STATUS_b.SRP;
308     *QuadEnable = (s.INNER.STATUS_b.QE == 1) ?  TRUE : FALSE;
309 }
310 
FLASH_EraseSector(uint32_t addr)311 void FLASH_EraseSector(uint32_t addr) {
312     flash_WaitInWritting();
313     flash_WriteWriteEnable(TRUE);
314 
315     addr = (addr << 8) >> 8;
316     addr = addr / FLASH_SECTOR_SIZE * FLASH_SECTOR_SIZE;
317     flash_Erase(FLASH_CME_ERASE_SECTOR, addr);
318 }
319 
FLASH_Erase32kBlock(uint32_t addr)320 void FLASH_Erase32kBlock(uint32_t addr) {
321     flash_WaitInWritting();
322     flash_WriteWriteEnable(TRUE);
323 
324     addr = (addr << 8) >> 8;
325     addr = addr / FLASH_BLOCK_32K_SIZE * FLASH_BLOCK_32K_SIZE;
326     flash_Erase(FLASH_CME_ERASE_BLOCK_32K, addr);
327 }
328 
FLASH_Erase64kBlock(uint32_t addr)329 void FLASH_Erase64kBlock(uint32_t addr) {
330     flash_WaitInWritting();
331     flash_WriteWriteEnable(TRUE);
332 
333     addr = (addr << 8) >> 8;
334     addr = addr / FLASH_BLOCK_64K_SIZE * FLASH_BLOCK_64K_SIZE;
335     flash_Erase(FLASH_CME_ERASE_BLOCK_64K, addr);
336 }
337 
FLASH_EraseChip(void)338 void FLASH_EraseChip(void) {
339     flash_WaitInWritting();
340     flash_WriteWriteEnable(TRUE);
341     flash_Erase(FLASH_CME_ERASE_CHIP, 0x0);
342 }
343 
FLASH_EnableDeepPowerDown(BOOL enable)344 void FLASH_EnableDeepPowerDown(BOOL enable) {
345     flash_WaitInWritting();
346     flash_WriteWriteEnable(TRUE);
347     flash_WriteDeepPowerDownEnable(enable);
348 }
349 
FLASH_Read(uint8_t ReadMode,uint32_t addr,uint16_t size,uint8_t * data)350 void FLASH_Read(uint8_t ReadMode, uint32_t addr, uint16_t size, uint8_t* data) {
351     uint8_t cmd;
352 
353     assert_param(IS_FLASH_READ_MODE(ReadMode));
354     assert_param(addr + size <= FLASH_MAX_SIZE);
355     assert_param(data);
356 
357     if (size == 0) {
358         return ;
359     }
360 
361     flash_WaitInWritting();
362 
363     if (ReadMode == FLASH_READ_MODE_NORMAL) {
364         cmd = FLASH_CME_RD_NORMAL;
365     } else if (ReadMode == FLASH_READ_MODE_FAST) {
366         cmd = FLASH_CME_RD_FAST;
367     } else if (ReadMode == FLASH_READ_MODE_FAST_DUAL) {
368         cmd = FLASH_CME_RD_FAST_DUAL;
369     } else {
370         cmd = FLASH_CME_RD_FAST_QUAD;
371     }
372 
373     flash_RwReq(cmd, addr, size);
374 
375   while (size > 0) {
376         uint16_t count = 0;
377 
378     flash_WaitReadFifoNotEmpty();
379 
380       count = flash_ReadFifo(size, data);
381         size -= count;
382         data += count;
383     }
384 }
385 
FLASH_Write(uint32_t addr,uint16_t size,uint8_t * data)386 void FLASH_Write(uint32_t addr, uint16_t size, uint8_t* data) {
387     assert_param(addr + size <= FLASH_MAX_SIZE);
388     assert_param(data);
389 
390     flash_WaitInWritting();
391 
392     while (size > 0) {
393       uint16_t count = flash_WritePage(addr, size, data);
394 
395         addr += count;
396         size -= count;
397         data += count;
398     }
399 }
400 
401