Part Number:TDA4VM
我使用了MCU_MCSPI0和MCU_MCSPI1分别对外接了两个外设。使用EB配置成异步中断模式。
使用mcsw中的mcal-spi驱动代码(ti-processor-sdk-rtos-j721e-evm-07_03_00_07)。
两路SPI配置如下:
MCU_MCSPI0 – seq0 – job0 – channel0 – 外设0
MCU_MCSPI1 – seq1 – job1 – channel1 – 外设1
调试发现问题,现象如下:
1. MCU_MCSPI0跟外设0通信都OK;(逻辑分析仪截取数据跟中断读取RAM数据都OK)
2. MCU_MCSPI1单独发送,逻辑分析仪截取发现没有数据发出;
3. 先发一包SPI0再发一包SPI1,SPI0数据OK,但是SPI1发送的数据是SPI0的,另外RAM读取数据都是0。
换种方法测试,将SPI0和SPI1的通道配置互换,即
MCU_MCSPI1 – seq0 – job0 – channel0 – 外设0
MCU_MCSPI0 – seq1 – job1 – channel1 – 外设1
测试结果是SPI1收发正常了,SPI0又出现了上面说明的异常情况。
以上调试结果分析,只有当外设配置的所有参数配置在第0的位置才好使,怀疑是MCAL源代码有问题,但也不排除是我的配置或者使用方法有问题。
请教下你们是否用MCAL的SPI代码调试过多路SPI,是否遇到以上的问题?
(注:1. 以上相关测试代码参照了MCAL examples中的McspiApp.c初始化及发送流程,但是examples中的官方测试代码只测试了一路SPI0对应一路chan0。 2. autosar配置文件是基于demo中的基础上使用EB修改配置的。)
Cherry Zhou:
您好我们已收到您的问题并升级到英文论坛,因感恩节假期,预计答复您的时间将稍晚。敬请谅解!
,
Andy Yau:
您好,请问针对以上问题英文论坛有更新吗,是否有反馈结果呢
,
Cherry Zhou:
抱歉回复晚了。
第二个序列 / 外设的配置似乎不太对。 交换 SPI0/SPI1 实例说明SPI 模块及其初始化是正常的,但 SEQ1 编程不对。
根据TI的文档,目前还尚未测试多个 MCSPI 实例配置:
https://www.ti2k.com/wp-content/uploads/ti2k/DeyiSupport_DSP_ug_spi_top.html
您是否能够提供您用来测试两个 SPI 模块的code?
,
Andy Yau:
感谢回答!
对于上面问题我为了方面描述给简化了一下,其实我们SPI接了三个外设,SPI0分别用CS1和CS2接两个外设,SPI1用CS0接一个外设。
目前只调试SPI0的CS1对应的外设0,跟SPI1的CS0对应的外设2。外设0跟外设2同时发送。
发送接口:
Std_ReturnType SpiWrapper_Xfer(Spi_ChanIdType channelId,Spi_DataBufferType* SrcDataBufferPtr,Spi_DataBufferType* DesDataBufferPtr,Spi_NumberOfDataType Length) {Spi_StatusTypestatus;uint32index;Spi_SequenceTypeseqId;Std_ReturnTyperetVal;const Spi_ConfigType *cfgPtr = &SpiDriver;#if (SPI_HW_STATUS_API == STD_ON)/* SPI HW unit should be free now - check */for (index = 0U; index < cfgPtr->maxHwUnit; index++){status = Spi_GetHWUnitStatus(cfgPtr->hwUnitCfg[index].hwUnitId);if(status != SPI_IDLE){return status;DRV_SPI_DBG("\x1b[1;31m[%s:%d]%d: HWUnitStatus is not idle!!\x1b[0m\n", __func__,__LINE__,OsWrapper_GetTimeMs());}}#endif/* #if (SPI_HW_STATUS_API == STD_ON) *//* Start the TX/RX */seqId= Spi_SeqConfig_PC[channelId].seqId;retVal= Spi_SetupEB(seqId,(Spi_DataBufferType*)SrcDataBufferPtr,(Spi_DataBufferType*)DesDataBufferPtr,Length);if (retVal != E_OK){DRV_SPI_DBG("\x1b[1;31m[%s:%d]%d: SPI Setup EB Failed!!\x1b[0m\n", __func__,__LINE__,OsWrapper_GetTimeMs());}retVal = Spi_AsyncTransmit(seqId);if (retVal != E_OK){DRV_SPI_DBG("\x1b[1;31m[%s:%d]%d: SPI Async transmit Failed!!\x1b[0m\n", __func__,__LINE__,OsWrapper_GetTimeMs());}return retVal; }下面是autosar配置生成的文件:
Spi_PBcfg.c:
CONST(struct Spi_ConfigType_s, SPI_CONFIG_DATA) SpiDriver = {.maxChannels = 3U,.maxJobs = 3U,.maxSeq= 3U,.maxHwUnit = 2U,.maxExtDevCfg = 3U,.udmaInstId= (uint32)UDMA_INST_ID_MCU_0,.cacheWbInv = (Spi_CacheWbInv)SpiApp_wbInvCache,.cacheWb = (Spi_CacheWb)SpiApp_wbCache,.cacheInv = (Spi_CacheInv)SpiApp_invCache,.channelCfg ={[0] ={.channelBufType = SPI_EB,.dataWidth = 8U,.defaultTxData = 255U,.maxBufLength = 256U,.transferType = SPI_MSB,},[1] ={.channelBufType = SPI_EB,.dataWidth = 8U,.defaultTxData = 255U,.maxBufLength = 256U,.transferType = SPI_MSB,},[2] ={.channelBufType = SPI_EB,.dataWidth = 8U,.defaultTxData = 255U,.maxBufLength = 256U,.transferType = SPI_MSB,},},.jobCfg ={[0] ={.jobPriority = SPI_JOB_PRIORITY_0,.hwUnitId = SPI_UNIT_MCU_MCSPI0,.Spi_JobEndNotification = SpiApp_McuMcspiJob0EndNotification,.channelPerJob = 1U,.channelList ={[0] = 0U,},},[1] ={.jobPriority = SPI_JOB_PRIORITY_0,.hwUnitId = SPI_UNIT_MCU_MCSPI0,.Spi_JobEndNotification = SpiApp_McuMcspiJob1EndNotification,.channelPerJob = 1U,.channelList ={[1] = 1U,},},[2] ={.jobPriority = SPI_JOB_PRIORITY_0,.hwUnitId = SPI_UNIT_MCU_MCSPI1,.Spi_JobEndNotification = SpiApp_McuMcspiJob2EndNotification,.channelPerJob = 1U,.channelList ={[2] = 2U,},},},.seqCfg ={[0] ={.seqInterruptible = (uint8) FALSE,.Spi_SequenceEndNotification = SpiApp_McuMcspiSeq0EndNotification,.jobPerSeq = 1U,.jobList ={0U,},},[1] ={.seqInterruptible = (uint8) FALSE,.Spi_SequenceEndNotification = SpiApp_McuMcspiSeq1EndNotification,.jobPerSeq = 1U,.jobList ={1U,},},[2] ={.seqInterruptible = (uint8) FALSE,.Spi_SequenceEndNotification = SpiApp_McuMcspiSeq2EndNotification,.jobPerSeq = 1U,.jobList ={2U,},},},.hwUnitCfg ={[0] ={.hwUnitId = SPI_UNIT_MCU_MCSPI0,.enabledmaMode = (boolean)FALSE,.dmaTxChIntrNum = 0,.dmaRxChIntrNum = 0,},[1] ={.hwUnitId = SPI_UNIT_MCU_MCSPI1,.enabledmaMode = (boolean)FALSE,.dmaTxChIntrNum = 0,.dmaRxChIntrNum = 0,},},.extDevCfg ={[0] ={.mcspi ={.csEnable = (uint16) TRUE,.csMode= SPI_SINGLE,.csPolarity = SPI_LOW,.csIdleTime = SPI_DATADELAY_2,.clkDivider = 48U,.clkMode = SPI_CLK_MODE_1,.txRxMode= SPI_TX_RX_MODE_BOTH,.startBitEnable =(uint16) FALSE,.startBitLevel= SPI_LOW,.receptionLineEnable= DATA_LINE_1_RECEPTION,.transmissionLineEnable= DATA_LINE_0_TRANSMISSION,},},[1] ={.mcspi ={.csEnable = (uint16) TRUE,.csMode= SPI_SINGLE,.csPolarity = SPI_LOW,.csIdleTime = SPI_DATADELAY_2,.clkDivider = 96U,.clkMode = SPI_CLK_MODE_1,.txRxMode= SPI_TX_RX_MODE_BOTH,.startBitEnable =(uint16) FALSE,.startBitLevel= SPI_LOW,.receptionLineEnable= DATA_LINE_1_RECEPTION,.transmissionLineEnable= DATA_LINE_0_TRANSMISSION,},},[2] ={.mcspi ={.csEnable = (uint16) TRUE,.csMode= SPI_CONTINUOUS,.csPolarity = SPI_LOW,.csIdleTime = SPI_DATADELAY_2,.clkDivider = 48U,.clkMode = SPI_CLK_MODE_1,.txRxMode= SPI_TX_RX_MODE_BOTH,.startBitEnable =(uint16) FALSE,.startBitLevel= SPI_LOW,.receptionLineEnable= DATA_LINE_1_RECEPTION,.transmissionLineEnable= DATA_LINE_0_TRANSMISSION,},},}, };Spi_Cfg.c:
CONST(Spi_ChannelConfigType_PC, SPI_CONFIG_DATA) Spi_ChannelConfig_PC[3] = {[0] ={.channelId = SpiConf_SpiChannel_SpiChannel_0,},[1] ={.channelId = SpiConf_SpiChannel_SpiChannel_1,},[2] ={.channelId = SpiConf_SpiChannel_SpiChannel_2,}, };CONST(Spi_JobConfigType_PC, SPI_CONFIG_DATA) Spi_JobConfig_PC[3] = {[0] ={.jobId = SpiConf_SpiJob_SpiJob_0,.csPin = SpiConf_SpiExternalDevice_CS0,.externalDeviceCfgId = (uint8)0U,},[1] ={.jobId = SpiConf_SpiJob_SpiJob_1,.csPin = SpiConf_SpiExternalDevice_CS1,.externalDeviceCfgId = (uint8)1U,},[2] ={.jobId = SpiConf_SpiJob_SpiJob_2,.csPin = SpiConf_SpiExternalDevice_CS2,.externalDeviceCfgId = (uint8)2U,}, };CONST(Spi_SeqConfigType_PC, SPI_CONFIG_DATA) Spi_SeqConfig_PC[3] = {[0] ={.seqId = SpiConf_SpiSequence_SpiSequence_0,},[1] ={.seqId = SpiConf_SpiSequence_SpiSequence_1,},[2] ={.seqId = SpiConf_SpiSequence_SpiSequence_2,}, };Spi_Cfg.h
#define SPI_VARIANT_POST_BUILD (STD_ON)/***\brief Pre Compile config macro name.*//** \brief Buffer mode - Internal or External or Both */ #define SPI_CHANNELBUFFERS(SPI_EB)/** \brief Internal Buffer length in bytes - applicable only for SPI_IB */ #define SPI_IB_MAX_LENGTH(0U)/** \brief Enable/disable SPI dev detect error */ #define SPI_DEV_ERROR_DETECT(STD_ON)/** \brief Enable/disable SPI job log */ #define SPI_JOB_LOG(STD_ON)/** \brief Maximum job log entries when logging is ON */ #define SPI_MAX_JOB_LOG(100U)/** \brief Enable/disable SPI DMA Support */ #define SPI_MAX_HW_DMA_UNIT(0U)/** \brief Enable/disable SPI DMA Support */ #define SPI_DMA_ENABLE(STD_OFF)/** Scalability levels*/ /** \brief Basic Synchronous functions */ #define SPI_LEVEL_0(0U) /** \brief Basic Asynchronous functions */ #define SPI_LEVEL_1(1U) /** \brief Synchronous and Asynchronous functions */ #define SPI_LEVEL_2(2U)/** \brief Concurrent sync transmit support - by defualt this is off */ #define SPI_SUPPORT_CONCURRENT_SYNC_TRANSMIT(STD_OFF)/** \brief Scalability level */ #define SPI_SCALEABILITY(SPI_LEVEL_1)/** \brief Enable/disable SPI get version info API */ #define SPI_VERSION_INFO_API(STD_ON)/** \brief Enable/disable SPI HW Status API */ #define SPI_HW_STATUS_API(STD_ON)/** \brief Enable/disable SPI cancel API */ #define SPI_CANCEL_API(STD_ON)/** All below macros are used for static memory allocation and can be changed to* match the usecase requirements.*/ /** \brief Maximum channels allowed per job */ #define SPI_MAX_CHANNELS_PER_JOB(3U)/** \brief Maximum jobs allowed per sequence */ #define SPI_MAX_JOBS_PER_SEQ(3U)/** \brief Maximum channels across all jobs/sequence/hwunit */ #define SPI_MAX_CHANNELS(3U)/** \brief Maximum jobs across all sequence/hwunit */ #define SPI_MAX_JOBS(3U)/** \brief Maximum sequence across all hwunit */ #define SPI_MAX_SEQ(3U)/***\brief Maximum HW unit - This should match the sum for the below units ISR*which are ON.*/ #define SPI_MAX_HW_UNIT(8U)/***\brief Maximum external device cfg*/ #define SPI_MAX_EXT_DEV(11U)/*All below macros are used for enabling the ISR for a particular hardware.*//** \brief Enable/disable SPI MCU MCSPI0 unit ISR */#define SPI_UNIT_MCU_MCSPI0_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCU MCSPI1 unit ISR */#define SPI_UNIT_MCU_MCSPI1_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCU MCSPI2 unit ISR */#define SPI_UNIT_MCU_MCSPI2_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI0 unit ISR */#define SPI_UNIT_MCSPI0_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI1 unit ISR */#define SPI_UNIT_MCSPI1_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI2 unit ISR */#define SPI_UNIT_MCSPI2_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI3 unit ISR */#define SPI_UNIT_MCSPI3_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI4 unit ISR */#define SPI_UNIT_MCSPI4_ACTIVE(STD_ON)/** \brief Enable/disable SPI MCSPI5 unit ISR */#define SPI_UNIT_MCSPI5_ACTIVE(STD_OFF)/** \brief Enable/disable SPI MCSPI6 unit ISR */#define SPI_UNIT_MCSPI6_ACTIVE(STD_OFF)/** \brief Enable/disable SPI MCSPI7 unit ISR */#define SPI_UNIT_MCSPI7_ACTIVE(STD_OFF)/** \brief ISR type */ #define SPI_ISR_TYPE(SPI_ISR_CAT1)/** \brief OS counter ID - used for timeout in case of error */ #define SPI_OS_COUNTER_ID((CounterType)OsCounter_0)/***\brief SPI timeout - used in McSPI IP reset*Each tick is 31.25us (for 32K Counter). Wait for 100ms which comes to*below value*/ #define SPI_TIMEOUT_DURATION(32000U)/** \brief Enable/disable SPI register read back API */ #define SPI_REGISTER_READBACK_API(STD_ON)/** \brief Symbolic Name Channel Id- 0 SpiChannel_0 */ #define SpiConf_SpiChannel_SpiChannel_0(0U) /** \brief Symbolic Name Channel Id- 1 SpiChannel_1 */ #define SpiConf_SpiChannel_SpiChannel_1(1U) /** \brief Symbolic Name Channel Id- 2 SpiChannel_2 */ #define SpiConf_SpiChannel_SpiChannel_2(2U)/** \brief Symbolic Name Chip Select- 0 */ #define SpiConf_SpiExternalDevice_CS0 (SPI_CS1)/** \brief Symbolic Name Job Id - 0 SpiJob_0 */ #define SpiConf_SpiJob_SpiJob_0(0U)/** \brief Symbolic Name Chip Select- 1 */ #define SpiConf_SpiExternalDevice_CS1 (SPI_CS2)/** \brief Symbolic Name Job Id - 1 SpiJob_1 */ #define SpiConf_SpiJob_SpiJob_1(1U)/** \brief Symbolic Name Chip Select- 2 */ #define SpiConf_SpiExternalDevice_CS2 (SPI_CS0)/** \brief Symbolic Name Job Id - 2 SpiJob_2 */ #define SpiConf_SpiJob_SpiJob_2(2U)/** \brief Symbolic Name Sequence Id - 0 SpiSequence_0 */ #define SpiConf_SpiSequence_SpiSequence_0(0U) /** \brief Symbolic Name Sequence Id - 1 SpiSequence_1 */ #define SpiConf_SpiSequence_SpiSequence_1(1U) /** \brief Symbolic Name Sequence Id - 2 SpiSequence_2 */ #define SpiConf_SpiSequence_SpiSequence_2(2U)/** \brief Symbolic Name HW Unit - 0 */ #define SpiConf_SpiExternalDevice_HwUnitId0(CSIB0) /** \brief Symbolic Name HW Unit - 1 */ #define SpiConf_SpiExternalDevice_HwUnitId0(CSIB0) /** \brief Symbolic Name HW Unit - 2 */ #define SpiConf_SpiExternalDevice_HwUnitId1(CSIB1)/***\name SPI DEM Error codes to report**Pre-compile switches for enabling/disabling DEM events*@{*/ #define DemConf_DemEventParameter_SPI_DEM_NO_EVENT (0xFFFFU) #define SPI_DEM_NO_EVENT DemConf_DemEventParameter_SPI_DEM_NO_EVENT#ifndef SPI_E_HARDWARE_ERROR /** \brief Hardware failed */ #define SPI_E_HARDWARE_ERROR(DemConf_DemEventParameter_SPI_E_HARDWARE_ERROR) #endif/* @} *//* ========================================================================== */ /*Structures and Enums*/ /* ========================================================================== *//** \briefCache write-back invalidate function */ extern void SpiApp_wbInvCache(uint8 *buf, uint16 len); /** \brief Cache write-back function */ extern void SpiApp_wbCache(uint8 *buf, uint16 len); /** \brief Cache invalidate function */ extern void SpiApp_invCache(uint8 *buf, uint16 len);/** \brief SPI Configuration struct declaration */ extern const struct Spi_ConfigType_s SpiDriver;/** \brief SPI Channel PC Configuration struct declaration */ extern const struct Spi_ChannelConfigType_PC_s Spi_ChannelConfig_PC[SPI_MAX_CHANNELS];/** \brief SPI Job PC Configuration struct declaration */ extern const struct Spi_JobConfigType_PC_s Spi_JobConfig_PC[SPI_MAX_JOBS];/** \brief SPI Sequence PC Configuration struct declaration */ extern const struct Spi_SeqConfigType_PC_s Spi_SeqConfig_PC[SPI_MAX_SEQ];测试两个SPI模块就是调用上面的SpiWrapper_Xfer接口,定义全局TX和RX buffer,传入channel。大致如下:
SpiWrapper_Xfer(0, TxBuffer0, RxBuffer0, 8);
SpiWrapper_Xfer(2, TxBuffer2, RxBuffer2, 8);
逻辑分析仪截取SPI总线数据,TxBuffer0、RxBuffer0正常,SpiApp_McuMcspiSeq0EndNotification中读取的数据也正常。
异常的是TxBuffer2发的竟然是TxBuffer0的数据!
然后SpiApp_McuMcspiSeq2EndNotification中读取RxBuffer2的数据都是0,但是逻辑分析仪截取数据看RX是有数据的。
以上,看看能否帮忙分析出问题点。
另外我对您的回复“第二个序列 / 外设的配置似乎不太对。”这句话不太理解,是说我的配置不对吗?
跟上面的稍有不同,详细配置如下:
MCU_MCSPI0 – CS1 – seq0 – job0 – channel0 – 外设0
MCU_MCSPI0 – CS2 – seq1 – job1 – channel1 – 外设1
MCU_MCSPI1 – CS0 – seq2 – job2 – channel2 – 外设2
,
Andy Yau:
哈喽,chan2正常了。修改地方是把SPI0-CS2改为DIO控制,csmode设置为SINGLE。chan0的SPI0-CS1不实用DIO,csmode设置为CONTINOUS。但是还是只能先发chan0再发chan2才好使,先发chan2就会失败。
,
Cherry Zhou:
好的收到,已帮您把最新的情况跟进给工程师,如果有新的消息会尽快给到您。