1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_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 "stm32f1xx_hal.h"
103 
104 #if defined(FSMC_BANK4)
105 
106 /** @addtogroup STM32F1xx_HAL_Driver
107   * @{
108   */
109 
110 #ifdef HAL_PCCARD_MODULE_ENABLED
111 
112 /** @defgroup PCCARD PCCARD
113   * @brief PCCARD HAL module driver
114   * @{
115   */
116 /* Private typedef -----------------------------------------------------------*/
117 /* Private define ------------------------------------------------------------*/
118 
119 /** @defgroup PCCARD_Private_Defines PCCARD Private Defines
120   * @{
121   */
122 #define PCCARD_TIMEOUT_READ_ID                 0x0000FFFFU
123 #define PCCARD_TIMEOUT_READ_WRITE_SECTOR       0x0000FFFFU
124 #define PCCARD_TIMEOUT_ERASE_SECTOR            0x00000400U
125 #define PCCARD_TIMEOUT_STATUS                  0x01000000U
126 
127 #define PCCARD_STATUS_OK                       (uint8_t)0x58
128 #define PCCARD_STATUS_WRITE_OK                 (uint8_t)0x50
129 /**
130   * @}
131   */
132 
133 /* Private macro -------------------------------------------------------------*/
134 /* Private variables ---------------------------------------------------------*/
135 /* Private function ----------------------------------------------------------*/
136 /* Exported functions --------------------------------------------------------*/
137 /** @defgroup PCCARD_Exported_Functions PCCARD Exported Functions
138   * @{
139   */
140 
141 /** @defgroup PCCARD_Exported_Functions_Group1 Initialization and de-initialization functions
142   * @brief    Initialization and Configuration functions
143   *
144   @verbatim
145   ==============================================================================
146           ##### PCCARD Initialization and de-initialization functions #####
147   ==============================================================================
148   [..]
149     This section provides functions allowing to initialize/de-initialize
150     the PCCARD memory
151 
152 @endverbatim
153   * @{
154   */
155 
156 /**
157   * @brief  Perform the PCCARD memory Initialization sequence
158   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
159   *                the configuration information for PCCARD module.
160   * @param  ComSpaceTiming Common space timing structure
161   * @param  AttSpaceTiming Attribute space timing structure
162   * @param  IOSpaceTiming IO space timing structure
163   * @retval HAL status
164   */
HAL_PCCARD_Init(PCCARD_HandleTypeDef * hpccard,FSMC_NAND_PCC_TimingTypeDef * ComSpaceTiming,FSMC_NAND_PCC_TimingTypeDef * AttSpaceTiming,FSMC_NAND_PCC_TimingTypeDef * IOSpaceTiming)165 HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FSMC_NAND_PCC_TimingTypeDef *ComSpaceTiming,
166                                   FSMC_NAND_PCC_TimingTypeDef *AttSpaceTiming, 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
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
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 = PCCARD_TIMEOUT_READ_ID, index = 0U;
311   uint8_t status = 0;
312 
313   /* Process Locked */
314   __HAL_LOCK(hpccard);
315 
316   /* Check the PCCARD controller state */
317   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
318   {
319     return HAL_BUSY;
320   }
321 
322   /* Update the PCCARD controller state */
323   hpccard->State = HAL_PCCARD_STATE_BUSY;
324 
325   /* Initialize the PCCARD status */
326   *pStatus = PCCARD_READY;
327 
328   /* Send the Identify Command */
329   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)  = (uint16_t)0xECEC;
330 
331   /* Read PCCARD IDs and timeout treatment */
332   do
333   {
334     /* Read the PCCARD status */
335     status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
336 
337     timeout--;
338   } while ((status != PCCARD_STATUS_OK) && timeout);
339 
340   if (timeout == 0U)
341   {
342     *pStatus = PCCARD_TIMEOUT_ERROR;
343   }
344   else
345   {
346     /* Read PCCARD ID bytes */
347     for (index = 0U; index < 16U; index++)
348     {
349       CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA);
350     }
351   }
352 
353   /* Update the PCCARD controller state */
354   hpccard->State = HAL_PCCARD_STATE_READY;
355 
356   /* Process unlocked */
357   __HAL_UNLOCK(hpccard);
358 
359   return HAL_OK;
360 }
361 
362 /**
363   * @brief  Read sector from PCCARD memory
364   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
365   *                the configuration information for PCCARD module.
366   * @param  pBuffer pointer to destination read buffer
367   * @param  SectorAddress Sector address to read
368   * @param  pStatus pointer to PCCARD status
369   * @retval HAL status
370   */
HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)371 HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
372                                          uint8_t *pStatus)
373 {
374   uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U;
375   uint8_t status = 0;
376 
377   /* Process Locked */
378   __HAL_LOCK(hpccard);
379 
380   /* Check the PCCARD controller state */
381   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
382   {
383     return HAL_BUSY;
384   }
385 
386   /* Update the PCCARD controller state */
387   hpccard->State = HAL_PCCARD_STATE_BUSY;
388 
389   /* Initialize PCCARD status */
390   *pStatus = PCCARD_READY;
391 
392   /* Set the parameters to write a sector */
393   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
394   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
395   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0xE4A0;
396 
397   do
398   {
399     /* wait till the Status = 0x80 */
400     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
401     timeout--;
402   } while ((status == 0x80U) && timeout);
403 
404   if (timeout == 0U)
405   {
406     *pStatus = PCCARD_TIMEOUT_ERROR;
407   }
408 
409   timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
410 
411   do
412   {
413     /* wait till the Status = PCCARD_STATUS_OK */
414     status =  *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
415     timeout--;
416   } while ((status != PCCARD_STATUS_OK) && timeout);
417 
418   if (timeout == 0U)
419   {
420     *pStatus = PCCARD_TIMEOUT_ERROR;
421   }
422 
423   /* Read bytes */
424   for (; index < PCCARD_SECTOR_SIZE; index++)
425   {
426     *(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR);
427   }
428 
429   /* Update the PCCARD controller state */
430   hpccard->State = HAL_PCCARD_STATE_READY;
431 
432   /* Process unlocked */
433   __HAL_UNLOCK(hpccard);
434 
435   return HAL_OK;
436 }
437 
438 
439 /**
440   * @brief  Write sector to PCCARD memory
441   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
442   *                the configuration information for PCCARD module.
443   * @param  pBuffer pointer to source write buffer
444   * @param  SectorAddress Sector address to write
445   * @param  pStatus pointer to PCCARD status
446   * @retval HAL status
447   */
HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t * pBuffer,uint16_t SectorAddress,uint8_t * pStatus)448 HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
449                                           uint8_t *pStatus)
450 {
451   uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U;
452   uint8_t status = 0;
453 
454   /* Process Locked */
455   __HAL_LOCK(hpccard);
456 
457   /* Check the PCCARD controller state */
458   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
459   {
460     return HAL_BUSY;
461   }
462 
463   /* Update the PCCARD controller state */
464   hpccard->State = HAL_PCCARD_STATE_BUSY;
465 
466   /* Initialize PCCARD status */
467   *pStatus = PCCARD_READY;
468 
469   /* Set the parameters to write a sector */
470   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
471   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
472   *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = (uint16_t)0x30A0;
473 
474   do
475   {
476     /* Wait till the Status = PCCARD_STATUS_OK */
477     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
478     timeout--;
479   } while ((status != PCCARD_STATUS_OK) && timeout);
480 
481   if (timeout == 0U)
482   {
483     *pStatus = PCCARD_TIMEOUT_ERROR;
484   }
485 
486   /* Write bytes */
487   for (; index < PCCARD_SECTOR_SIZE; index++)
488   {
489     *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++;
490   }
491 
492   do
493   {
494     /* Wait till the Status = PCCARD_STATUS_WRITE_OK */
495     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
496     timeout--;
497   } while ((status != PCCARD_STATUS_WRITE_OK) && timeout);
498 
499   if (timeout == 0U)
500   {
501     *pStatus = PCCARD_TIMEOUT_ERROR;
502   }
503 
504   /* Update the PCCARD controller state */
505   hpccard->State = HAL_PCCARD_STATE_READY;
506 
507   /* Process unlocked */
508   __HAL_UNLOCK(hpccard);
509 
510   return HAL_OK;
511 }
512 
513 
514 /**
515   * @brief  Erase sector from PCCARD memory
516   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
517   *                the configuration information for PCCARD module.
518   * @param  SectorAddress Sector address to erase
519   * @param  pStatus pointer to PCCARD status
520   * @retval HAL status
521   */
HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef * hpccard,uint16_t SectorAddress,uint8_t * pStatus)522 HAL_StatusTypeDef  HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus)
523 {
524   uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR;
525   uint8_t status = 0;
526 
527   /* Process Locked */
528   __HAL_LOCK(hpccard);
529 
530   /* Check the PCCARD controller state */
531   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
532   {
533     return HAL_BUSY;
534   }
535 
536   /* Update the PCCARD controller state */
537   hpccard->State = HAL_PCCARD_STATE_BUSY;
538 
539   /* Initialize PCCARD status */
540   *pStatus = PCCARD_READY;
541 
542   /* Set the parameters to write a sector */
543   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW)  = 0x00;
544   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00;
545   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress;
546   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT)  = 0x01;
547   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD)     = 0xA0;
548   *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD)    = ATA_ERASE_SECTOR_CMD;
549 
550   /* wait till the PCCARD is ready */
551   status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
552 
553   while ((status != PCCARD_STATUS_WRITE_OK) && timeout)
554   {
555     status =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
556     timeout--;
557   }
558 
559   if (timeout == 0U)
560   {
561     *pStatus = PCCARD_TIMEOUT_ERROR;
562   }
563 
564   /* Check the PCCARD controller state */
565   hpccard->State = HAL_PCCARD_STATE_READY;
566 
567   /* Process unlocked */
568   __HAL_UNLOCK(hpccard);
569 
570   return HAL_OK;
571 }
572 
573 /**
574   * @brief  Reset the PCCARD memory
575   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
576   *                the configuration information for PCCARD module.
577   * @retval HAL status
578   */
HAL_PCCARD_Reset(PCCARD_HandleTypeDef * hpccard)579 HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard)
580 {
581   /* Process Locked */
582   __HAL_LOCK(hpccard);
583 
584   /* Check the PCCARD controller state */
585   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
586   {
587     return HAL_BUSY;
588   }
589 
590   /* Provide a SW reset and Read and verify the:
591    - PCCard Configuration Option Register at address 0x98000200 --> 0x80
592    - Card Configuration and Status Register at address 0x98000202 --> 0x00
593    - Pin Replacement Register at address 0x98000204 --> 0x0C
594    - Socket and Copy Register at address 0x98000206 --> 0x00
595   */
596 
597   /* Check the PCCARD controller state */
598   hpccard->State = HAL_PCCARD_STATE_BUSY;
599 
600   *(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01;
601 
602   /* Check the PCCARD controller state */
603   hpccard->State = HAL_PCCARD_STATE_READY;
604 
605   /* Process unlocked */
606   __HAL_UNLOCK(hpccard);
607 
608   return HAL_OK;
609 }
610 
611 /**
612   * @brief  This function handles PCCARD device interrupt request.
613   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
614   *                the configuration information for PCCARD module.
615   * @retval HAL status
616   */
HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef * hpccard)617 void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard)
618 {
619   /* Check PCCARD interrupt Rising edge flag */
620   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE))
621   {
622     /* PCCARD interrupt callback*/
623 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
624     hpccard->ItCallback(hpccard);
625 #else
626     HAL_PCCARD_ITCallback(hpccard);
627 #endif
628 
629     /* Clear PCCARD interrupt Rising edge pending bit */
630     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE);
631   }
632 
633   /* Check PCCARD interrupt Level flag */
634   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL))
635   {
636     /* PCCARD interrupt callback*/
637 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
638     hpccard->ItCallback(hpccard);
639 #else
640     HAL_PCCARD_ITCallback(hpccard);
641 #endif
642 
643     /* Clear PCCARD interrupt Level pending bit */
644     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL);
645   }
646 
647   /* Check PCCARD interrupt Falling edge flag */
648   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE))
649   {
650     /* PCCARD interrupt callback*/
651 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
652     hpccard->ItCallback(hpccard);
653 #else
654     HAL_PCCARD_ITCallback(hpccard);
655 #endif
656 
657     /* Clear PCCARD interrupt Falling edge pending bit */
658     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE);
659   }
660 
661   /* Check PCCARD interrupt FIFO empty flag */
662   if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT))
663   {
664     /* PCCARD interrupt callback*/
665 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
666     hpccard->ItCallback(hpccard);
667 #else
668     HAL_PCCARD_ITCallback(hpccard);
669 #endif
670 
671     /* Clear PCCARD interrupt FIFO empty pending bit */
672     __FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT);
673   }
674 }
675 
676 /**
677   * @brief  PCCARD interrupt feature callback
678   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
679   *                the configuration information for PCCARD module.
680   * @retval None
681   */
HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef * hpccard)682 __weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard)
683 {
684   /* Prevent unused argument(s) compilation warning */
685   UNUSED(hpccard);
686   /* NOTE : This function Should not be modified, when the callback is needed,
687             the HAL_PCCARD_ITCallback could be implemented in the user file
688    */
689 }
690 
691 #if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
692 /**
693   * @brief  Register a User PCCARD Callback
694   *         To be used instead of the weak (surcharged) predefined callback
695   * @param hpccard : PCCARD handle
696   * @param CallbackId : ID of the callback to be registered
697   *        This parameter can be one of the following values:
698   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
699   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
700   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
701   * @param pCallback : pointer to the Callback function
702   * @retval status
703   */
HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId,pPCCARD_CallbackTypeDef pCallback)704 HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId,
705                                               pPCCARD_CallbackTypeDef pCallback)
706 {
707   HAL_StatusTypeDef status = HAL_OK;
708 
709   if (pCallback == NULL)
710   {
711     return HAL_ERROR;
712   }
713 
714   /* Process locked */
715   __HAL_LOCK(hpccard);
716 
717   if (hpccard->State == HAL_PCCARD_STATE_READY)
718   {
719     switch (CallbackId)
720     {
721       case HAL_PCCARD_MSP_INIT_CB_ID :
722         hpccard->MspInitCallback = pCallback;
723         break;
724       case HAL_PCCARD_MSP_DEINIT_CB_ID :
725         hpccard->MspDeInitCallback = pCallback;
726         break;
727       case HAL_PCCARD_IT_CB_ID :
728         hpccard->ItCallback = pCallback;
729         break;
730       default :
731         /* update return status */
732         status =  HAL_ERROR;
733         break;
734     }
735   }
736   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
737   {
738     switch (CallbackId)
739     {
740       case HAL_PCCARD_MSP_INIT_CB_ID :
741         hpccard->MspInitCallback = pCallback;
742         break;
743       case HAL_PCCARD_MSP_DEINIT_CB_ID :
744         hpccard->MspDeInitCallback = pCallback;
745         break;
746       default :
747         /* update return status */
748         status =  HAL_ERROR;
749         break;
750     }
751   }
752   else
753   {
754     /* update return status */
755     status =  HAL_ERROR;
756   }
757 
758   /* Release Lock */
759   __HAL_UNLOCK(hpccard);
760   return status;
761 }
762 
763 /**
764   * @brief  Unregister a User PCCARD Callback
765   *         PCCARD Callback is redirected to the weak (surcharged) predefined callback
766   * @param hpccard : PCCARD handle
767   * @param CallbackId : ID of the callback to be unregistered
768   *        This parameter can be one of the following values:
769   *          @arg @ref HAL_PCCARD_MSP_INIT_CB_ID       PCCARD MspInit callback ID
770   *          @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID     PCCARD MspDeInit callback ID
771   *          @arg @ref HAL_PCCARD_IT_CB_ID             PCCARD IT callback ID
772   * @retval status
773   */
HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef * hpccard,HAL_PCCARD_CallbackIDTypeDef CallbackId)774 HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId)
775 {
776   HAL_StatusTypeDef status = HAL_OK;
777 
778   /* Process locked */
779   __HAL_LOCK(hpccard);
780 
781   if (hpccard->State == HAL_PCCARD_STATE_READY)
782   {
783     switch (CallbackId)
784     {
785       case HAL_PCCARD_MSP_INIT_CB_ID :
786         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
787         break;
788       case HAL_PCCARD_MSP_DEINIT_CB_ID :
789         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
790         break;
791       case HAL_PCCARD_IT_CB_ID :
792         hpccard->ItCallback = HAL_PCCARD_ITCallback;
793         break;
794       default :
795         /* update return status */
796         status =  HAL_ERROR;
797         break;
798     }
799   }
800   else if (hpccard->State == HAL_PCCARD_STATE_RESET)
801   {
802     switch (CallbackId)
803     {
804       case HAL_PCCARD_MSP_INIT_CB_ID :
805         hpccard->MspInitCallback = HAL_PCCARD_MspInit;
806         break;
807       case HAL_PCCARD_MSP_DEINIT_CB_ID :
808         hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
809         break;
810       default :
811         /* update return status */
812         status =  HAL_ERROR;
813         break;
814     }
815   }
816   else
817   {
818     /* update return status */
819     status =  HAL_ERROR;
820   }
821 
822   /* Release Lock */
823   __HAL_UNLOCK(hpccard);
824   return status;
825 }
826 #endif
827 
828 /**
829   * @}
830   */
831 
832 /** @defgroup PCCARD_Exported_Functions_Group3 State functions
833   *  @brief   Peripheral State functions
834   *
835 @verbatim
836   ==============================================================================
837                       ##### PCCARD State functions #####
838   ==============================================================================
839   [..]
840     This subsection permits to get in run-time the status of the PCCARD controller
841     and the data flow.
842 
843 @endverbatim
844   * @{
845   */
846 
847 /**
848   * @brief  return the PCCARD controller state
849   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
850   *                the configuration information for PCCARD module.
851   * @retval HAL state
852   */
HAL_PCCARD_GetState(PCCARD_HandleTypeDef * hpccard)853 HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard)
854 {
855   return hpccard->State;
856 }
857 
858 /**
859   * @brief  Get the compact flash memory status
860   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
861   *                the configuration information for PCCARD module.
862   * @retval New status of the PCCARD operation. This parameter can be:
863   *          - CompactFlash_TIMEOUT_ERROR: when the previous operation generate
864   *            a Timeout error
865   *          - CompactFlash_READY: when memory is ready for the next operation
866   */
HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef * hpccard)867 HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard)
868 {
869   uint32_t timeout = PCCARD_TIMEOUT_STATUS, status_pccard = 0U;
870 
871   /* Check the PCCARD controller state */
872   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
873   {
874     return HAL_PCCARD_STATUS_ONGOING;
875   }
876 
877   status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
878 
879   while ((status_pccard == PCCARD_BUSY) && timeout)
880   {
881     status_pccard =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
882     timeout--;
883   }
884 
885   if (timeout == 0U)
886   {
887     status_pccard =  PCCARD_TIMEOUT_ERROR;
888   }
889 
890   /* Return the operation status */
891   return (HAL_PCCARD_StatusTypeDef) status_pccard;
892 }
893 
894 /**
895   * @brief  Reads the Compact Flash memory status using the Read status command
896   * @param  hpccard pointer to a PCCARD_HandleTypeDef structure that contains
897   *                the configuration information for PCCARD module.
898   * @retval The status of the Compact Flash memory. This parameter can be:
899   *          - CompactFlash_BUSY: when memory is busy
900   *          - CompactFlash_READY: when memory is ready for the next operation
901   *          - CompactFlash_ERROR: when the previous operation generates error
902   */
HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef * hpccard)903 HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard)
904 {
905   uint8_t data = 0U, status_pccard = PCCARD_BUSY;
906 
907   /* Check the PCCARD controller state */
908   if (hpccard->State == HAL_PCCARD_STATE_BUSY)
909   {
910     return HAL_PCCARD_STATUS_ONGOING;
911   }
912 
913   /* Read status operation */
914   data =  *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
915 
916   if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR)
917   {
918     status_pccard = PCCARD_TIMEOUT_ERROR;
919   }
920   else if ((data & PCCARD_READY) == PCCARD_READY)
921   {
922     status_pccard = PCCARD_READY;
923   }
924 
925   return (HAL_PCCARD_StatusTypeDef) status_pccard;
926 }
927 
928 /**
929   * @}
930   */
931 
932 /**
933   * @}
934   */
935 
936 /**
937   * @}
938   */
939 
940 #endif /* HAL_PCCARD_MODULE_ENABLED */
941 
942 /**
943   * @}
944   */
945 
946 #endif /* FSMC_BANK4 */
947