1 /**
2   ******************************************************************************
3   * @file    stm32f2xx_hal_pccard.c
4   * @author  MCD Application Team
5   * @brief   PCCARD HAL module driver.
6   *          This file provides a generic firmware to drive PCCARD memories mounted
7   *          as external device.
8   *
9   ******************************************************************************
10   * @attention
11   *
12   * Copyright (c) 2016 STMicroelectronics.
13   * All rights reserved.
14   *
15   * This software is licensed under terms that can be found in the LICENSE file
16   * in the root directory of this software component.
17   * If no LICENSE file comes with this software, it is provided AS-IS.
18   *
19   ******************************************************************************
20   @verbatim
21  ===============================================================================
22                         ##### How to use this driver #####
23  ===============================================================================
24    [..]
25      This driver is a generic layered driver which contains a set of APIs used to
26       control PCCARD/compact flash memories. It uses the FSMC layer functions
27      to interface with PCCARD devices. This driver is used for:
28 
29     (+) PCCARD/Compact Flash memory configuration sequence using the function
30         HAL_PCCARD_Init()/HAL_CF_Init() with control and timing parameters for
31         both common and attribute spaces.
32 
33     (+) Read PCCARD/Compact Flash memory maker and device IDs using the function
34         HAL_PCCARD_Read_ID()/HAL_CF_Read_ID(). The read information is stored in
35         the CompactFlash_ID structure declared by the function caller.
36 
37     (+) Access PCCARD/Compact Flash memory by read/write operations using the functions
38         HAL_PCCARD_Read_Sector()/ HAL_PCCARD_Write_Sector() -
39         HAL_CF_Read_Sector()/HAL_CF_Write_Sector(), to read/write sector.
40 
41     (+) Perform PCCARD/Compact Flash Reset chip operation using the function
42         HAL_PCCARD_Reset()/HAL_CF_Reset.
43 
44     (+) Perform PCCARD/Compact Flash erase sector operation using the function
45         HAL_PCCARD_Erase_Sector()/HAL_CF_Erase_Sector.
46 
47     (+) Read the PCCARD/Compact Flash status operation using the function
48         HAL_PCCARD_ReadStatus()/HAL_CF_ReadStatus().
49 
50     (+) You can monitor the PCCARD/Compact Flash  device HAL state by calling
51         the function HAL_PCCARD_GetState()/HAL_CF_GetState()
52 
53    [..]
54      (@) This driver is a set of generic APIs which handle standard PCCARD/compact flash
55          operations. If a PCCARD/Compact Flash device contains different operations
56          and/or implementations, it should be implemented separately.
57 
58       *** Callback registration ***
59     =============================================
60     [..]
61       The compilation define  USE_HAL_PCCARD_REGISTER_CALLBACKS when set to 1
62       allows the user to configure dynamically the driver callbacks.
63 
64       Use Functions HAL_PCCARD_RegisterCallback() to register a user callback,
65       it allows to register following callbacks:
66         (+) MspInitCallback    : PCCARD MspInit.
67         (+) MspDeInitCallback  : PCCARD MspDeInit.
68       This function takes as parameters the HAL peripheral handle, the Callback ID
69       and a pointer to the user callback function.
70 
71       Use function HAL_PCCARD_UnRegisterCallback() to reset a callback to the default
72       weak (surcharged) function. It allows to reset following callbacks:
73         (+) MspInitCallback    : PCCARD MspInit.
74         (+) MspDeInitCallback  : PCCARD MspDeInit.
75       This function) takes as parameters the HAL peripheral handle and the Callback ID.
76 
77       By default, after the HAL_PCCARD_Init and if the state is HAL_PCCARD_STATE_RESET
78       all callbacks are reset to the corresponding legacy weak (surcharged) functions.
79       Exception done for MspInit and MspDeInit callbacks that are respectively
80       reset to the legacy weak (surcharged) functions in the HAL_PCCARD_Init
81       and  HAL_PCCARD_DeInit only when these callbacks are null (not registered beforehand).
82       If not, MspInit or MspDeInit are not null, the HAL_PCCARD_Init and HAL_PCCARD_DeInit
83       keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
84 
85       Callbacks can be registered/unregistered in READY state only.
86       Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
87       in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
88       during the Init/DeInit.
89       In that case first register the MspInit/MspDeInit user callbacks
90       using HAL_PCCARD_RegisterCallback before calling HAL_PCCARD_DeInit
91       or HAL_PCCARD_Init function.
92 
93       When The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS is set to 0 or
94       not defined, the callback registering feature is not available
95       and weak (surcharged) callbacks are used.
96 
97   @endverbatim
98   ******************************************************************************
99   */
100 
101 /* Includes ------------------------------------------------------------------*/
102 #include "stm32f2xx_hal.h"
103 
104 
105 /** @addtogroup STM32F2xx_HAL_Driver
106   * @{
107   */
108 
109 #ifdef HAL_PCCARD_MODULE_ENABLED
110 
111 /** @defgroup PCCARD PCCARD
112   * @brief PCCARD HAL module driver
113   * @{
114   */
115 /* Private typedef -----------------------------------------------------------*/
116 /* Private define ------------------------------------------------------------*/
117 
118 /** @defgroup PCCARD_Private_Defines PCCARD Private Defines
119   * @{
120   */
121 #define PCCARD_TIMEOUT_READ_ID                 0x0000FFFFU
122 #define PCCARD_TIMEOUT_READ_WRITE_SECTOR       0x0000FFFFU
123 #define PCCARD_TIMEOUT_ERASE_SECTOR            0x00000400U
124 #define PCCARD_TIMEOUT_STATUS                  0x01000000U
125 
126 #define PCCARD_STATUS_OK                       (uint8_t)0x58
127 #define PCCARD_STATUS_WRITE_OK                 (uint8_t)0x50
128 /**
129   * @}
130   */
131 
132 /* Private macro -------------------------------------------------------------*/
133 /* Private variables ---------------------------------------------------------*/
134 /* Private function ----------------------------------------------------------*/
135 /* Exported functions --------------------------------------------------------*/
136 /** @defgroup PCCARD_Exported_Functions PCCARD Exported Functions
137   * @{
138   */
139 
140 /** @defgroup PCCARD_Exported_Functions_Group1 Initialization and de-initialization functions
141   * @brief    Initialization and Configuration functions
142   *
143   @verbatim
144   ==============================================================================
145           ##### PCCARD Initialization and de-initialization functions #####
146   ==============================================================================
147   [..]
148     This section provides functions allowing to initialize/de-initialize
149     the PCCARD memory
150 
151 @endverbatim
152   * @{
153   */
154 
155 /**
156   * @brief  Perform the PCCARD memory Initialization sequence
157   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
158   *                the configuration information for PCCARD module.
159   * @param  ComSpaceTiming Common space timing structure
160   * @param  AttSpaceTiming Attribute space timing structure
161   * @param  IOSpaceTiming IO space timing structure
162   * @retval HAL status
163   */
HAL_PCCARD_Init(PCCARD_HandleTypeDef * hpccard,FSMC_NAND_PCC_TimingTypeDef * ComSpaceTiming,FSMC_NAND_PCC_TimingTypeDef * AttSpaceTiming,FSMC_NAND_PCC_TimingTypeDef * IOSpaceTiming)164 HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FSMC_NAND_PCC_TimingTypeDef *ComSpaceTiming,
165                                   FSMC_NAND_PCC_TimingTypeDef *AttSpaceTiming,
166                                   FSMC_NAND_PCC_TimingTypeDef *IOSpaceTiming)
167 {
168   /* Check the PCCARD controller state */
169   if (hpccard == NULL)
170   {
171     return HAL_ERROR;
172   }
173 
174   if (hpccard->State == HAL_PCCARD_STATE_RESET)
175   {
176     /* Allocate lock resource and initialize it */
177     hpccard->Lock = HAL_UNLOCKED;
178 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
179     if (hpccard->MspInitCallback == NULL)
180     {
181       hpccard->MspInitCallback = HAL_PCCARD_MspInit;
182     }
183     hpccard->ItCallback = HAL_PCCARD_ITCallback;
184 
185     /* Init the low level hardware */
186     hpccard->MspInitCallback(hpccard);
187 #else
188     /* Initialize the low level hardware (MSP) */
189     HAL_PCCARD_MspInit(hpccard);
190 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
191   }
192 
193   /* Initialize the PCCARD state */
194   hpccard->State = HAL_PCCARD_STATE_BUSY;
195 
196   /* Initialize PCCARD control Interface */
197   FSMC_PCCARD_Init(hpccard->Instance, &(hpccard->Init));
198 
199   /* Init PCCARD common space timing Interface */
200   FSMC_PCCARD_CommonSpace_Timing_Init(hpccard->Instance, ComSpaceTiming);
201 
202   /* Init PCCARD attribute space timing Interface */
203   FSMC_PCCARD_AttributeSpace_Timing_Init(hpccard->Instance, AttSpaceTiming);
204 
205   /* Init PCCARD IO space timing Interface */
206   FSMC_PCCARD_IOSpace_Timing_Init(hpccard->Instance, IOSpaceTiming);
207 
208   /* Enable the PCCARD device */
209   __FSMC_PCCARD_ENABLE(hpccard->Instance);
210 
211   /* Update the PCCARD state */
212   hpccard->State = HAL_PCCARD_STATE_READY;
213 
214   return HAL_OK;
215 
216 }
217 
218 /**
219   * @brief  Perform the PCCARD memory De-initialization sequence
220   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
221   *                the configuration information for PCCARD module.
222   * @retval HAL status
223   */
HAL_PCCARD_DeInit(PCCARD_HandleTypeDef * hpccard)224 HAL_StatusTypeDef  HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard)
225 {
226 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
227   if (hpccard->MspDeInitCallback == NULL)
228   {
229     hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
230   }
231 
232   /* DeInit the low level hardware */
233   hpccard->MspDeInitCallback(hpccard);
234 #else
235   /* De-Initialize the low level hardware (MSP) */
236   HAL_PCCARD_MspDeInit(hpccard);
237 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
238 
239   /* Configure the PCCARD registers with their reset values */
240   FSMC_PCCARD_DeInit(hpccard->Instance);
241 
242   /* Update the PCCARD controller state */
243   hpccard->State = HAL_PCCARD_STATE_RESET;
244 
245   /* Release Lock */
246   __HAL_UNLOCK(hpccard);
247 
248   return HAL_OK;
249 }
250 
251 /**
252   * @brief  PCCARD MSP Init
253   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
254   *                the configuration information for PCCARD module.
255   * @retval None
256   */
HAL_PCCARD_MspInit(PCCARD_HandleTypeDef * hpccard)257 __weak void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard)
258 {
259   /* Prevent unused argument(s) compilation warning */
260   UNUSED(hpccard);
261   /* NOTE : This function Should not be modified, when the callback is needed,
262             the HAL_PCCARD_MspInit could be implemented in the user file
263    */
264 }
265 
266 /**
267   * @brief  PCCARD MSP DeInit
268   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
269   *                the configuration information for PCCARD module.
270   * @retval None
271   */
HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef * hpccard)272 __weak void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard)
273 {
274   /* Prevent unused argument(s) compilation warning */
275   UNUSED(hpccard);
276   /* NOTE : This function Should not be modified, when the callback is needed,
277             the HAL_PCCARD_MspDeInit could be implemented in the user file
278    */
279 }
280 
281 /**
282   * @}
283   */
284 
285 /** @defgroup PCCARD_Exported_Functions_Group2 Input and Output functions
286   * @brief    Input Output and memory control functions
287   *
288   @verbatim
289   ==============================================================================
290                     ##### PCCARD Input and Output functions #####
291   ==============================================================================
292   [..]
293     This section provides functions allowing to use and control the PCCARD memory
294 
295 @endverbatim
296   * @{
297   */
298 
299 /**
300   * @brief  Read Compact Flash's ID.
301   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
302   *                the configuration information for PCCARD module.
303   * @param  CompactFlash_ID Compact flash ID structure.
304   * @param  pStatus pointer to compact flash status
305   * @retval HAL status
306   *
307   */
HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef * hpccard,uint8_t CompactFlash_ID[],uint8_t * pStatus)308 HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus)
309 {
310   uint32_t timeout = 0U;
311   uint32_t index = 0U;
312   uint8_t status = 0U;
313 
314   /* Process Locked */
315   __HAL_LOCK(hpccard);
316 
317   /* Check the PCCARD controller state */
318   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
319   {
320     return HAL_BUSY;
321   }
322 
323   /* Initialize timeout value */
324   timeout = PCCARD_TIMEOUT_READ_ID;
325 
326   /* Update the PCCARD controller state */
327   hpccard->State = HAL_PCCARD_STATE_BUSY;
328 
329   /* Initialize the PCCARD status */
330   *pStatus = PCCARD_READY;
331 
332   /* Send the Identify Command */
333   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)  = (uint16_t)0xECEC;
334 
335   /* Read PCCARD IDs and timeout treatment */
336   do
337   {
338     /* Read the PCCARD status */
339     status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
340 
341     timeout--;
342   } while ((status != PCCARD_STATUS_OK) && timeout);
343 
344   if (timeout == 0U)
345   {
346     *pStatus = PCCARD_TIMEOUT_ERROR;
347   }
348   else
349   {
350     /* Read PCCARD ID bytes */
351     for (index = 0U; index < 16U; index++)
352     {
353       CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA);
354     }
355   }
356 
357   /* Update the PCCARD controller state */
358   hpccard->State = HAL_PCCARD_STATE_READY;
359 
360   /* Process unlocked */
361   __HAL_UNLOCK(hpccard);
362 
363   return HAL_OK;
364 }
365 
366 /**
367   * @brief  Read sector from PCCARD memory
368   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
369   *                the configuration information for PCCARD module.
370   * @param  pBuffer pointer to destination read buffer
371   * @param  SectorAddress Sector address to read
372   * @param  pStatus pointer to PCCARD status
373   * @retval HAL status
374   */
HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)375 HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
376                                          uint8_t *pStatus)
377 {
378   uint32_t timeout = 0U;
379   uint32_t index = 0U;
380   uint8_t status = 0U;
381 
382   /* Process Locked */
383   __HAL_LOCK(hpccard);
384 
385   /* Check the PCCARD controller state */
386   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
387   {
388     return HAL_BUSY;
389   }
390 
391   /* Initialize timeout value */
392   timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
393 
394   /* Update the PCCARD controller state */
395   hpccard->State = HAL_PCCARD_STATE_BUSY;
396 
397   /* Initialize PCCARD status */
398   *pStatus = PCCARD_READY;
399 
400   /* Set the parameters to write a sector */
401   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
402   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
403   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0xE4A0;
404 
405   do
406   {
407     /* wait till the Status = 0x80 */
408     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
409     timeout--;
410   } while ((status == 0x80U) && timeout);
411 
412   if (timeout == 0U)
413   {
414     *pStatus = PCCARD_TIMEOUT_ERROR;
415   }
416 
417   timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
418 
419   do
420   {
421     /* wait till the Status = PCCARD_STATUS_OK */
422     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
423     timeout--;
424   } while ((status != PCCARD_STATUS_OK) && timeout);
425 
426   if (timeout == 0U)
427   {
428     *pStatus = PCCARD_TIMEOUT_ERROR;
429   }
430 
431   /* Read bytes */
432   for (; index < PCCARD_SECTOR_SIZE; index++)
433   {
434     *(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR);
435   }
436 
437   /* Update the PCCARD controller state */
438   hpccard->State = HAL_PCCARD_STATE_READY;
439 
440   /* Process unlocked */
441   __HAL_UNLOCK(hpccard);
442 
443   return HAL_OK;
444 }
445 
446 
447 /**
448   * @brief  Write sector to PCCARD memory
449   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
450   *                the configuration information for PCCARD module.
451   * @param  pBuffer pointer to source write buffer
452   * @param  SectorAddress Sector address to write
453   * @param  pStatus pointer to PCCARD status
454   * @retval HAL status
455   */
HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)456 HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
457                                           uint8_t *pStatus)
458 {
459   uint32_t timeout = 0U;
460   uint32_t index = 0U;
461   uint8_t status = 0U;
462 
463   /* Process Locked */
464   __HAL_LOCK(hpccard);
465 
466   /* Check the PCCARD controller state */
467   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
468   {
469     return HAL_BUSY;
470   }
471 
472   /* Initialize timeout value */
473   timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
474 
475   /* Update the PCCARD controller state */
476   hpccard->State = HAL_PCCARD_STATE_BUSY;
477 
478   /* Initialize PCCARD status */
479   *pStatus = PCCARD_READY;
480 
481   /* Set the parameters to write a sector */
482   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
483   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
484   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0x30A0;
485 
486   do
487   {
488     /* Wait till the Status = PCCARD_STATUS_OK */
489     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
490     timeout--;
491   } while ((status != PCCARD_STATUS_OK) && timeout);
492 
493   if (timeout == 0U)
494   {
495     *pStatus = PCCARD_TIMEOUT_ERROR;
496   }
497 
498   /* Write bytes */
499   for (; index < PCCARD_SECTOR_SIZE; index++)
500   {
501     *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++;
502   }
503 
504   do
505   {
506     /* Wait till the Status = PCCARD_STATUS_WRITE_OK */
507     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
508     timeout--;
509   } while ((status != PCCARD_STATUS_WRITE_OK) && timeout);
510 
511   if (timeout == 0U)
512   {
513     *pStatus = PCCARD_TIMEOUT_ERROR;
514   }
515 
516   /* Update the PCCARD controller state */
517   hpccard->State = HAL_PCCARD_STATE_READY;
518 
519   /* Process unlocked */
520   __HAL_UNLOCK(hpccard);
521 
522   return HAL_OK;
523 }
524 
525 
526 /**
527   * @brief  Erase sector from PCCARD memory
528   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
529   *                the configuration information for PCCARD module.
530   * @param  SectorAddress Sector address to erase
531   * @param  pStatus pointer to PCCARD status
532   * @retval HAL status
533   */
HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t SectorAddress,uint8_t * pStatus)534 HAL_StatusTypeDef  HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus)
535 {
536   uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR;
537   uint8_t status = 0U;
538 
539   /* Process Locked */
540   __HAL_LOCK(hpccard);
541 
542   /* Check the PCCARD controller state */
543   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
544   {
545     return HAL_BUSY;
546   }
547 
548   /* Update the PCCARD controller state */
549   hpccard->State = HAL_PCCARD_STATE_BUSY;
550 
551   /* Initialize PCCARD status */
552   *pStatus = PCCARD_READY;
553 
554   /* Set the parameters to write a sector */
555   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW)  = 0x00;
556   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00;
557   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress;
558   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = 0x01;
559   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD)     = 0xA0;
560   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = ATA_ERASE_SECTOR_CMD;
561 
562   /* wait till the PCCARD is ready */
563   status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
564 
565   while ((status != PCCARD_STATUS_WRITE_OK) && timeout)
566   {
567     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
568     timeout--;
569   }
570 
571   if (timeout == 0U)
572   {
573     *pStatus = PCCARD_TIMEOUT_ERROR;
574   }
575 
576   /* Check the PCCARD controller state */
577   hpccard->State = HAL_PCCARD_STATE_READY;
578 
579   /* Process unlocked */
580   __HAL_UNLOCK(hpccard);
581 
582   return HAL_OK;
583 }
584 
585 /**
586   * @brief  Reset the PCCARD memory
587   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
588   *                the configuration information for PCCARD module.
589   * @retval HAL status
590   */
HAL_PCCARD_Reset(PCCARD_HandleTypeDef * hpccard)591 HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard)
592 {
593   /* Process Locked */
594   __HAL_LOCK(hpccard);
595 
596   /* Check the PCCARD controller state */
597   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
598   {
599     return HAL_BUSY;
600   }
601 
602   /* Provide a SW reset and Read and verify the:
603    - PCCard Configuration Option Register at address 0x98000200 --> 0x80
604    - Card Configuration and Status Register at address 0x98000202 --> 0x00
605    - Pin Replacement Register at address 0x98000204 --> 0x0C
606    - Socket and Copy Register at address 0x98000206 --> 0x00
607   */
608 
609   /* Check the PCCARD controller state */
610   hpccard->State = HAL_PCCARD_STATE_BUSY;
611 
612   *(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01;
613 
614   /* Check the PCCARD controller state */
615   hpccard->State = HAL_PCCARD_STATE_READY;
616 
617   /* Process unlocked */
618   __HAL_UNLOCK(hpccard);
619 
620   return HAL_OK;
621 }
622 
623 /**
624   * @brief  This function handles PCCARD device interrupt request.
625   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
626   *                the configuration information for PCCARD module.
627   * @retval HAL status
628   */
HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef * hpccard)629 void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard)
630 {
631   /* Check PCCARD interrupt Rising edge flag */
632   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE))
633   {
634     /* PCCARD interrupt callback*/
635 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
636     hpccard->ItCallback(hpccard);
637 #else
638     HAL_PCCARD_ITCallback(hpccard);
639 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
640 
641     /* Clear PCCARD interrupt Rising edge pending bit */
642     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE);
643   }
644 
645   /* Check PCCARD interrupt Level flag */
646   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL))
647   {
648     /* PCCARD interrupt callback*/
649 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
650     hpccard->ItCallback(hpccard);
651 #else
652     HAL_PCCARD_ITCallback(hpccard);
653 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
654 
655     /* Clear PCCARD interrupt Level pending bit */
656     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL);
657   }
658 
659   /* Check PCCARD interrupt Falling edge flag */
660   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE))
661   {
662     /* PCCARD interrupt callback*/
663 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
664     hpccard->ItCallback(hpccard);
665 #else
666     HAL_PCCARD_ITCallback(hpccard);
667 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
668 
669     /* Clear PCCARD interrupt Falling edge pending bit */
670     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE);
671   }
672 
673   /* Check PCCARD interrupt FIFO empty flag */
674   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT))
675   {
676     /* PCCARD interrupt callback*/
677 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
678     hpccard->ItCallback(hpccard);
679 #else
680     HAL_PCCARD_ITCallback(hpccard);
681 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
682 
683     /* Clear PCCARD interrupt FIFO empty pending bit */
684     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT);
685   }
686 }
687 
688 /**
689   * @brief  PCCARD interrupt feature callback
690   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
691   *                the configuration information for PCCARD module.
692   * @retval None
693   */
HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef * hpccard)694 __weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard)
695 {
696   /* Prevent unused argument(s) compilation warning */
697   UNUSED(hpccard);
698   /* NOTE : This function Should not be modified, when the callback is needed,
699             the HAL_PCCARD_ITCallback could be implemented in the user file
700    */
701 }
702 
703 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
704 /**
705   * @brief  Register a User PCCARD Callback
706   *         To be used instead of the weak (surcharged) predefined callback
707   * @param hpccard : PCCARD handle
708   * @param CallbackId : ID of the callback to be registered
709   *        This parameter can be one of the following values:
710   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
711   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
712   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
713   * @param pCallback : pointer to the Callback function
714   * @retval status
715   */
HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId,pPCCARD_CallbackTypeDef pCallback)716 HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId,
717                                               pPCCARD_CallbackTypeDef pCallback)
718 {
719   HAL_StatusTypeDef status = HAL_OK;
720 
721   if (pCallback == NULL)
722   {
723     return HAL_ERROR;
724   }
725 
726   /* Process locked */
727   __HAL_LOCK(hpccard);
728 
729   if (hpccard->State == HAL_PCCARD_STATE_READY)
730   {
731     switch (CallbackId)
732     {
733       case HAL_PCCARD_MSP_INIT_CB_ID :
734         hpccard->MspInitCallback = pCallback;
735         break;
736       case HAL_PCCARD_MSP_DEINIT_CB_ID :
737         hpccard->MspDeInitCallback = pCallback;
738         break;
739       case HAL_PCCARD_IT_CB_ID :
740         hpccard->ItCallback = pCallback;
741         break;
742       default :
743         /* update return status */
744         status =  HAL_ERROR;
745         break;
746     }
747   }
748   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
749   {
750     switch (CallbackId)
751     {
752       case HAL_PCCARD_MSP_INIT_CB_ID :
753         hpccard->MspInitCallback = pCallback;
754         break;
755       case HAL_PCCARD_MSP_DEINIT_CB_ID :
756         hpccard->MspDeInitCallback = pCallback;
757         break;
758       default :
759         /* update return status */
760         status =  HAL_ERROR;
761         break;
762     }
763   }
764   else
765   {
766     /* update return status */
767     status =  HAL_ERROR;
768   }
769 
770   /* Release Lock */
771   __HAL_UNLOCK(hpccard);
772   return status;
773 }
774 
775 /**
776   * @brief  Unregister a User PCCARD Callback
777   *         PCCARD Callback is redirected to the weak (surcharged) predefined callback
778   * @param hpccard : PCCARD handle
779   * @param CallbackId : ID of the callback to be unregistered
780   *        This parameter can be one of the following values:
781   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
782   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
783   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
784   * @retval status
785   */
HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId)786 HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId)
787 {
788   HAL_StatusTypeDef status = HAL_OK;
789 
790   /* Process locked */
791   __HAL_LOCK(hpccard);
792 
793   if (hpccard->State == HAL_PCCARD_STATE_READY)
794   {
795     switch (CallbackId)
796     {
797       case HAL_PCCARD_MSP_INIT_CB_ID :
798         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
799         break;
800       case HAL_PCCARD_MSP_DEINIT_CB_ID :
801         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
802         break;
803       case HAL_PCCARD_IT_CB_ID :
804         hpccard->ItCallback = HAL_PCCARD_ITCallback;
805         break;
806       default :
807         /* update return status */
808         status =  HAL_ERROR;
809         break;
810     }
811   }
812   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
813   {
814     switch (CallbackId)
815     {
816       case HAL_PCCARD_MSP_INIT_CB_ID :
817         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
818         break;
819       case HAL_PCCARD_MSP_DEINIT_CB_ID :
820         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
821         break;
822       default :
823         /* update return status */
824         status =  HAL_ERROR;
825         break;
826     }
827   }
828   else
829   {
830     /* update return status */
831     status =  HAL_ERROR;
832   }
833 
834   /* Release Lock */
835   __HAL_UNLOCK(hpccard);
836   return status;
837 }
838 #endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
839 
840 /**
841   * @}
842   */
843 
844 /** @defgroup PCCARD_Exported_Functions_Group3 State functions
845   *  @brief   Peripheral State functions
846   *
847 @verbatim
848   ==============================================================================
849                       ##### PCCARD State functions #####
850   ==============================================================================
851   [..]
852     This subsection permits to get in run-time the status of the PCCARD controller
853     and the data flow.
854 
855 @endverbatim
856   * @{
857   */
858 
859 /**
860   * @brief  return the PCCARD controller state
861   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
862   *                the configuration information for PCCARD module.
863   * @retval HAL state
864   */
HAL_PCCARD_GetState(PCCARD_HandleTypeDef * hpccard)865 HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard)
866 {
867   return hpccard->State;
868 }
869 
870 /**
871   * @brief  Get the compact flash memory status
872   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
873   *                the configuration information for PCCARD module.
874   * @retval New status of the PCCARD operation. This parameter can be:
875   *          - CompactFlash_TIMEOUT_ERROR: when the previous operation generate
876   *            a Timeout error
877   *          - CompactFlash_READY: when memory is ready for the next operation
878   */
HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef * hpccard)879 HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard)
880 {
881   uint32_t timeout = PCCARD_TIMEOUT_STATUS;
882   uint32_t status_pccard = 0U;
883 
884   /* Check the PCCARD controller state */
885   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
886   {
887     return HAL_PCCARD_STATUS_ONGOING;
888   }
889 
890   status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
891 
892   while ((status_pccard == PCCARD_BUSY) && timeout)
893   {
894     status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
895     timeout--;
896   }
897 
898   if (timeout == 0U)
899   {
900     status_pccard =  PCCARD_TIMEOUT_ERROR;
901   }
902 
903   /* Return the operation status */
904   return (HAL_PCCARD_StatusTypeDef) status_pccard;
905 }
906 
907 /**
908   * @brief  Reads the Compact Flash memory status using the Read status command
909   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
910   *                the configuration information for PCCARD module.
911   * @retval The status of the Compact Flash memory. This parameter can be:
912   *          - CompactFlash_BUSY: when memory is busy
913   *          - CompactFlash_READY: when memory is ready for the next operation
914   *          - CompactFlash_ERROR: when the previous operation generates error
915   */
HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef * hpccard)916 HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard)
917 {
918   uint8_t data = 0U;
919   uint8_t status_pccard = PCCARD_BUSY;
920 
921   /* Check the PCCARD controller state */
922   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
923   {
924     return HAL_PCCARD_STATUS_ONGOING;
925   }
926 
927   /* Read status operation */
928   data =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
929 
930   if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR)
931   {
932     status_pccard = PCCARD_TIMEOUT_ERROR;
933   }
934   else if ((data & PCCARD_READY) == PCCARD_READY)
935   {
936     status_pccard = PCCARD_READY;
937   }
938 
939   return (HAL_PCCARD_StatusTypeDef) status_pccard;
940 }
941 
942 /**
943   * @}
944   */
945 
946 /**
947   * @}
948   */
949 
950 /**
951   * @}
952   */
953 
954 #endif /* HAL_PCCARD_MODULE_ENABLED */
955 
956 /**
957   * @}
958   */
959 
960