Created
January 20, 2017 21:30
-
-
Save kylemanna/c7dd795167f8a8c315c31894394fdc8e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From bce26662da4b31e3f333142ebcbc24bef629c45e Mon Sep 17 00:00:00 2001 | |
From: Kyle Manna <kyle@kylemanna.com> | |
Date: Fri, 20 Jan 2017 13:27:41 -0800 | |
Subject: [PATCH] sai: Delay SAI DMA TX disable until FIFO is empty | |
This resolves a bug that otherwise would cause the last frame to be | |
written to the FIFO but the FIFO and transmitter are disable before the | |
frame is sent. The frame will be sent on the next enable of the | |
transmitter. | |
Instead, disable the transmitter after the FIFO has consumed the last | |
frame. | |
--- | |
devices/MKL27Z4/drivers/fsl_sai.c | 31 +++++++++++++++++++++++++++++++ | |
devices/MKL27Z4/drivers/fsl_sai.h | 10 ++++++++++ | |
devices/MKL27Z4/drivers/fsl_sai_dma.c | 4 ++-- | |
3 files changed, 43 insertions(+), 2 deletions(-) | |
diff --git a/devices/MKL27Z4/drivers/fsl_sai.c b/devices/MKL27Z4/drivers/fsl_sai.c | |
index 0d19d09..ee58cc7 100644 | |
--- a/devices/MKL27Z4/drivers/fsl_sai.c | |
+++ b/devices/MKL27Z4/drivers/fsl_sai.c | |
@@ -690,6 +690,37 @@ void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transf | |
EnableIRQ(s_saiTxIRQ[SAI_GetInstance(base)]); | |
} | |
+static void SAI_TxDisableAfterFIFOEmptyCallback(I2S_Type *base, sai_handle_t *handle) | |
+{ | |
+ /* Handle isn't actually a handle in this case */ | |
+ void *userData = (void*)handle; | |
+ assert(userData); | |
+ | |
+ SAI_TxDisableInterrupts(base, kSAI_FIFOWarningInterruptEnable); | |
+ SAI_TxEnable(base, false); | |
+} | |
+ | |
+void SAI_TxDisableAfterFIFOEmpty(I2S_Type *base, void *userData) | |
+{ | |
+ /* When called from SAI_TransferAbortSendDMA a sai_dma_handle_t* is passed | |
+ * in as userData and is only used to satisfy the IRQ test for the handle | |
+ * being set before calling SAI_TxDisableAfterFIFOEmptyCallback(). | |
+ * | |
+ * This is a hack. | |
+ */ | |
+ assert(userData); | |
+ | |
+ /* Handle isn't actually a handle in this case */ | |
+ s_saiHandle[SAI_GetInstance(base)][0] = userData; | |
+ | |
+ /* Set the isr pointer */ | |
+ s_saiTxIsr = SAI_TxDisableAfterFIFOEmptyCallback; | |
+ | |
+ /* Enable Tx irq */ | |
+ SAI_TxEnableInterrupts(base, kSAI_FIFOWarningInterruptEnable); | |
+ EnableIRQ(s_saiTxIRQ[SAI_GetInstance(base)]); | |
+} | |
+ | |
void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData) | |
{ | |
assert(handle); | |
diff --git a/devices/MKL27Z4/drivers/fsl_sai.h b/devices/MKL27Z4/drivers/fsl_sai.h | |
index be7563b..ac5a295 100644 | |
--- a/devices/MKL27Z4/drivers/fsl_sai.h | |
+++ b/devices/MKL27Z4/drivers/fsl_sai.h | |
@@ -838,6 +838,16 @@ void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle); | |
*/ | |
void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle); | |
+/*! | |
+ * @brief Called when a DMA TX needs to disable after the last byte is sent | |
+ * otherwise DMA driver will disable the driver when the last byte is | |
+ * written to the FIFO and disable the transmitter before it is sent. | |
+ * | |
+ * @param base SAI base pointer. | |
+ * @param handle Pointer to the sai_handle_t structure. | |
+ */ | |
+void SAI_TxDisableAfterFIFOEmpty(I2S_Type *base, void *userData); | |
+ | |
/*! @} */ | |
#if defined(__cplusplus) | |
diff --git a/devices/MKL27Z4/drivers/fsl_sai_dma.c b/devices/MKL27Z4/drivers/fsl_sai_dma.c | |
index b8afec2..80fc2ad 100644 | |
--- a/devices/MKL27Z4/drivers/fsl_sai_dma.c | |
+++ b/devices/MKL27Z4/drivers/fsl_sai_dma.c | |
@@ -361,8 +361,8 @@ void SAI_TransferAbortSendDMA(I2S_Type *base, sai_dma_handle_t *handle) | |
SAI_TxEnableDMA(base, kSAI_FIFOWarningDMAEnable, false); | |
#endif | |
- /* Disable Tx */ | |
- SAI_TxEnable(base, false); | |
+ /* Disable Tx after the FIFO is empty */ | |
+ SAI_TxDisableAfterFIFOEmpty(base, handle); | |
/* Set the handle state */ | |
handle->state = kSAI_Idle; | |
-- | |
2.11.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment