Hello,
I'm unsure whatever my problems comes from a wrong initialization, or actual bug in the spdif_edma driver, or possibly the MCUXpresso config tool. The crash causes the IMXRT to become unresponsive both to my jtag (segger) and the on-board DAP debugger. I need to set it to boot from the sd-card, reflash with working firmware, and set it to boot from the device again. It's not something simple as a hardfault, as the mcu becomes completely unresponsive.
My peripheral.c/peripheral.h is generated by the MCUXpresso config tool (v5). Using the newest SDK (2.5.0).
This is peripheral.h:
/***********************************************************************************************************************
* This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file
* will be overwritten if the respective MCUXpresso Config Tools is used to update this file.
**********************************************************************************************************************/
#ifndef _PERIPHERALS_H_
#define _PERIPHERALS_H_
/***********************************************************************************************************************
* Included files
**********************************************************************************************************************/
#include "fsl_edma.h"
#include "fsl_dmamux.h"
#include "fsl_common.h"
#include "fsl_spdif.h"
#include "fsl_spdif_edma.h"
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/***********************************************************************************************************************
* Definitions
**********************************************************************************************************************/
/* Definitions for BOARD_InitPeripherals functional group */
/* Used DMA device. */
#define EDMA_1_DMA_BASEADDR DMA0
/* Associated DMAMUX device that is used for muxing of requests. */
#define EDMA_1_DMAMUX_BASEADDR DMAMUX
/* BOARD_InitPeripherals defines for SPDIF */
/* Definition of peripheral ID. */
#define SPDIF_1_PERIPHERAL SPDIF
/* Definition Tx clock source frequency. */
#define SPDIF_1_TX_CLK_FREQ 30000000U
/* Definition Tx sample rate. */
#define SPDIF_1_TX_SAMPLE_RATE 44100U
/* Definition Tx eDMA transfer buffer size. */
#define SPDIF_1_TX_EDMA_BUFFER_SIZE 6U
/* SPDIF_1 eDMA source request. */
#define SPDIF_1_TX_LEFT_DMA_REQUEST kDmaRequestMuxSpdifTx
/* Selected eDMA channel number. */
#define SPDIF_1_TX_LEFT_DMA_CHANNEL 0
/* DMAMUX device that is used for muxing of the request. */
#define SPDIF_1_TX_LEFT_DMAMUX_BASEADDR DMAMUX
/* Used DMA device. */
#define SPDIF_1_TX_LEFT_DMA_BASEADDR DMA0
/* SPDIF_1 eDMA source request. */
#define SPDIF_1_TX_RIGHT_DMA_REQUEST kDmaRequestMuxSpdifTx
/* Selected eDMA channel number. */
#define SPDIF_1_TX_RIGHT_DMA_CHANNEL 1
/* DMAMUX device that is used for muxing of the request. */
#define SPDIF_1_TX_RIGHT_DMAMUX_BASEADDR DMAMUX
/* Used DMA device. */
#define SPDIF_1_TX_RIGHT_DMA_BASEADDR DMA0
/***********************************************************************************************************************
* Global variables
**********************************************************************************************************************/
extern const edma_config_t eDMA_1_config;
extern const spdif_config_t SPDIF_1_config;
extern edma_handle_t SPDIF_1_TX_Left_Handle;
extern edma_handle_t SPDIF_1_TX_Right_Handle;
extern uint8_t SPDIF_1_txLeftData[SPDIF_XFER_QUEUE_SIZE][SPDIF_1_TX_EDMA_BUFFER_SIZE];
extern uint8_t SPDIF_1_txRightData[SPDIF_XFER_QUEUE_SIZE][SPDIF_1_TX_EDMA_BUFFER_SIZE];
extern spdif_edma_handle_t SPDIF_1_tx_SPDIF_eDMA_Handle;
/***********************************************************************************************************************
* Callback functions
**********************************************************************************************************************/
/* SPDIF eDMA callback function for the SPDIF_1 component (init. function BOARD_InitPeripherals)*/
extern void rxDMAcallback(SPDIF_Type *, spdif_edma_handle_t *, status_t, void *);
/***********************************************************************************************************************
* Initialization functions
**********************************************************************************************************************/
void BOARD_InitPeripherals(void);
/***********************************************************************************************************************
* BOARD_InitBootPeripherals function
**********************************************************************************************************************/
void BOARD_InitBootPeripherals(void);
#if defined(__cplusplus)
}
#endif
#endif /* _PERIPHERALS_H_ */
And my peripheral.c:
/***********************************************************************************************************************
* This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file
* will be overwritten if the respective MCUXpresso Config Tools is used to update this file.
**********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
product: Peripherals v5.0
processor: MIMXRT1052xxxxB
package_id: MIMXRT1052DVL6B
mcu_data: ksdk2_0
processor_version: 5.0.0
board: IMXRT1050-EVKB
functionalGroups:
- name: BOARD_InitPeripherals
called_from_default_init: true
selectedCore: core0
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
component:
- type: 'system'
- type_id: 'system_54b53072540eeeb8f8e9343e71f28176'
- global_system_definitions: []
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
/***********************************************************************************************************************
* Included files
**********************************************************************************************************************/
#include "peripherals.h"
/***********************************************************************************************************************
* BOARD_InitPeripherals functional group
**********************************************************************************************************************/
/***********************************************************************************************************************
* eDMA_1 initialization code
**********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
instance:
- name: 'eDMA_1'
- type: 'edma'
- mode: 'basic'
- type_id: 'edma_a23fca76a894e1bcdf9d01a687505ff9'
- functional_group: 'BOARD_InitPeripherals'
- peripheral: 'DMA0'
- config_sets:
- fsl_edma:
- common_settings:
- enableContinuousLinkMode: 'false'
- enableHaltOnError: 'true'
- enableRoundRobinArbitration: 'false'
- enableDebugMode: 'false'
- edma_channels: []
- quick_selection: 'default'
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
const edma_config_t eDMA_1_config = {
.enableContinuousLinkMode = false,
.enableHaltOnError = true,
.enableRoundRobinArbitration = false,
.enableDebugMode = false
};
void eDMA_1_init(void) {
}
/***********************************************************************************************************************
* SPDIF_1 initialization code
**********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
instance:
- name: 'SPDIF_1'
- type: 'spdif'
- mode: 'edma'
- type_id: 'spdif_040614b5288766ad77a1a386b39d0a3c'
- functional_group: 'BOARD_InitPeripherals'
- peripheral: 'SPDIF'
- config_sets:
- fsl_spdif:
- usage: 'transmit'
- wrapper:
- tx_spdif_config:
- isTxAutoSync: 'true'
- txClkSource: 'SpdifClock'
- txSourceFreq: 'BOARD_BootClockRUN'
- txSampleRate: '44.1kHz'
- txFullSelect: 'kSPDIF_TxEmpty0Sample'
- txSource: 'kSPDIF_txNormal'
- validityConfig: 'kSPDIF_validityFlagAlwaysClear'
- edma_channels:
- enable_edma_channel_left: 'true'
- edma_channel_left:
- eDMAn: '0'
- eDMA_source: 'kDmaRequestMuxSpdifTx'
- enable_custom_name: 'false'
- enable_edma_channel_right: 'true'
- edma_channel_right:
- eDMAn: '1'
- eDMA_source: 'kDmaRequestMuxSpdifTx'
- enable_custom_name: 'false'
- spdif_edma_handle:
- enable_custom_name: 'false'
- init_transfer: 'true'
- transfer:
- dataSize: '6'
- allocate_buffer: 'true'
- init_callback: 'true'
- callback_fcn: 'rxDMAcallback'
- user_data: ''
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
const spdif_config_t SPDIF_1_config = {
.isTxAutoSync = true,
.isRxAutoSync = false,
.DPLLClkSource = 1U,
.txClkSource = 1U,
.rxFullSelect = kSPDIF_RxFull8Samples,
.txFullSelect = kSPDIF_TxEmpty0Sample,
.uChannelSrc = kSPDIF_UChannelFromTx,
.txSource = kSPDIF_txNormal,
.validityConfig = kSPDIF_validityFlagAlwaysClear,
.gain = kSPDIF_GAIN_8
};
edma_handle_t SPDIF_1_TX_Left_Handle;
edma_handle_t SPDIF_1_TX_Right_Handle;
spdif_edma_handle_t SPDIF_1_tx_SPDIF_eDMA_Handle;
uint8_t SPDIF_1_txLeftData[SPDIF_XFER_QUEUE_SIZE][SPDIF_1_TX_EDMA_BUFFER_SIZE];
uint8_t SPDIF_1_txRightData[SPDIF_XFER_QUEUE_SIZE][SPDIF_1_TX_EDMA_BUFFER_SIZE];
void SPDIF_1_init(void) {
/* Buffer iterator */
uint32_t i;
/* Create the eDMA SPDIF_1_TX_Left_Handle handle */
EDMA_CreateHandle(&SPDIF_1_TX_Left_Handle, SPDIF_1_TX_LEFT_DMA_BASEADDR, SPDIF_1_TX_LEFT_DMA_CHANNEL);
/* Create the eDMA SPDIF_1_TX_Right_Handle handle */
EDMA_CreateHandle(&SPDIF_1_TX_Right_Handle, SPDIF_1_TX_RIGHT_DMA_BASEADDR, SPDIF_1_TX_RIGHT_DMA_CHANNEL);
/* Set the source kDmaRequestMuxSpdifTx request in the DMAMUX */
DMAMUX_SetSource(SPDIF_1_TX_LEFT_DMAMUX_BASEADDR, SPDIF_1_TX_LEFT_DMA_CHANNEL, SPDIF_1_TX_LEFT_DMA_REQUEST);
/* Enable the 0 channel in the DMAMUX */
DMAMUX_EnableChannel(SPDIF_1_TX_LEFT_DMAMUX_BASEADDR, SPDIF_1_TX_LEFT_DMA_CHANNEL);
/* Set the source kDmaRequestMuxSpdifTx request in the DMAMUX */
DMAMUX_SetSource(SPDIF_1_TX_RIGHT_DMAMUX_BASEADDR, SPDIF_1_TX_RIGHT_DMA_CHANNEL, SPDIF_1_TX_RIGHT_DMA_REQUEST);
/* Enable the 1 channel in the DMAMUX */
DMAMUX_EnableChannel(SPDIF_1_TX_RIGHT_DMAMUX_BASEADDR, SPDIF_1_TX_RIGHT_DMA_CHANNEL);
/* Create the SPDIF Tx eDMA handle. */
SPDIF_TransferTxCreateHandleEDMA(SPDIF_1_PERIPHERAL, &SPDIF_1_tx_SPDIF_eDMA_Handle, rxDMAcallback, NULL, &SPDIF_1_TX_Left_Handle, &SPDIF_1_TX_Right_Handle);
/* Assign allocated buffer to the handle */
for (i = 0U; i < SPDIF_XFER_QUEUE_SIZE; i++) {
SPDIF_1_tx_SPDIF_eDMA_Handle.spdifQueue[i].dataSize = SPDIF_1_TX_EDMA_BUFFER_SIZE;
SPDIF_1_tx_SPDIF_eDMA_Handle.spdifQueue[i].leftData = &(SPDIF_1_txLeftData[i][0]);
SPDIF_1_tx_SPDIF_eDMA_Handle.spdifQueue[i].rightData = &(SPDIF_1_txRightData[i][0]);
}
/* Initialize the SPDIF. */
SPDIF_Init(SPDIF_1_PERIPHERAL, &SPDIF_1_config);
/* Set SPDIF TX sample rate to 44.1kHz. */
SPDIF_TxSetSampleRate(SPDIF_1_PERIPHERAL, SPDIF_1_TX_SAMPLE_RATE, SPDIF_1_TX_CLK_FREQ);
/* Enable SPDIF transmitter. */
SPDIF_TxEnable(SPDIF_1_PERIPHERAL, true);
/* Enable DMA requests from SPDIF. */
SPDIF_EnableDMA(SPDIF_1_PERIPHERAL, kSPDIF_TxDMAEnable, true);
}
/***********************************************************************************************************************
* Initialization functions
**********************************************************************************************************************/
void BOARD_InitPeripherals(void)
{
/* Global initialization */
DMAMUX_Init(EDMA_1_DMAMUX_BASEADDR);
EDMA_Init(EDMA_1_DMA_BASEADDR, &eDMA_1_config);
/* Initialize components */
eDMA_1_init();
SPDIF_1_init();
}
/***********************************************************************************************************************
* BOARD_InitBootPeripherals function
**********************************************************************************************************************/
void BOARD_InitBootPeripherals(void)
{
BOARD_InitPeripherals();
}
The crash happens in fsl_spdig_edma.c in "SPDIF_TransferTxCreateHandleEDMA", when trying to read the "base->SCR" register (line 265/266):
void SPDIF_TransferTxCreateHandleEDMA(SPDIF_Type *base,
spdif_edma_handle_t *handle,
spdif_edma_callback_t callback,
void *userData,
edma_handle_t *dmaLeftHandle,
edma_handle_t *dmaRightHandle)
{
//[...]
handle->count =
s_spdif_tx_watermark[(base->SCR & SPDIF_SCR_TXFIFOEMPTY_SEL_MASK) >> SPDIF_SCR_TXFIFOEMPTY_SEL_SHIFT];
I've checked myself and simply trying to read the base->SCR inside the function can cause the crash.
Any idea what might be causing this?
I'm not sure whatever it's a bug or not, but there are no examples for the spdif (using edma or not), and I've also found other bugs in the spdif driver. So I think it's possible that the spdif_edma might contain some bugs as well.
Is there any plan on making a spdif_edma example, like the one already made for SAI (and sai_edma)?
Hi mmlee,
I think there is a bug in peripherals.c. SPDIF_TransferTxCreateHandleEDMA() is called before SPDIF_Init(). When it read SPDIF_SCR register, SPDIF's clock is still gated. This cause a hardfault.
You can call SPDIF_Init() before it. Or just open the clock.
I'll report this bug. Thanks a lot!
Regards,
Jing
Thanks a lot, that's definitely part of the issue, and moving the SPDIF_Init() before the SPDIF_TransferTxCreateHandleEDMA(), stop crashes from occurring. I still have some issues with the spdif_edma: can it really be right that the edma should be set up to transferring 4 bytes to the spdif FIFO? The spdif FIFO is only 3bytes long (16x24)?
Hi mmlee,
The data handled by the SPDIF module is 24-bit wide. The 24-bit SPDIF data is aligned in the 24 least significant bits of the 32-bit shared peripheral bus data word. The 8 most significant bits of the 32-bit word are ignored by the SPDIF Transmitter when data is being stored in the Transmit FIFOs from the peripheral bus. The 8 most significant bits of
the 32-bit word are zeroed by the SPDIF Receiver module when the data is being read from the Receiver FIFOs to the peripheral bus.
Regards
Jing