Bug fixes to interrupt/event handling in SDHC HAL

pull/11324/head
Ryan Morse 2019-08-27 12:52:10 -07:00 committed by Kyle Kearney
parent 8ad377add3
commit 5c899a3350
2 changed files with 137 additions and 81 deletions

View File

@ -76,23 +76,23 @@ typedef enum
/** SDHC interrupt triggers */ /** SDHC interrupt triggers */
typedef enum { typedef enum {
CYHAL_SDHC_CMD_COMPLETE, //!> Command Complete CYHAL_SDHC_CMD_COMPLETE = 0x0001, //!> Command Complete
CYHAL_SDHC_XFER_COMPLETE, //!> Host read/write transfer is complete CYHAL_SDHC_XFER_COMPLETE = 0x0002, //!> Host read/write transfer is complete
CYHAL_SDHC_BGAP_EVENT, //!> This bit is set when both read/write transaction is stopped CYHAL_SDHC_BGAP_EVENT = 0x0004, //!> This bit is set when both read/write transaction is stopped at the block gap
CYHAL_SDHC_DMA_INTERRUPT, //!> Host controller detects an SDMA Buffer Boundary during transfer CYHAL_SDHC_DMA_INTERRUPT = 0x0008, //!> Host controller detects an SDMA Buffer Boundary during transfer
CYHAL_SDHC_BUF_WR_READY, //!> This bit is set if the Buffer Write Enable changes from 0 to 1 CYHAL_SDHC_BUF_WR_READY = 0x0010, //!> This bit is set if the Buffer Write Enable changes from 0 to 1
CYHAL_SDHC_BUF_RD_READY, //!> This bit is set if the Buffer Read Enable changes from 0 to 1 CYHAL_SDHC_BUF_RD_READY = 0x0020, //!> This bit is set if the Buffer Read Enable changes from 0 to 1
CYHAL_SDHC_CARD_INSERTION, //!> This bit is set if the Card Inserted in the Present State CYHAL_SDHC_CARD_INSERTION = 0x0040, //!> This bit is set if the Card Inserted in the Present State register changes from 0 to 1.
CYHAL_SDHC_CARD_REMOVAL, //!> This bit is set if the Card Inserted in the Present State CYHAL_SDHC_CARD_REMOVAL = 0x0080, //!> This bit is set if the Card Inserted in the Present State register changes from 1 to 0.
CYHAL_SDHC_CARD_INTERRUPT, //!> The synchronized value of the DAT[1] interrupt input for SD mode CYHAL_SDHC_CARD_INTERRUPT = 0x0100, //!> The synchronized value of the DAT[1] interrupt input for SD mode
CYHAL_SDHC_INT_A, CYHAL_SDHC_INT_A = 0x0200,
CYHAL_SDHC_INT_B, CYHAL_SDHC_INT_B = 0x0400,
CYHAL_SDHC_INT_C, CYHAL_SDHC_INT_C = 0x0800,
CYHAL_SDHC_RE_TUNE_EVENT, //!> This bit is set if the Re-Tuning Request changes from 0 to 1 CYHAL_SDHC_RE_TUNE_EVENT = 0x1000, //!> This bit is set if the Re-Tuning Request changes from 0 to 1
CYHAL_SDHC_FX_EVENT, //!> This status is set when R[14] of response register is set to 1 CYHAL_SDHC_FX_EVENT = 0x2000, //!> This status is set when R[14] of response register is set to 1
CYHAL_SDHC_CQE_EVENT, //!> This status is set if Command Queuing/Crypto event has occurred CYHAL_SDHC_CQE_EVENT = 0x4000, //!> This status is set if Command Queuing/Crypto event has occurred
CYHAL_SDHC_ERR_INTERRUPT, //!> If any of the bits in the Error Interrupt Status register are set CYHAL_SDHC_ERR_INTERRUPT = 0x8000, //!> If any of the bits in the Error Interrupt Status register are set
CYHAL_SDHC_ALL_INTERRUPTS, //!> Is used to enable/disable all interrupts CYHAL_SDHC_ALL_INTERRUPTS = 0xFFFF, //!> Is used to enable/disable all interrupts
} cyhal_sdhc_event_t; } cyhal_sdhc_event_t;
/** \} group_hal_sdhc_enums */ /** \} group_hal_sdhc_enums */
@ -121,7 +121,7 @@ typedef struct
{ {
bool enableLedControl; //!< Drive one IO to indicate when the card is being accessed bool enableLedControl; //!< Drive one IO to indicate when the card is being accessed
bool lowVoltageSignaling; //!< Whether 1.8V signaling is supported bool lowVoltageSignaling; //!< Whether 1.8V signaling is supported
bool isEmmc; //!< true if eMMC card, other way false bool isEmmc; //!< true if eMMC card, otherwise false
uint8_t busWidth; //!< The desired bus width uint8_t busWidth; //!< The desired bus width
} cyhal_sdhc_config_t; } cyhal_sdhc_config_t;
@ -186,7 +186,7 @@ void cyhal_sdhc_free(cyhal_sdhc_t *obj);
* @param[in] obj The SDHC object * @param[in] obj The SDHC object
* @param[in] address The address to read data from * @param[in] address The address to read data from
* @param[out] data Pointer to the byte-array of data to read from the device * @param[out] data Pointer to the byte-array of data to read from the device
* @param[in,out] length Number of bytes to read, updated with the number actually read * @param[in,out] length Number of 512 byte blocks to read, updated with the number actually read
* @return The status of the read request * @return The status of the read request
*/ */
cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length); cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
@ -196,7 +196,7 @@ cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *da
* @param[in] obj The SDHC object * @param[in] obj The SDHC object
* @param[in] address The address to write data to * @param[in] address The address to write data to
* @param[in] data Pointer to the byte-array of data to write to the device * @param[in] data Pointer to the byte-array of data to write to the device
* @param[in,out] length Number of bytes to read, updated with the number actually read * @param[in,out] length Number of 512 byte blocks to write, updated with the number actually written
* @return The status of the write request * @return The status of the write request
*/ */
cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length); cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length);
@ -205,7 +205,7 @@ cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint
* *
* @param[in] obj The SDHC object * @param[in] obj The SDHC object
* @param[in] startAddr Is the address of the first byte to erase * @param[in] startAddr Is the address of the first byte to erase
* @param[in] length The number of bytes (starting at startAddr) to erase * @param[in] length Number of 512 byte blocks (starting at startAddr) to erase
* @return The status of the erase request * @return The status of the erase request
*/ */
cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t length); cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t length);
@ -215,7 +215,7 @@ cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t l
* @param[in] obj The SDHC object that holds the transfer information * @param[in] obj The SDHC object that holds the transfer information
* @param[in] address The address to read data from * @param[in] address The address to read data from
* @param[out] data The receive buffer * @param[out] data The receive buffer
* @param[in,out] length Number of bytes to read, updated with the number actually read * @param[in,out] length Number of 512 byte blocks to read, updated with the number actually read
* @return The status of the read_async request * @return The status of the read_async request
*/ */
cy_rslt_t cyhal_sdhc_read_async(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length); cy_rslt_t cyhal_sdhc_read_async(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *data, size_t *length);
@ -225,7 +225,7 @@ cy_rslt_t cyhal_sdhc_read_async(const cyhal_sdhc_t *obj, uint32_t address, uint8
* @param[in] obj The SDHC object that holds the transfer information * @param[in] obj The SDHC object that holds the transfer information
* @param[in] address The address to write data to * @param[in] address The address to write data to
* @param[in] data The transmit buffer * @param[in] data The transmit buffer
* @param[in,out] length Number of bytes to read, updated with the number actually read * @param[in,out] length The number of 512 byte blocks to write, updated with the number actually written
* @return The status of the write_async request * @return The status of the write_async request
*/ */
cy_rslt_t cyhal_sdhc_write_async(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length); cy_rslt_t cyhal_sdhc_write_async(const cyhal_sdhc_t *obj, uint32_t address, const uint8_t *data, size_t *length);

View File

@ -135,6 +135,15 @@ extern "C"
#define CYHAL_SDIO_DS_CB_ORDER (0U) #define CYHAL_SDIO_DS_CB_ORDER (0U)
#endif /* !defined(CYHAL_SDIO_DS_CB_ORDER) */ #endif /* !defined(CYHAL_SDIO_DS_CB_ORDER) */
/* Defines for mapping sdhc events on interrupts */
#define SDHC_EVENTS_NUM (12U)
#define SDHC_EVENTS_MAP_NUM (2U)
#define SDHC_EVENT (0U)
#define SDHC_ISR (1U)
/* List of available SDHC instances */ /* List of available SDHC instances */
static SDHC_Type * const CYHAL_SDHC_BASE_ADDRESSES[CY_IP_MXSDHC_INSTANCES] = static SDHC_Type * const CYHAL_SDHC_BASE_ADDRESSES[CY_IP_MXSDHC_INSTANCES] =
{ {
@ -197,6 +206,24 @@ static uint8_t cyhal_sd_get_block_from_irqn(IRQn_Type irqn)
static void *cyhal_sd_config_structs[CY_IP_MXSDHC_INSTANCES]; static void *cyhal_sd_config_structs[CY_IP_MXSDHC_INSTANCES];
/* Structure to map SDHC events on SDHC interrupts */
const uint32_t eventMap[SDHC_EVENTS_NUM][SDHC_EVENTS_MAP_NUM] =
{
{ (uint32_t)CYHAL_SDHC_CMD_COMPLETE, (uint32_t)CY_SD_HOST_CMD_COMPLETE},
{ (uint32_t)CYHAL_SDHC_XFER_COMPLETE, (uint32_t)CY_SD_HOST_XFER_COMPLETE },
{ (uint32_t)CYHAL_SDHC_BGAP_EVENT, (uint32_t)CY_SD_HOST_BGAP },
{ (uint32_t)CYHAL_SDHC_DMA_INTERRUPT, (uint32_t)CY_SD_HOST_DMA_INTERRUPT },
{ (uint32_t)CYHAL_SDHC_BUF_WR_READY, (uint32_t)CY_SD_HOST_BUF_WR_READY },
{ (uint32_t)CYHAL_SDHC_BUF_RD_READY, (uint32_t)CY_SD_HOST_BUF_RD_READY },
{ (uint32_t)CYHAL_SDHC_CARD_INSERTION, (uint32_t)CY_SD_HOST_CARD_INSERTION },
{ (uint32_t)CYHAL_SDHC_CARD_REMOVAL, (uint32_t)CY_SD_HOST_CARD_REMOVAL },
{ (uint32_t)CYHAL_SDHC_CARD_INTERRUPT, (uint32_t)CY_SD_HOST_CARD_INTERRUPT },
{ (uint32_t)CYHAL_SDHC_FX_EVENT, (uint32_t)CY_SD_HOST_FX_EVENT },
{ (uint32_t)CYHAL_SDHC_CQE_EVENT, (uint32_t)CY_SD_HOST_CQE_EVENT },
{ (uint32_t)CYHAL_SDHC_ERR_INTERRUPT, (uint32_t)CY_SD_HOST_ERR_INTERRUPT },
};
static void release_pin_if_used(cyhal_gpio_t *pin) static void release_pin_if_used(cyhal_gpio_t *pin)
{ {
if (CYHAL_NC_PIN_VALUE != *pin) if (CYHAL_NC_PIN_VALUE != *pin)
@ -248,6 +275,7 @@ static cy_en_sd_host_status_t Cy_SD_Host_SdCardChangeClock(SDHC_Type *base, uint
static cy_en_sd_host_bus_width_t convert_buswidth(uint8_t stopbits); static cy_en_sd_host_bus_width_t convert_buswidth(uint8_t stopbits);
static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_params_t *params, static cy_en_syspm_status_t cyhal_sdio_syspm_callback(cy_stc_syspm_callback_params_t *params,
cy_en_syspm_callback_mode_t mode); cy_en_syspm_callback_mode_t mode);
static cyhal_sdhc_event_t get_event_from_isr(uint32_t asserted_interrupt);
/******************************************************************************* /*******************************************************************************
* Deep Sleep Callback Service Routine * Deep Sleep Callback Service Routine
@ -484,21 +512,20 @@ static void cyhal_sdhc_irq_handler(void)
uint32_t interruptStatus = Cy_SD_Host_GetNormalInterruptStatus(blockAddr); uint32_t interruptStatus = Cy_SD_Host_GetNormalInterruptStatus(blockAddr);
uint32_t userInterruptStatus = interruptStatus & obj->irq_cause; uint32_t userInterruptStatus = interruptStatus & obj->irq_cause;
cyhal_sdhc_event_t user_events = get_event_from_isr(userInterruptStatus);
if (obj->callback_data.callback != NULL) if (obj->callback_data.callback != NULL)
{ {
cyhal_sdhc_event_callback_t callback = (cyhal_sdhc_event_callback_t) obj->callback_data.callback; cyhal_sdhc_event_callback_t callback = (cyhal_sdhc_event_callback_t) obj->callback_data.callback;
/* Call registered callbacks here */ /* Call registered callbacks here */
(void) (callback) (obj->callback_data.callback_arg, (cyhal_sdhc_event_t) userInterruptStatus); (void) (callback) (obj->callback_data.callback_arg, user_events);
} }
/* Clear only handled events */ /* Clear only handled events */
Cy_SD_Host_ClearNormalInterruptStatus(blockAddr, userInterruptStatus); Cy_SD_Host_ClearNormalInterruptStatus(blockAddr, interruptStatus);
/* To clear SD Card interrupt need to disable SD Card Interrupt Enable bit. /* To clear SD Card interrupt need to disable SD Card Interrupt Enable bit */
* The SD Card interrupt is enabled in the bulk transfer function later on
* the next data transfer.
*/
if (0U != (interruptStatus & CY_SD_HOST_CARD_INTERRUPT)) if (0U != (interruptStatus & CY_SD_HOST_CARD_INTERRUPT))
{ {
uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptEnable(blockAddr); uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptEnable(blockAddr);
@ -507,7 +534,26 @@ static void cyhal_sdhc_irq_handler(void)
/* Disable SD Card interrupt */ /* Disable SD Card interrupt */
Cy_SD_Host_SetNormalInterruptEnable(blockAddr, interruptMask); Cy_SD_Host_SetNormalInterruptEnable(blockAddr, interruptMask);
} }
}
static cyhal_sdhc_event_t get_event_from_isr(uint32_t asserted_interrupt)
{
cyhal_sdhc_event_t anded_events = (cyhal_sdhc_event_t) 0U;
for (uint8_t i = 0; i < SDHC_EVENTS_NUM; i++)
{
const uint32_t *map_entry = eventMap[i];
/* Anded events should be handled in user callback function as only
* there exist the knowledge of enabled events
*/
if ((asserted_interrupt & map_entry[SDHC_ISR]) != 0)
{
anded_events |= map_entry[SDHC_EVENT];
}
}
return anded_events;
} }
cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj, cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
@ -680,7 +726,7 @@ cy_rslt_t cyhal_sdhc_init(cyhal_sdhc_t *obj,
/* Do not support eMMC card */ /* Do not support eMMC card */
obj->emmc = config->isEmmc; obj->emmc = config->isEmmc;
obj->dmaType = CY_SD_HOST_DMA_SDMA; obj->dmaType = CY_SD_HOST_DMA_ADMA2;
/* Configure SD Host to operate */ /* Configure SD Host to operate */
cy_stc_sd_host_init_config_t hostConfig; cy_stc_sd_host_init_config_t hostConfig;
@ -807,6 +853,7 @@ cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *da
cy_rslt_t ret = CY_RSLT_SUCCESS; cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t driverRet; cy_en_sd_host_status_t driverRet;
cy_stc_sd_host_write_read_config_t dataConfig; cy_stc_sd_host_write_read_config_t dataConfig;
uint32_t regIntrSts = Cy_SD_Host_GetNormalInterruptMask(obj->base);
dataConfig.data = (uint32_t*)data; /* The pointer to data. */ dataConfig.data = (uint32_t*)data; /* The pointer to data. */
dataConfig.address = address; /* The address to write/read data on the card or eMMC. */ dataConfig.address = address; /* The address to write/read data on the card or eMMC. */
@ -818,6 +865,12 @@ cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *da
dataConfig.enReliableWrite = false; /* For EMMC cards enable reliable write. */ dataConfig.enReliableWrite = false; /* For EMMC cards enable reliable write. */
dataConfig.enableDma = true; dataConfig.enableDma = true;
/* First clear out the transfer and command complete statuses */
Cy_SD_Host_ClearNormalInterruptStatus(obj->base, (CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE));
/* Disable CMD Done interrupt, will be enabled after transition is complete */
Cy_SD_Host_SetNormalInterruptMask(obj->base, (regIntrSts & (uint32_t)~(CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE)));
driverRet = Cy_SD_Host_Read(obj->base, &dataConfig, &obj->context); driverRet = Cy_SD_Host_Read(obj->base, &dataConfig, &obj->context);
if (CY_SD_HOST_SUCCESS != driverRet) if (CY_SD_HOST_SUCCESS != driverRet)
@ -834,8 +887,11 @@ cy_rslt_t cyhal_sdhc_read(const cyhal_sdhc_t *obj, uint32_t address, uint8_t *da
} }
} }
/* Restore interrupts after transition */
Cy_SD_Host_SetNormalInterruptMask(obj->base, regIntrSts);
/* Enable SD Card interrupt because it was disabled in interrupt handler */ /* Enable SD Card interrupt because it was disabled in interrupt handler */
if ((uint32_t) CYHAL_SDHC_CARD_INTERRUPT == ((uint32_t)CYHAL_SDHC_CARD_INTERRUPT & obj->irq_cause)) if (0U != (obj->irq_cause & CY_SD_HOST_CARD_INTERRUPT))
{ {
uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base); uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base);
@ -851,6 +907,7 @@ cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint
cy_rslt_t ret = CY_RSLT_SUCCESS; cy_rslt_t ret = CY_RSLT_SUCCESS;
cy_en_sd_host_status_t driverRet; cy_en_sd_host_status_t driverRet;
cy_stc_sd_host_write_read_config_t dataConfig; cy_stc_sd_host_write_read_config_t dataConfig;
uint32_t regIntrSts = Cy_SD_Host_GetNormalInterruptMask(obj->base);
dataConfig.data = (uint32_t*)data; /* The pointer to data. */ dataConfig.data = (uint32_t*)data; /* The pointer to data. */
dataConfig.address = address; /* The address to write/read data on the card or eMMC. */ dataConfig.address = address; /* The address to write/read data on the card or eMMC. */
@ -862,6 +919,12 @@ cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint
dataConfig.enReliableWrite = false; /* For EMMC cards enable reliable write. */ dataConfig.enReliableWrite = false; /* For EMMC cards enable reliable write. */
dataConfig.enableDma = true; dataConfig.enableDma = true;
/* First clear out the transfer and command complete statuses */
Cy_SD_Host_ClearNormalInterruptStatus(obj->base, (CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE));
/* Disable CMD Done interrupt, will be enabled after transition is complete */
Cy_SD_Host_SetNormalInterruptMask(obj->base, (regIntrSts & (uint32_t)~(CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE)));
driverRet = Cy_SD_Host_Write(obj->base, &dataConfig, &obj->context); driverRet = Cy_SD_Host_Write(obj->base, &dataConfig, &obj->context);
if (CY_SD_HOST_SUCCESS != driverRet) if (CY_SD_HOST_SUCCESS != driverRet)
@ -878,8 +941,11 @@ cy_rslt_t cyhal_sdhc_write(const cyhal_sdhc_t *obj, uint32_t address, const uint
} }
} }
/* Restore interrupts after transition */
Cy_SD_Host_SetNormalInterruptMask(obj->base, regIntrSts);
/* Enable SD Card interrupt because it was disabled in interrupt handler */ /* Enable SD Card interrupt because it was disabled in interrupt handler */
if ((uint32_t) CYHAL_SDHC_CARD_INTERRUPT == ((uint32_t)CYHAL_SDHC_CARD_INTERRUPT & obj->irq_cause)) if (0U != (obj->irq_cause & CY_SD_HOST_CARD_INTERRUPT))
{ {
uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base); uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base);
@ -897,20 +963,29 @@ cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t l
cy_en_sd_host_erase_type_t eraseType = CY_SD_HOST_ERASE_ERASE; cy_en_sd_host_erase_type_t eraseType = CY_SD_HOST_ERASE_ERASE;
uint32_t i = SDHC_RETRY_TIMES; uint32_t i = SDHC_RETRY_TIMES;
uint32_t cardStatus; uint32_t cardStatus;
uint32_t regIntrSts = Cy_SD_Host_GetNormalInterruptMask(obj->base);
if (obj->emmc) if (obj->emmc)
{ {
eraseType = CY_SD_HOST_ERASE_TRIM; eraseType = CY_SD_HOST_ERASE_TRIM;
} }
/* First clear out the transfer and command complete statuses */
Cy_SD_Host_ClearNormalInterruptStatus(obj->base, (CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE));
/* Disable CMD Done interrupt, will be enabled after transition is complete */
Cy_SD_Host_SetNormalInterruptMask(obj->base, (regIntrSts & (uint32_t)~(CY_SD_HOST_XFER_COMPLETE | CY_SD_HOST_CMD_COMPLETE)));
driverRet = Cy_SD_Host_Erase(obj->base, startAddr, (startAddr + length), eraseType, &obj->context); driverRet = Cy_SD_Host_Erase(obj->base, startAddr, (startAddr + length), eraseType, &obj->context);
if (CY_SD_HOST_SUCCESS != driverRet) if (CY_SD_HOST_SUCCESS != driverRet)
{ {
ret = CY_RSLT_TYPE_ERROR; ret = CY_RSLT_TYPE_ERROR;
} }
else
driverRet = Cy_SD_Host_PollCmdComplete(obj->base); {
driverRet = Cy_SD_Host_PollCmdComplete(obj->base);
}
if (CY_SD_HOST_SUCCESS != driverRet) if (CY_SD_HOST_SUCCESS != driverRet)
{ {
@ -945,8 +1020,11 @@ cy_rslt_t cyhal_sdhc_erase(const cyhal_sdhc_t *obj, uint32_t startAddr, size_t l
Cy_SysLib_Delay(SDHC_EMMC_TRIM_DELAY_MS); Cy_SysLib_Delay(SDHC_EMMC_TRIM_DELAY_MS);
} }
/* Restore interrupts after transition */
Cy_SD_Host_SetNormalInterruptMask(obj->base, regIntrSts);
/* Enable SD Card interrupt because it was disabled in interrupt handler */ /* Enable SD Card interrupt because it was disabled in interrupt handler */
if ((uint32_t) CYHAL_SDHC_CARD_INTERRUPT == ((uint32_t)CYHAL_SDHC_CARD_INTERRUPT & obj->irq_cause)) if (0U != (obj->irq_cause & CY_SD_HOST_CARD_INTERRUPT))
{ {
uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base); uint32_t intrStsEn = Cy_SD_Host_GetNormalInterruptEnable(obj->base);
@ -1001,85 +1079,63 @@ void cyhal_sdhc_register_callback(cyhal_sdhc_t *obj, cyhal_sdhc_event_callback_t
void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intrPriority, bool enable) void cyhal_sdhc_enable_event(cyhal_sdhc_t *obj, cyhal_sdhc_event_t event, uint8_t intrPriority, bool enable)
{ {
const uint8_t eventCount = 12; uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base);
const uint32_t eventMap[12][2] =
{
{ (uint32_t)CYHAL_SDHC_CMD_COMPLETE, (uint32_t)CY_SD_HOST_CMD_COMPLETE},
{ (uint32_t)CYHAL_SDHC_XFER_COMPLETE, (uint32_t)CY_SD_HOST_XFER_COMPLETE },
{ (uint32_t)CYHAL_SDHC_BGAP_EVENT, (uint32_t)CY_SD_HOST_BGAP },
{ (uint32_t)CYHAL_SDHC_DMA_INTERRUPT, (uint32_t)CY_SD_HOST_DMA_INTERRUPT },
{ (uint32_t)CYHAL_SDHC_BUF_WR_READY, (uint32_t)CY_SD_HOST_BUF_WR_READY },
{ (uint32_t)CYHAL_SDHC_BUF_RD_READY, (uint32_t)CY_SD_HOST_BUF_RD_READY },
{ (uint32_t)CYHAL_SDHC_CARD_INSERTION, (uint32_t)CY_SD_HOST_CARD_INSERTION },
{ (uint32_t)CYHAL_SDHC_CARD_REMOVAL, (uint32_t)CY_SD_HOST_CARD_REMOVAL },
{ (uint32_t)CYHAL_SDHC_CARD_INTERRUPT, (uint32_t)CY_SD_HOST_CARD_INTERRUPT },
{ (uint32_t)CYHAL_SDHC_FX_EVENT, (uint32_t)CY_SD_HOST_FX_EVENT },
{ (uint32_t)CYHAL_SDHC_CQE_EVENT, (uint32_t)CY_SD_HOST_CQE_EVENT },
{ (uint32_t)CYHAL_SDHC_ERR_INTERRUPT, (uint32_t)CY_SD_HOST_ERR_INTERRUPT },
};
uint32_t interruptMask;
uint32_t interruptEnable;
interruptEnable = Cy_SD_Host_GetNormalInterruptEnable(obj->base);
interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base);
IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num]; IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num];
NVIC_SetPriority(irqn, intrPriority); NVIC_SetPriority(irqn, intrPriority);
if(enable == true) if(enable == true)
{ {
obj->irq_cause |= event;
/* Enable specific interrupt */ /* Enable specific interrupt */
if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS) if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
{ {
for (int i = 0; i < eventCount; i++) obj->irq_cause |= event;
uint32_t event_count = SDHC_EVENTS_NUM;
uint8_t i;
for (i = 0; i < event_count; i++)
{ {
const uint32_t *map_entry = eventMap[i]; const uint32_t *map_entry = eventMap[i];
if ((map_entry[0] & obj->irq_cause) > 0) if ((map_entry[SDHC_EVENT] & obj->irq_cause) != 0)
{ {
interruptEnable |= map_entry[1]; interruptMask |= map_entry[SDHC_ISR];
interruptMask |= map_entry[1];
} }
} }
} }
/* Enable all interrupts */ /* Enable all interrupts */
else else
{ {
interruptEnable = SDIO_ALL_INTERRUPTS_ENABLE_MASK; interruptMask = SDIO_SET_ALL_INTERRUPTS_MASK;
interruptMask = SDIO_SET_ALL_INTERRUPTS_MASK; obj->irq_cause = SDIO_SET_ALL_INTERRUPTS_MASK;
obj->irq_cause = (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS;
} }
} }
/* Disable interrupt */ /* Disable interrupt */
else else
{ {
obj->irq_cause &= ~event;
if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS) if((uint32_t) event < (uint32_t) CYHAL_SDHC_ALL_INTERRUPTS)
{ {
for (int i = 0; i < eventCount; i++) obj->irq_cause &= ~event;
uint32_t event_count = SDHC_EVENTS_NUM;
uint8_t i;
for (i = 0; i < event_count; i++)
{ {
const uint32_t *map_entry = eventMap[i]; const uint32_t *map_entry = eventMap[i];
if ((map_entry[0] & obj->irq_cause) > 0) if ((map_entry[SDHC_EVENT] & obj->irq_cause) != 0)
{ {
interruptEnable &= ~map_entry[1]; interruptMask &= ~map_entry[SDHC_ISR];
interruptMask &= ~map_entry[1];
} }
} }
} }
/* Disable all interrupts */ /* Disable all interrupts */
else else
{ {
interruptEnable = SDIO_CLEAR_ALL_INTERRUPTS_ENABLE_MASK;
interruptMask = SDIO_CLEAR_ALL_INTERRUPTS_MASK; interruptMask = SDIO_CLEAR_ALL_INTERRUPTS_MASK;
obj->irq_cause = 0u; obj->irq_cause = SDIO_CLEAR_ALL_INTERRUPTS_MASK;
} }
} }
Cy_SD_Host_SetNormalInterruptMask(obj->base, interruptMask); Cy_SD_Host_SetNormalInterruptMask(obj->base, interruptMask);
Cy_SD_Host_SetNormalInterruptEnable(obj->base, interruptEnable);
} }
static void cyhal_sdio_irq_handler() static void cyhal_sdio_irq_handler()
@ -1129,6 +1185,12 @@ cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk,
obj->resource.type = CYHAL_RSC_INVALID; obj->resource.type = CYHAL_RSC_INVALID;
obj->base = NULL; obj->base = NULL;
obj->pin_cmd = CYHAL_NC_PIN_VALUE;
obj->pin_clk = CYHAL_NC_PIN_VALUE;
obj->pin_data0 = CYHAL_NC_PIN_VALUE;
obj->pin_data1 = CYHAL_NC_PIN_VALUE;
obj->pin_data2 = CYHAL_NC_PIN_VALUE;
obj->pin_data3 = CYHAL_NC_PIN_VALUE;
result = setup_pin( result = setup_pin(
cmd, cyhal_pin_map_sdhc_card_cmd, COUNT(cyhal_pin_map_sdhc_card_cmd), &(obj->pin_cmd)); cmd, cyhal_pin_map_sdhc_card_cmd, COUNT(cyhal_pin_map_sdhc_card_cmd), &(obj->pin_cmd));
@ -1713,7 +1775,6 @@ void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, ui
/* Configure interrupt-based event(s) */ /* Configure interrupt-based event(s) */
if (0U != ((uint32_t) event & (uint32_t) CYHAL_SDIO_ALL_INTERRUPTS)) if (0U != ((uint32_t) event & (uint32_t) CYHAL_SDIO_ALL_INTERRUPTS))
{ {
uint32_t interruptEnable = Cy_SD_Host_GetNormalInterruptEnable(obj->base);
uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base); uint32_t interruptMask = Cy_SD_Host_GetNormalInterruptMask(obj->base);
IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num]; IRQn_Type irqn = CYHAL_SDHC_IRQ_N[obj->resource.block_num];
@ -1721,21 +1782,16 @@ void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_irq_event_t event, ui
if (enable) if (enable)
{ {
interruptEnable |= event;
interruptMask |= event; interruptMask |= event;
obj->irq_cause |= event; obj->irq_cause |= event;
} }
else else
{ {
interruptEnable &= ~(event);
interruptMask &= ~(event); interruptMask &= ~(event);
obj->irq_cause &= ~event; obj->irq_cause &= ~event;
} }
Cy_SD_Host_SetNormalInterruptMask(obj->base, interruptMask); Cy_SD_Host_SetNormalInterruptMask(obj->base, interruptMask);
Cy_SD_Host_SetNormalInterruptEnable(obj->base, interruptEnable);
} }
/* Configure non-interrupt based event(s) */ /* Configure non-interrupt based event(s) */