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, FSMC_NAND_PCC_TimingTypeDef *IOSpaceTiming)
166 {
167   /* Check the PCCARD controller state */
168   if (hpccard == NULL)
169   {
170     return HAL_ERROR;
171   }
172 
173   if (hpccard->State == HAL_PCCARD_STATE_RESET)
174   {
175     /* Allocate lock resource and initialize it */
176     hpccard->Lock = HAL_UNLOCKED;
177 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
178     if (hpccard->MspInitCallback == NULL)
179     {
180       hpccard->MspInitCallback = HAL_PCCARD_MspInit;
181     }
182     hpccard->ItCallback = HAL_PCCARD_ITCallback;
183 
184     /* Init the low level hardware */
185     hpccard->MspInitCallback(hpccard);
186 #else
187     /* Initialize the low level hardware (MSP) */
188     HAL_PCCARD_MspInit(hpccard);
189 #endif
190   }
191 
192   /* Initialize the PCCARD state */
193   hpccard->State = HAL_PCCARD_STATE_BUSY;
194 
195   /* Initialize PCCARD control Interface */
196   FSMC_PCCARD_Init(hpccard->Instance, &(hpccard->Init));
197 
198   /* Init PCCARD common space timing Interface */
199   FSMC_PCCARD_CommonSpace_Timing_Init(hpccard->Instance, ComSpaceTiming);
200 
201   /* Init PCCARD attribute space timing Interface */
202   FSMC_PCCARD_AttributeSpace_Timing_Init(hpccard->Instance, AttSpaceTiming);
203 
204   /* Init PCCARD IO space timing Interface */
205   FSMC_PCCARD_IOSpace_Timing_Init(hpccard->Instance, IOSpaceTiming);
206 
207   /* Enable the PCCARD device */
208   __FSMC_PCCARD_ENABLE(hpccard->Instance);
209 
210   /* Update the PCCARD state */
211   hpccard->State = HAL_PCCARD_STATE_READY;
212 
213   return HAL_OK;
214 
215 }
216 
217 /**
218   * @brief  Perform the PCCARD memory De-initialization sequence
219   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
220   *                the configuration information for PCCARD module.
221   * @retval HAL status
222   */
HAL_PCCARD_DeInit(PCCARD_HandleTypeDef * hpccard)223 HAL_StatusTypeDef  HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard)
224 {
225 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
226   if (hpccard->MspDeInitCallback == NULL)
227   {
228     hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
229   }
230 
231   /* DeInit the low level hardware */
232   hpccard->MspDeInitCallback(hpccard);
233 #else
234   /* De-Initialize the low level hardware (MSP) */
235   HAL_PCCARD_MspDeInit(hpccard);
236 #endif
237 
238   /* Configure the PCCARD registers with their reset values */
239   FSMC_PCCARD_DeInit(hpccard->Instance);
240 
241   /* Update the PCCARD controller state */
242   hpccard->State = HAL_PCCARD_STATE_RESET;
243 
244   /* Release Lock */
245   __HAL_UNLOCK(hpccard);
246 
247   return HAL_OK;
248 }
249 
250 /**
251   * @brief  PCCARD MSP Init
252   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
253   *                the configuration information for PCCARD module.
254   * @retval None
255   */
HAL_PCCARD_MspInit(PCCARD_HandleTypeDef * hpccard)256 __weak void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard)
257 {
258   /* Prevent unused argument(s) compilation warning */
259   UNUSED(hpccard);
260   /* NOTE : This function Should not be modified, when the callback is needed,
261             the HAL_PCCARD_MspInit could be implemented in the user file
262    */
263 }
264 
265 /**
266   * @brief  PCCARD MSP DeInit
267   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
268   *                the configuration information for PCCARD module.
269   * @retval None
270   */
HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef * hpccard)271 __weak void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard)
272 {
273   /* Prevent unused argument(s) compilation warning */
274   UNUSED(hpccard);
275   /* NOTE : This function Should not be modified, when the callback is needed,
276             the HAL_PCCARD_MspDeInit could be implemented in the user file
277    */
278 }
279 
280 /**
281   * @}
282   */
283 
284 /** @defgroup PCCARD_Exported_Functions_Group2 Input and Output functions
285   * @brief    Input Output and memory control functions
286   *
287   @verbatim
288   ==============================================================================
289                     ##### PCCARD Input and Output functions #####
290   ==============================================================================
291   [..]
292     This section provides functions allowing to use and control the PCCARD memory
293 
294 @endverbatim
295   * @{
296   */
297 
298 /**
299   * @brief  Read Compact Flash's ID.
300   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
301   *                the configuration information for PCCARD module.
302   * @param  CompactFlash_ID Compact flash ID structure.
303   * @param  pStatus pointer to compact flash status
304   * @retval HAL status
305   *
306   */
HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef * hpccard,uint8_t CompactFlash_ID[],uint8_t * pStatus)307 HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus)
308 {
309   uint32_t timeout = PCCARD_TIMEOUT_READ_ID, index = 0U;
310   uint8_t status = 0;
311 
312   /* Process Locked */
313   __HAL_LOCK(hpccard);
314 
315   /* Check the PCCARD controller state */
316   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
317   {
318     return HAL_BUSY;
319   }
320 
321   /* Update the PCCARD controller state */
322   hpccard->State = HAL_PCCARD_STATE_BUSY;
323 
324   /* Initialize the PCCARD status */
325   *pStatus = PCCARD_READY;
326 
327   /* Send the Identify Command */
328   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)  = (uint16_t)0xECEC;
329 
330   /* Read PCCARD IDs and timeout treatment */
331   do
332   {
333     /* Read the PCCARD status */
334     status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
335 
336     timeout--;
337   } while ((status != PCCARD_STATUS_OK) && timeout);
338 
339   if (timeout == 0U)
340   {
341     *pStatus = PCCARD_TIMEOUT_ERROR;
342   }
343   else
344   {
345     /* Read PCCARD ID bytes */
346     for (index = 0U; index < 16U; index++)
347     {
348       CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA);
349     }
350   }
351 
352   /* Update the PCCARD controller state */
353   hpccard->State = HAL_PCCARD_STATE_READY;
354 
355   /* Process unlocked */
356   __HAL_UNLOCK(hpccard);
357 
358   return HAL_OK;
359 }
360 
361 /**
362   * @brief  Read sector from PCCARD memory
363   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
364   *                the configuration information for PCCARD module.
365   * @param  pBuffer pointer to destination read buffer
366   * @param  SectorAddress Sector address to read
367   * @param  pStatus pointer to PCCARD status
368   * @retval HAL status
369   */
HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)370 HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
371                                          uint8_t *pStatus)
372 {
373   uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U;
374   uint8_t status = 0;
375 
376   /* Process Locked */
377   __HAL_LOCK(hpccard);
378 
379   /* Check the PCCARD controller state */
380   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
381   {
382     return HAL_BUSY;
383   }
384 
385   /* Update the PCCARD controller state */
386   hpccard->State = HAL_PCCARD_STATE_BUSY;
387 
388   /* Initialize PCCARD status */
389   *pStatus = PCCARD_READY;
390 
391   /* Set the parameters to write a sector */
392   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
393   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
394   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0xE4A0;
395 
396   do
397   {
398     /* wait till the Status = 0x80 */
399     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
400     timeout--;
401   } while ((status == 0x80U) && timeout);
402 
403   if (timeout == 0U)
404   {
405     *pStatus = PCCARD_TIMEOUT_ERROR;
406   }
407 
408   timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
409 
410   do
411   {
412     /* wait till the Status = PCCARD_STATUS_OK */
413     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
414     timeout--;
415   } while ((status != PCCARD_STATUS_OK) && timeout);
416 
417   if (timeout == 0U)
418   {
419     *pStatus = PCCARD_TIMEOUT_ERROR;
420   }
421 
422   /* Read bytes */
423   for (; index < PCCARD_SECTOR_SIZE; index++)
424   {
425     *(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR);
426   }
427 
428   /* Update the PCCARD controller state */
429   hpccard->State = HAL_PCCARD_STATE_READY;
430 
431   /* Process unlocked */
432   __HAL_UNLOCK(hpccard);
433 
434   return HAL_OK;
435 }
436 
437 
438 /**
439   * @brief  Write sector to PCCARD memory
440   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
441   *                the configuration information for PCCARD module.
442   * @param  pBuffer pointer to source write buffer
443   * @param  SectorAddress Sector address to write
444   * @param  pStatus pointer to PCCARD status
445   * @retval HAL status
446   */
HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)447 HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
448                                           uint8_t *pStatus)
449 {
450   uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U;
451   uint8_t status = 0;
452 
453   /* Process Locked */
454   __HAL_LOCK(hpccard);
455 
456   /* Check the PCCARD controller state */
457   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
458   {
459     return HAL_BUSY;
460   }
461 
462   /* Update the PCCARD controller state */
463   hpccard->State = HAL_PCCARD_STATE_BUSY;
464 
465   /* Initialize PCCARD status */
466   *pStatus = PCCARD_READY;
467 
468   /* Set the parameters to write a sector */
469   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
470   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
471   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0x30A0;
472 
473   do
474   {
475     /* Wait till the Status = PCCARD_STATUS_OK */
476     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
477     timeout--;
478   } while ((status != PCCARD_STATUS_OK) && timeout);
479 
480   if (timeout == 0U)
481   {
482     *pStatus = PCCARD_TIMEOUT_ERROR;
483   }
484 
485   /* Write bytes */
486   for (; index < PCCARD_SECTOR_SIZE; index++)
487   {
488     *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++;
489   }
490 
491   do
492   {
493     /* Wait till the Status = PCCARD_STATUS_WRITE_OK */
494     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
495     timeout--;
496   } while ((status != PCCARD_STATUS_WRITE_OK) && timeout);
497 
498   if (timeout == 0U)
499   {
500     *pStatus = PCCARD_TIMEOUT_ERROR;
501   }
502 
503   /* Update the PCCARD controller state */
504   hpccard->State = HAL_PCCARD_STATE_READY;
505 
506   /* Process unlocked */
507   __HAL_UNLOCK(hpccard);
508 
509   return HAL_OK;
510 }
511 
512 
513 /**
514   * @brief  Erase sector from PCCARD memory
515   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
516   *                the configuration information for PCCARD module.
517   * @param  SectorAddress Sector address to erase
518   * @param  pStatus pointer to PCCARD status
519   * @retval HAL status
520   */
HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t SectorAddress,uint8_t * pStatus)521 HAL_StatusTypeDef  HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus)
522 {
523   uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR;
524   uint8_t status = 0;
525 
526   /* Process Locked */
527   __HAL_LOCK(hpccard);
528 
529   /* Check the PCCARD controller state */
530   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
531   {
532     return HAL_BUSY;
533   }
534 
535   /* Update the PCCARD controller state */
536   hpccard->State = HAL_PCCARD_STATE_BUSY;
537 
538   /* Initialize PCCARD status */
539   *pStatus = PCCARD_READY;
540 
541   /* Set the parameters to write a sector */
542   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW)  = 0x00;
543   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00;
544   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress;
545   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = 0x01;
546   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD)     = 0xA0;
547   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = ATA_ERASE_SECTOR_CMD;
548 
549   /* wait till the PCCARD is ready */
550   status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
551 
552   while ((status != PCCARD_STATUS_WRITE_OK) && timeout)
553   {
554     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
555     timeout--;
556   }
557 
558   if (timeout == 0U)
559   {
560     *pStatus = PCCARD_TIMEOUT_ERROR;
561   }
562 
563   /* Check the PCCARD controller state */
564   hpccard->State = HAL_PCCARD_STATE_READY;
565 
566   /* Process unlocked */
567   __HAL_UNLOCK(hpccard);
568 
569   return HAL_OK;
570 }
571 
572 /**
573   * @brief  Reset the PCCARD memory
574   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
575   *                the configuration information for PCCARD module.
576   * @retval HAL status
577   */
HAL_PCCARD_Reset(PCCARD_HandleTypeDef * hpccard)578 HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard)
579 {
580   /* Process Locked */
581   __HAL_LOCK(hpccard);
582 
583   /* Check the PCCARD controller state */
584   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
585   {
586     return HAL_BUSY;
587   }
588 
589   /* Provide a SW reset and Read and verify the:
590    - PCCard Configuration Option Register at address 0x98000200 --> 0x80
591    - Card Configuration and Status Register at address 0x98000202 --> 0x00
592    - Pin Replacement Register at address 0x98000204 --> 0x0C
593    - Socket and Copy Register at address 0x98000206 --> 0x00
594   */
595 
596   /* Check the PCCARD controller state */
597   hpccard->State = HAL_PCCARD_STATE_BUSY;
598 
599   *(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01;
600 
601   /* Check the PCCARD controller state */
602   hpccard->State = HAL_PCCARD_STATE_READY;
603 
604   /* Process unlocked */
605   __HAL_UNLOCK(hpccard);
606 
607   return HAL_OK;
608 }
609 
610 /**
611   * @brief  This function handles PCCARD device interrupt request.
612   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
613   *                the configuration information for PCCARD module.
614   * @retval HAL status
615   */
HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef * hpccard)616 void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard)
617 {
618   /* Check PCCARD interrupt Rising edge flag */
619   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE))
620   {
621     /* PCCARD interrupt callback*/
622 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
623     hpccard->ItCallback(hpccard);
624 #else
625     HAL_PCCARD_ITCallback(hpccard);
626 #endif
627 
628     /* Clear PCCARD interrupt Rising edge pending bit */
629     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE);
630   }
631 
632   /* Check PCCARD interrupt Level flag */
633   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL))
634   {
635     /* PCCARD interrupt callback*/
636 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
637     hpccard->ItCallback(hpccard);
638 #else
639     HAL_PCCARD_ITCallback(hpccard);
640 #endif
641 
642     /* Clear PCCARD interrupt Level pending bit */
643     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL);
644   }
645 
646   /* Check PCCARD interrupt Falling edge flag */
647   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE))
648   {
649     /* PCCARD interrupt callback*/
650 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
651     hpccard->ItCallback(hpccard);
652 #else
653     HAL_PCCARD_ITCallback(hpccard);
654 #endif
655 
656     /* Clear PCCARD interrupt Falling edge pending bit */
657     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE);
658   }
659 
660   /* Check PCCARD interrupt FIFO empty flag */
661   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT))
662   {
663     /* PCCARD interrupt callback*/
664 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
665     hpccard->ItCallback(hpccard);
666 #else
667     HAL_PCCARD_ITCallback(hpccard);
668 #endif
669 
670     /* Clear PCCARD interrupt FIFO empty pending bit */
671     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT);
672   }
673 }
674 
675 /**
676   * @brief  PCCARD interrupt feature callback
677   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
678   *                the configuration information for PCCARD module.
679   * @retval None
680   */
HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef * hpccard)681 __weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard)
682 {
683   /* Prevent unused argument(s) compilation warning */
684   UNUSED(hpccard);
685   /* NOTE : This function Should not be modified, when the callback is needed,
686             the HAL_PCCARD_ITCallback could be implemented in the user file
687    */
688 }
689 
690 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
691 /**
692   * @brief  Register a User PCCARD Callback
693   *         To be used instead of the weak (surcharged) predefined callback
694   * @param hpccard : PCCARD handle
695   * @param CallbackId : ID of the callback to be registered
696   *        This parameter can be one of the following values:
697   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
698   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
699   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
700   * @param pCallback : pointer to the Callback function
701   * @retval status
702   */
HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId,pPCCARD_CallbackTypeDef pCallback)703 HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId,
704                                               pPCCARD_CallbackTypeDef pCallback)
705 {
706   HAL_StatusTypeDef status = HAL_OK;
707 
708   if (pCallback == NULL)
709   {
710     return HAL_ERROR;
711   }
712 
713   /* Process locked */
714   __HAL_LOCK(hpccard);
715 
716   if (hpccard->State == HAL_PCCARD_STATE_READY)
717   {
718     switch (CallbackId)
719     {
720       case HAL_PCCARD_MSP_INIT_CB_ID :
721         hpccard->MspInitCallback = pCallback;
722         break;
723       case HAL_PCCARD_MSP_DEINIT_CB_ID :
724         hpccard->MspDeInitCallback = pCallback;
725         break;
726       case HAL_PCCARD_IT_CB_ID :
727         hpccard->ItCallback = pCallback;
728         break;
729       default :
730         /* update return status */
731         status =  HAL_ERROR;
732         break;
733     }
734   }
735   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
736   {
737     switch (CallbackId)
738     {
739       case HAL_PCCARD_MSP_INIT_CB_ID :
740         hpccard->MspInitCallback = pCallback;
741         break;
742       case HAL_PCCARD_MSP_DEINIT_CB_ID :
743         hpccard->MspDeInitCallback = pCallback;
744         break;
745       default :
746         /* update return status */
747         status =  HAL_ERROR;
748         break;
749     }
750   }
751   else
752   {
753     /* update return status */
754     status =  HAL_ERROR;
755   }
756 
757   /* Release Lock */
758   __HAL_UNLOCK(hpccard);
759   return status;
760 }
761 
762 /**
763   * @brief  Unregister a User PCCARD Callback
764   *         PCCARD Callback is redirected to the weak (surcharged) predefined callback
765   * @param hpccard : PCCARD handle
766   * @param CallbackId : ID of the callback to be unregistered
767   *        This parameter can be one of the following values:
768   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
769   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
770   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
771   * @retval status
772   */
HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId)773 HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId)
774 {
775   HAL_StatusTypeDef status = HAL_OK;
776 
777   /* Process locked */
778   __HAL_LOCK(hpccard);
779 
780   if (hpccard->State == HAL_PCCARD_STATE_READY)
781   {
782     switch (CallbackId)
783     {
784       case HAL_PCCARD_MSP_INIT_CB_ID :
785         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
786         break;
787       case HAL_PCCARD_MSP_DEINIT_CB_ID :
788         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
789         break;
790       case HAL_PCCARD_IT_CB_ID :
791         hpccard->ItCallback = HAL_PCCARD_ITCallback;
792         break;
793       default :
794         /* update return status */
795         status =  HAL_ERROR;
796         break;
797     }
798   }
799   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
800   {
801     switch (CallbackId)
802     {
803       case HAL_PCCARD_MSP_INIT_CB_ID :
804         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
805         break;
806       case HAL_PCCARD_MSP_DEINIT_CB_ID :
807         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
808         break;
809       default :
810         /* update return status */
811         status =  HAL_ERROR;
812         break;
813     }
814   }
815   else
816   {
817     /* update return status */
818     status =  HAL_ERROR;
819   }
820 
821   /* Release Lock */
822   __HAL_UNLOCK(hpccard);
823   return status;
824 }
825 #endif
826 
827 /**
828   * @}
829   */
830 
831 /** @defgroup PCCARD_Exported_Functions_Group3 State functions
832   *  @brief   Peripheral State functions
833   *
834 @verbatim
835   ==============================================================================
836                       ##### PCCARD State functions #####
837   ==============================================================================
838   [..]
839     This subsection permits to get in run-time the status of the PCCARD controller
840     and the data flow.
841 
842 @endverbatim
843   * @{
844   */
845 
846 /**
847   * @brief  return the PCCARD controller state
848   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
849   *                the configuration information for PCCARD module.
850   * @retval HAL state
851   */
HAL_PCCARD_GetState(PCCARD_HandleTypeDef * hpccard)852 HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard)
853 {
854   return hpccard->State;
855 }
856 
857 /**
858   * @brief  Get the compact flash memory status
859   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
860   *                the configuration information for PCCARD module.
861   * @retval New status of the PCCARD operation. This parameter can be:
862   *          - CompactFlash_TIMEOUT_ERROR: when the previous operation generate
863   *            a Timeout error
864   *          - CompactFlash_READY: when memory is ready for the next operation
865   */
HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef * hpccard)866 HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard)
867 {
868   uint32_t timeout = PCCARD_TIMEOUT_STATUS, status_pccard = 0U;
869 
870   /* Check the PCCARD controller state */
871   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
872   {
873     return HAL_PCCARD_STATUS_ONGOING;
874   }
875 
876   status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
877 
878   while ((status_pccard == PCCARD_BUSY) && timeout)
879   {
880     status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
881     timeout--;
882   }
883 
884   if (timeout == 0U)
885   {
886     status_pccard =  PCCARD_TIMEOUT_ERROR;
887   }
888 
889   /* Return the operation status */
890   return (HAL_PCCARD_StatusTypeDef) status_pccard;
891 }
892 
893 /**
894   * @brief  Reads the Compact Flash memory status using the Read status command
895   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
896   *                the configuration information for PCCARD module.
897   * @retval The status of the Compact Flash memory. This parameter can be:
898   *          - CompactFlash_BUSY: when memory is busy
899   *          - CompactFlash_READY: when memory is ready for the next operation
900   *          - CompactFlash_ERROR: when the previous operation generates error
901   */
HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef * hpccard)902 HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard)
903 {
904   uint8_t data = 0U, status_pccard = PCCARD_BUSY;
905 
906   /* Check the PCCARD controller state */
907   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
908   {
909     return HAL_PCCARD_STATUS_ONGOING;
910   }
911 
912   /* Read status operation */
913   data =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
914 
915   if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR)
916   {
917     status_pccard = PCCARD_TIMEOUT_ERROR;
918   }
919   else if ((data & PCCARD_READY) == PCCARD_READY)
920   {
921     status_pccard = PCCARD_READY;
922   }
923 
924   return (HAL_PCCARD_StatusTypeDef) status_pccard;
925 }
926 
927 /**
928   * @}
929   */
930 
931 /**
932   * @}
933   */
934 
935 /**
936   * @}
937   */
938 
939 #endif /* HAL_PCCARD_MODULE_ENABLED */
940 
941 /**
942   * @}
943   */
944 
945