1 /**
2   ******************************************************************************
3   * @file    tae32f53xx_ll_dflash.c
4   * @author  MCD Application Team
5   * @brief   Source file for DFLASH module.
6   *
7   ******************************************************************************
8   * @attention
9   *
10   * <h2><center>&copy; Copyright (c) 2020 Tai-Action.
11   * All rights reserved.</center></h2>
12   *
13   * This software is licensed by Tai-Action under BSD 3-Clause license,
14   * the "License"; You may not use this file except in compliance with the
15   * License. You may obtain a copy of the License at:
16   *                        opensource.org/licenses/BSD-3-Clause
17   *
18   ******************************************************************************
19   */
20 
21 /* Includes ------------------------------------------------------------------*/
22 #include "tae32f53xx_ll.h"
23 
24 
25 #define DBG_TAG             "DFLASH LL"
26 #define DBG_LVL             DBG_ERROR
27 #include "dbg/tae32f53xx_dbg.h"
28 
29 
30 /** @addtogroup TAE32F53xx_LL_Driver
31   * @{
32   */
33 
34 /** @defgroup DFLASH_LL DFLASH LL
35   * @brief    DFLASH LL module driver
36   * @{
37   */
38 
39 #ifdef LL_DFLASH_MODULE_ENABLED
40 
41 /* Private define ------------------------------------------------------------*/
42 /* Private macro -------------------------------------------------------------*/
43 /* Private typedef -----------------------------------------------------------*/
44 /* Private variables ---------------------------------------------------------*/
45 /* Private function prototypes -----------------------------------------------*/
46 /* Exported functions --------------------------------------------------------*/
47 /** @defgroup DFLASH_LL_Exported_Functions DFLASH LL Exported Functions
48   * @brief    DFLASH LL Exported Functions
49   * @{
50   */
51 
52 /** @defgroup DFLASH_LL_Exported_Functions_Group1 DFLASH Peripheral State functions
53   * @brief    DFLASH Peripheral State functions
54 @verbatim
55   ===============================================================================
56                        ##### Peripheral State functions #####
57   ===============================================================================
58   [..]
59     This section provides functions allowing to:
60     (+) Peripheral State functions
61 
62 @endverbatim
63   * @{
64   */
65 
66 /**
67   * @brief  Wait for a DFLASH operation to complete.
68   * @param  Timeout Maximum DataFlash operation timeout
69   * @return LL Status
70   */
LL_DFLASH_WaitForLastOperation(uint32_t Timeout)71 LL_StatusETypeDef LL_DFLASH_WaitForLastOperation(uint32_t Timeout)
72 {
73     uint32_t tickstart = LL_GetTick();
74 
75     /* Wait for the DFLASH operation to complete by polling on BUSY flag to be reset.
76        Even if the DFLASH operation fails, the BUSY flag will be reset and an error
77        flag will be set */
78     while (__LL_DFLASH_STATUS_FLAG_GET(DFLASH_FLAG_BSY) != RESET) {
79         if (Timeout != LL_WAIT_FOREVER) {
80             if ((Timeout == 0U) || ((LL_GetTick() - tickstart) > Timeout)) {
81                 return LL_TIMEOUT;
82             }
83         }
84     }
85 
86     /* Check and clear DIF flag */
87     if (__LL_DFLASH_PENDING_FLAG_GET(DFLASH_FLAG_DIF) != RESET) {
88         __LL_DFLASH_PENDING_FLAG_CLEAR(DFLASH_FLAG_DIF);
89     }
90 
91     /* Check if any errors occurred */
92     if (__LL_DFLASH_PENDING_FLAG_GET(DFLASH_FLAG_EIF) != RESET) {
93         return LL_ERROR;
94     }
95 
96     /* Return function status */
97     return LL_OK;
98 }
99 
100 /**
101   * @}
102   */
103 
104 
105 /** @defgroup DFLASH_LL_Exported_Functions_Group2 DFLASH Input and Output operation functions
106   * @brief    DFLASH Input and Output operation functions
107 @verbatim
108   ===============================================================================
109                   ##### Input and Output operation functions #####
110   ===============================================================================
111   [..]
112     This section provides functions allowing to:
113     (+) Byte/Word Program operations functions
114     (+) Byte/Word Read operations functions
115     (+) Erase operations functions
116 
117 @endverbatim
118   * @{
119   */
120 
121 /**
122   * @brief  Program one byte at a specified address.
123   * @param  Address specifies the address to be programmed.
124   * @param  Data specifies the data to be programmed.
125   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
126   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
127   * @return LL Status
128   */
LL_DFLASH_Program_Byte(uint32_t Address,uint8_t Data)129 LL_StatusETypeDef LL_DFLASH_Program_Byte(uint32_t Address, uint8_t Data)
130 {
131     LL_StatusETypeDef status = LL_OK;
132 
133     /* Check the parameters */
134     assert_param(IS_DFLASH_ADDRESS_MASK(Address));
135 
136     /* Address mask */
137     Address &= DFLASH_PROGRAM_ADDRESS_MASK;
138 
139     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
140         /* Byte Program mode */
141         CLEAR_BIT(DFLASH->CR, DFLASH_CR_DS);
142 
143         /* Fill the data into DFLASH_DR register */
144         WRITE_REG(DFLASH->DR, Data);
145 
146         /* Set Address */
147         WRITE_REG(DFLASH->ADDR, Address);
148 
149         /* Ignore full 0xFF data programming */
150         if ((DFLASH->DR & 0xFF) != 0xFFU) {
151             /* Pragram Start */
152             SET_BIT(DFLASH->CR, DFLASH_CR_PS);
153 
154             /* Wait until operation complete */
155             status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE);
156         }
157     }
158 
159     /* Return function status */
160     return status;
161 }
162 
163 /**
164   * @brief  Program one word at a specified address.
165   * @param  Address specifies the address to be programmed.
166   *         Notice that address must align to a word
167   * @param  Data specifies the data to be programmed.
168   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
169   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
170   * @return LL Status
171   */
LL_DFLASH_Program_Word(uint32_t Address,uint32_t Data)172 LL_StatusETypeDef LL_DFLASH_Program_Word(uint32_t Address, uint32_t Data)
173 {
174     LL_StatusETypeDef status = LL_OK;
175 
176     /* Check the parameters */
177     assert_param(IS_DFLASH_ADDRESS_MASK(Address));
178     assert_param(IS_DFLASH_ADDRESS_CHECK_ALIGN(Address));
179 
180     /* Address mask */
181     Address &= DFLASH_PROGRAM_ADDRESS_MASK;
182 
183     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
184         /* Byte Program mode */
185         SET_BIT(DFLASH->CR, DFLASH_CR_DS);
186 
187         /* Fill the data into DFLASH_DR register */
188         WRITE_REG(DFLASH->DR, Data);
189 
190         /* Set Address */
191         WRITE_REG(DFLASH->ADDR, Address);
192 
193         /* Ignore full 0xFF data programming */
194         if (DFLASH->DR != 0xFFFFFFFFU) {
195             /* Pragram Start */
196             SET_BIT(DFLASH->CR, DFLASH_CR_PS);
197 
198             /* Wait until operation complete */
199             status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE);
200         }
201     }
202 
203     /* Return function status */
204     return status;
205 }
206 
207 /**
208   * @brief  Read one byte from a specified address.
209   * @param  Address specifies the address to read.
210   * @param  Data specifies the data pointer to read in.
211   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
212   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
213   * @return LL Status
214   */
LL_DFLASH_Read_Byte(uint32_t Address,uint8_t * Data)215 LL_StatusETypeDef LL_DFLASH_Read_Byte(uint32_t Address, uint8_t *Data)
216 {
217     LL_StatusETypeDef status = LL_OK;
218 
219     /* Check the parameters */
220     assert_param(IS_DFLASH_ADDRESS_MASK(Address));
221 
222     /* Address mask */
223     Address &= DFLASH_PROGRAM_ADDRESS_MASK;
224     /* Initialize the value of Data */
225     *Data    = 0;
226 
227     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
228         /* Byte Read mode */
229         CLEAR_BIT(DFLASH->CR, DFLASH_CR_DS);
230 
231         /* Set Address */
232         WRITE_REG(DFLASH->ADDR, Address);
233 
234         /* Read Start */
235         SET_BIT(DFLASH->CR, DFLASH_CR_RS);
236 
237         /* Wait until operation complete */
238         if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
239             /* Read the data from DFLASH->DR Registers */
240             *Data = READ_REG(DFLASH->DR) & 0xFFU;
241         }
242     }
243 
244     /* Return function status */
245     return status;
246 }
247 
248 /**
249   * @brief  Read one wrod from a specified address.
250   * @param  Address specifies the address to read.
251   *         Notice that address must align to a word
252   * @param  Data specifies the data pointer to read in.
253   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
254   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
255   * @return LL Status
256   */
LL_DFLASH_Read_Word(uint32_t Address,uint32_t * Data)257 LL_StatusETypeDef LL_DFLASH_Read_Word(uint32_t Address, uint32_t *Data)
258 {
259     LL_StatusETypeDef status = LL_OK;
260 
261     /* Check the parameters */
262     assert_param(IS_DFLASH_ADDRESS_MASK(Address));
263     assert_param(IS_DFLASH_ADDRESS_CHECK_ALIGN(Address));
264 
265     /* Address mask */
266     Address &= DFLASH_PROGRAM_ADDRESS_MASK;
267     /* Initialize the value of Data */
268     *Data    = 0;
269 
270     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
271         /* Byte Read mode */
272         CLEAR_BIT(DFLASH->CR, DFLASH_CR_DS);
273 
274         /* Set Address */
275         WRITE_REG(DFLASH->ADDR, Address);
276 
277         /* Read Start */
278         SET_BIT(DFLASH->CR, DFLASH_CR_RS);
279 
280         /* Wait until operation complete */
281         if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
282             /* Read the data from DFLASH->DR Registers */
283             *Data = READ_REG(DFLASH->DR);
284         }
285     }
286 
287     /* Return function status */
288     return status;
289 }
290 
291 /**
292   * @brief  DFLASH mass erase. This will mass erase the Main-Memory area.
293   * @note   Please Notice this function has no effect to the Secondary-Memory.
294   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
295   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
296   * @return LL Status
297   */
LL_DFLASH_MassErase(void)298 LL_StatusETypeDef LL_DFLASH_MassErase(void)
299 {
300     LL_StatusETypeDef status = LL_OK;
301 
302     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
303         /* Set to Mass Erase mode */
304         SET_BIT(DFLASH->ECR, DFLASH_ECR_EMODE);
305 
306         /* Erase Start */
307         SET_BIT(DFLASH->CR, DFLASH_CR_ES);
308 
309         /* Wait until operation complete */
310         status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE);
311     }
312 
313     /* Return function status */
314     return status;
315 }
316 
317 /**
318   * @brief  Erase one specified DFLASH memory sector. This function is effective for both
319   *         Main-Memory and Secondary-Memory areas.
320   * @param  sector The start sector number of the specified sectors to erase.
321   *         This parameter must be a value between 0 and (NB of sectors - 1)
322   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
323   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
324   * @return Status
325   */
LL_DFLASH_SectorErase(uint16_t Sector)326 LL_StatusETypeDef LL_DFLASH_SectorErase(uint16_t Sector)
327 {
328     LL_StatusETypeDef status = LL_OK;
329 
330     /* Check the parameters */
331     assert_param(IS_DFLASH_NB_SECTORS(Sector));
332 
333     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
334         /* Set to Sector Erase mode */
335         CLEAR_BIT(DFLASH->ECR, DFLASH_ECR_EMODE);
336 
337         /* Set Sector to erase */
338         MODIFY_REG(DFLASH->ECR, DFLASH_ECR_ESNB_Msk, Sector);
339 
340         /* Erase Start */
341         SET_BIT(DFLASH->CR, DFLASH_CR_ES);
342 
343         /* Wait until operation complete */
344         status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE);
345     }
346 
347     /* Return function status */
348     return status;
349 }
350 
351 /**
352   * @brief  Erase the specified DFLASH memory multiple sectors.
353   * @param  sector The start sector number of the specified sectors to erase.
354   *         This parameter must be a value between 0 and (NB of sectors - 1)
355   * @param  num Number of sectors to be erased.
356   *         This parameter must be a value between 1 and NB of sectors
357   * @note   Please notice that all specified sectors number must between 0 and (NB of sectors - 1)
358   * @param  *SectorError Pointer to variable that contains the configuration information on faulty
359   *         sector in case of error (0xFFFF means that all the sectors have been correctly erased).
360   *         Set this pointer to NULL if you do not need it.
361   * @note   LL_DFLASH_Unlock() should be called before to unlock the DFLASH interface
362   *         LL_DFLASH_Lock() should be called after to lock the DFLASH interface
363   * @return LL Status
364   */
LL_DFLASH_MultiSectorsErase(uint16_t Sector,uint16_t Num,uint16_t * SectorError)365 LL_StatusETypeDef LL_DFLASH_MultiSectorsErase(uint16_t Sector, uint16_t Num, uint16_t *SectorError)
366 {
367     LL_StatusETypeDef status = LL_OK;
368 
369     assert_param(Num != 0);
370     assert_param(IS_DFLASH_NB_SECTORS(Sector));
371     assert_param(IS_DFLASH_NB_SECTORS(Sector + Num - 1));
372 
373     if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) == LL_OK) {
374         /*Initialization of SectorError variable*/
375         if (SectorError != NULL) {
376             *SectorError = 0xFFFF;
377         }
378 
379         /* Set to Sector Erase mode */
380         CLEAR_BIT(DFLASH->ECR, DFLASH_ECR_EMODE);
381 
382         /* Erase the specified sectors */
383         for (uint16_t index = Sector; index < (Sector + Num); index++) {
384             /* Set current Sector to erase */
385             MODIFY_REG(DFLASH->ECR, DFLASH_ECR_ESNB_Msk, index);
386 
387             /* Erase Start */
388             SET_BIT(DFLASH->CR, DFLASH_CR_ES);
389 
390             /* Wait until operation complete */
391             if ((status = LL_DFLASH_WaitForLastOperation(DFLASH_TIMEOUT_MAX_VALUE)) != LL_OK) {
392                 /* In case of error, stop erase procedure and return the faulty Sector */
393                 if (SectorError != NULL) {
394                     *SectorError = index;
395                 }
396 
397                 break;
398             }
399         }
400     }
401 
402     /* Return function status */
403     return status;
404 }
405 
406 /**
407   * @}
408   */
409 
410 /**
411   * @}
412   */
413 
414 
415 /* Private functions ---------------------------------------------------------*/
416 
417 
418 #endif /* LL_DFLASH_MODULE_ENABLED */
419 
420 
421 /**
422   * @}
423   */
424 
425 /**
426   * @}
427   */
428 
429 
430 /************************* (C) COPYRIGHT Tai-Action *****END OF FILE***********/
431 
432