This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:TI-RTOS
大家好
最近、我在 MSP_EXP430F5529LP 开发 板上配置了 SPI 主器件和 SPI 从器 件、在 TI-RTOS 两个任务下、我发现两个 SPI 相互交互。 当我关闭其中一个任务而另一个 SPI 工作正常时, 我尝试添加信标以保护 SPI_TRANSF()功能,问题仍然存在, 我放置断点,发现问题出现在下图中,导致 SPI 传输返回错误, SPI 从器件只能向外发送第一个字节。 谁能教我如何做、或者给我一个类似的例子、谢谢!
此致
XC.mo
2.代码
#define spiA1_TASKSTACKSIZE 512 SPI_Handle spiA1_master; spi_Params spiA1_master_params; Task_Structt spiA1_master_taskStructt; char spiA1_master_taskStack[spiA1_TASKSTACKSIZE]; GateMutex_handle gatemutex_handle; GateMutex_Params gatemutex_params; #define spiB1_TASKSTACKSIZE 512 SPI_Handle spiB1_slave; SPI_Params spiB1_slave_Params; Task_Structt spiB1_slave_taskStructt; Char spiB1_slave_taskStack[spiB1_TASKSTACKSIZE]; //semaphore_handle spiB1_semHandle; Semaphore_Params spiB1_semParams; Semaphore_Structp1_semStructP; //semaphore_handle protect SPI_transfer () semaphore_Params two_SPI_semParams; semaphore_Structt two_SPI_transferStructP; // // void spiA1transferCallbackFxn (SPI_handle、SPI_transaction_semCI_transaction* ;{smain_transfer_transaction_transaction_1s_transaction_high_transaction_transaction_transaction_s*; Semaphore_post (Semaphore_handle (&two_SPI_semStructP)); system_printf ("spiA1 transferCallbackFxn inter!\n"); system_flush(); }/* ==== uscia1_SPI taskFxn === *此函数的任务是静态创建的。 请参阅工程的.cfg 文件。 // void spiA1_master_taskFxn (UArg0、UArgarg1) { /*创建 I2C 以供使用*/ SPI_PARAMS_INIT (&spiA1_MASTER_PARAMS); spiA1_master_Params.transferMode = SPI_MODE_CALLACK; spiA1_master_Params.transferCallbackFxn = spiA1transferCallbackFxn; spiA1_master_Params.mode = SPI_MASTER; spiA1_master_Params.bitrate = 50000、 /*比特率 Hz*/ spiA1_master_Params.dataSize = 8; spiA1_master_Params.frameFormat = SPI_POL1_PHA1; spiA1_master = SPI_open (Board_SPIA1_master、&spiA1_MASTER_Params); if (spiA1_master == NULL){ System_abort ("初始化 SPI\n"时出错); } 否则{ system_printf ("spiA1已初始化!\n"); } system_flush(); //gatemute GateMutex_Params_init (&G); gatemutex_handle = GateMutex_create (&gatemutex_params、NULL); if (gatemutex_handle = NULL){ System_abort ("错误 GateMutex_create\n"); } 否则{ System_printf ("GateMutex_create OK!\n"); } char txbuf[5]={0x21、0x22、0x23、0x24、0x25}; char rxbuf[6]; uint8_t 计数; SPI_Transaction spiTransaction; while (1){ //Cs 低电平 Board_SPIA1_MASTER_CS_LOW; Semaphore_pend (Semaphore_handle (&two_SPI_semStructP)、BIOS_wait_forever); spiTransaction.txBuf = txbuf; spiTransaction.rxBuf =空; spiTransaction.count = 5; if (SPI_transfer (spiA1_master、&spiTransaction)= NULL){ System_printf ("spiA1总线故障\n"); system_flush(); } Task_sleep (1000); GPIO_TOGGLE (Board_LED_P1_0);; } } void spiB1_CS_Fxn1 (UArg arg) { Semaphore_post (semaphore_handle (&spiB1_semStructP)); //System_printf ("spiB1 CS P2_4中断回调!\n"); //System_flush(); } void spiB1_slave_taskFxn (UArg0、UArgarg1) { /*创建 SPI 供使用*/ SPI_PARAMS_INIT (&spiB1_SLAVE_PARAMS); spiB1_SLAVE_PARAMS.transferMode = SPI_MODE_CALLACK; spiB1_slave_Params.transferCallbackFxn = spiB1_transferCallbackFxn; spiB1_SLAVE_PARAMS.MODE = SPI_SLAVE; spiB1_slave_Params.dataSize = 8; spib1_slave = SPI_open (Board_SPIB1_slave、&spib1_slave_Params); if (spiB1_slave = NULL){ System_abort ("初始化 SPI B1\n"时出错); } 否则{ System_printf ("SPI B1已初始化!\n"); } system_flush(); //gatemute GateMutex_Params_init (&gatemutex_spiB1_params); gatemutex_spiB1_handle = GateMutex_create (&gatemutex_spiB1_params、NULL); if (gatemutex_spiB1_handle = NULL){ system_abort ("错误 gatemutex_spiB1_create\n"); } 否则{ system_printf ("gatemutex_spiB1_create OK!\n"); } system_flush(); //CS 信标 Semaphore_Params_init (&spiB1_semParams); spiB1_semParams.mode = semaphore_Mode_binary; Semaphore_construction (&spiB1_semStructP、0、&spiB1_semParams); //启用 CS (P2_4)中断 GPIO_setCallback (Board_SPIB1_SLAVE_CS_P2_4、(GPIO_CallbackFxn) spib1_CS_Fxn1);//大量早于 GPIO_enableInt () GPIO_enableInt (Board_SPIB1_SLAVE_CS_P2_4); char txbuf[5]={0x12、0x13、0x14、0x15、0x16}; SPI_Transaction spiTransaction spiTransaction; Task_sleep (100); while (1){ //根据 GPIO 中断判断 CS Semaphore_pend (Semaphore_handle (&spiB1_semStructP)、BIOS_WAIT_FOREVE); //保护 SPI_transfer () semaphore_pend (semaphore_handle (&two_SPI_semStructP)、BIOS_wait_forever); spiTransaction.txBuf = txbuf; spiTransaction.rxBuf = NULL; spiTransaction.count = 5; if (SPI_transfer (spiB1_slave、 &spiTransaction)=NULL){ System_printf ("spiB1总线故障\n"); System_flush (); } semaphore_post (semaphore_handle (&two_spi_semStructP)); Task_sleep (1000); GPIO_toggle (Board_LED_P4_7); } } int main (void) { /*呼叫板初始化函数*/ Board_initGeneral(); Board_initGPIO(); Board_initSPI(); //SPI 主器件 taskParams.arg0 = 1000; taskParams.STACKSIZE = spiA1_TASKSTACKSIZE; taskParams.stack = spiA1_master_taskStack (&S); Task_construction (&spiA1_master_taskStruct,(Task_Functr) a1_master_taskFxn、&taskParams、NULL); //spiB1从属设备 taskParams.arg0 = 1000; taskParams.STACKSIZE = spiB1_TASKSTACKSIZE; taskParams.stack = spiB1_slave_taskStack; Task_construct(&spiB1_slave_taskStruct,(Task_Functr )spiB1_slave_taskFxn,&taskParams,NULL ); //stwo_SPI 信号量受保护的 SPI_transfer () Semaphore_Params_init (&two_SPI_semParams); spiB1_semParams.mode = semaphore_Mode_binary; Semaphore_construction (&two_SPI_semStructP、1、&two_SPI_semParams); /*启动 BIOS */ BIOS_start(); 返回(0); }
您好 XC.mo、
我认为 spiB1_slave_taskFxn()中的 semaphore_post (&two_spi_semStructP)中存在该问题。
您已在回调模式下打开 SPIB1_SLAVE,因此当您从 spib1_slave_taskFxn ()中的 SPI_transfer ()返回时,传输可能仍在进行中,但您发布了"SPI 可用"信标2_SPI_semStructP。 这使得 spiA1_master_taskFxn ()从其 Semaphore_pend (&two_SPI_semStructP)调用进入 SPI_transfer ()、并且传递函数 SPIUSCIBDMA_transfer ()发现仍有一个正在进行的事务并返回失败。
您没有粘贴 spib1_transferCallbackFxn()的 SPIB1回调函数代码,因此我看不到它在做什么,但 spib1_slave_taskFxn()中的 semaphore_post (&two_spi_semStructP)不应该位于 spib1_slave_taskFxn()中,而是位于 spib1_transferCallbackFxn()中,类似于处理 fxn()中的 spi_semaphore()? 或者,将其保留为您所拥有的状态,但将 SPIB1的模式更改为阻塞,在这种情况下,当 SPI_TRANSFORT()返回 true 时,您就会知道您已经完成了传输。
此致、
- Rob
您能否确认两个 SPI (总共4个不同的 DMA 通道)使用不同的 TX 和 RX DMA 通道?
你好,Tooma
很抱歉、由于时间差、我刚回来。 你是对的。 两个 SPI 可以使用不同的 DMA 通道 来解决 SPI_TRANSF()功能 冲突,但 5529器件数据表中只有三个 DMA 通道用于外设, 我有两个 SPI、总共需要四个 DMA 通道(一个 SPI TX 和 RX)、 当我在 SPI 的 TX 或 RX 中使用其他通道(超过3个)时、XPi 的 TX 或 RX 无法发送或接收数据。 您能给我更多指导吗? 谢谢!
此致
XC.mo
msp430f5529器件数据表
我的 SPI 代码
/*
================================================ DMA ================================================
//
/*
=== MSP_EXP430F5529LP_isrDMA ===
*这是一个应用程序定义的 DMA ISR。 此 ISR 必须映射并调用
*相应的 Driver_event (handle) API 以指示完成的 DMA 传输。
*/
#include
#include
void MSP_EXP430F5529LP_isrDMA (UARg arg)
{
SPIUSCIADA_HWAttrs const *hwAttrsA;
SPIUSCIBDMA_HWAttrs const *hwAttrsB;
hwAttrsA =((SPI_Handle)&(SPI_CONFIG[0])->hwAttrs;
hwAttrsB =((SPI_Handle)&(SPI_CONFIG[1])->hwAttrs;
//调用 SPI DMA 函数,传递用于 WiFi 的 SPI 句柄
if (dma_getInterruptStatus (hwAttrsA->txDMAChannelIndex)=dma_int_active||
DMA_getInterruptStatus (hwAttrsA->rxDMAChannelIndex)=DMA_INT_ACTIVE
){
//dma_clearInterrupt (hwAttrsA->txDMAChannelIndex);
//dma_clearInterrupt (hwAttrsA->rxDMAChannelIndex);
//注:打印 CA 不会因为延迟而删除
System_printf ("SPIA-SPI_serviceISR------------ \r\n");
system_flush();
SPI_serviceISR ((SPI_Handle)&(SPI_CONFIG[0]));
}
if (dma_getInterruptStatus (hwAttrsB->txDMAChannelIndex)=dma_int_active||
DMA_getInterruptStatus (hwAttrsB->rxDMAChannelIndex)=DMA_INT_ACTIVE
){
//dma_clearInterrupt (hwAttrsB->txDMAChannelIndex);
//dma_clearInterrupt (hwAttrsB->rxDMAChannelIndex);
//注:打印 CA 不会因为延迟而删除
System_printf ("SPIB-SPI_serviceISR-------- \r\n");
system_flush();
SPI_serviceISR ((SPI_Handle)&(SPI_CONFIG[1]));
}
/*调用 SPI DMA 函数、传递用于 WiFi 的 SPI 句柄*/
//SPI_serviceISR ((SPI_Handle)&(SPI_CONFIG[0]));
//SPI_serviceISR ((SPI_Handle)&(SPI_CONFIG[1]));
}
/*
=========================== SPI ========================================================
*/
*放入子段中以允许 TI 链接器正确删除项目*/
#if defined (__TI_Compiler_version__)
#pragma DATA_SECTION (SPI_CONFIG、".CONST:SPI_CONFIG")
#pragma DATA_SECTION (spiUSCIBDMAHWAttrs、".CONST:USCIADMAATtrs)#spiHWendif include
#include
//
USCIA
//
SPIUSCIADA_Object spiUSCIADMAObjects[MSP_EXP430F5529LP_SPIA_COUNT];
uint8_t spiUSCIADDMAscratchBuf[MSP_EXP430F5529LP_SPIA_COUNT];
const SPIUSCIADM_SPIADM_={MSP430USCI_EXP5529LP_UST_SPIAD_DP_TRS = USCIAD_USTRS = USCI_EXP55430USTRS = USTREMALP55_IN_USTRIN_IN_IN_
{
baseAddr = USCI_A1_BASE、
时钟源 = USCI_A_SPI_CLOCKSOURCE_SMCLK、
.bitOrder = USCI_A_SPI_MSB_FIRST、
暂存缓冲区 = spiUSCIADDMAscratchBuf[0]、
defaultTxBufValue = 0xff、
/* DMA */
.dmaBaseAddr = dma_BASE、
/* Rx 通道*/
.rxDMAChannelIndex = DMA_CHANGE_1、
.rxDMASourcedTrigger = DMA_TRIGGERSOURCE_20、//查找设备 cheel
/* Tx 通道*/
TxDMAChannelIndex = DMA_CHANGE_0、
TxDMASourcedTrigger = DMA_TRIGGERSOURCE_21
}
};
//
USCIB
//
#pragma DATA_SECTION (spiUSCIADMAHWAttrs、".const:spiUSCIBDMAHWAttrs")
#include
SPIUSCIBDMA_Object spiUSCIBDMAObjects[MSP_EXP430F5529LP_SPIB_COUNT];
uint8_t spiUSCIBDMAscratchBuf[MSP_EXP430F5529LP_SPIB_COUNT];
const SPIUSCIBDMA_HWAttrs USCIBDMACR_BUSC5529LP_MSP_EXP430F55_PWMENT];const SPIAB_PWMENT
{
baseAddr = USCI_B1_BASE、
时钟源 = USCI_B_SPI_CLOCKSOURCE_SMCLK、
.bitOrder = USCI_B_SPI_MSB_FIRST、
暂存缓冲区 = spiUSCIBDMAscratchBuf[0]、
defaultTxBufValue = 0xff、
/* DMA */
.dmaBaseAddr = dma_BASE、
/* Rx 通道*/
.rxDMAChannelIndex = DMA_CHANGE_2、
.rxDMASourcedTrigger = DMA_TRIGGERSOURCE_22、//查找设备 cheel
/* Tx 通道*/
TxDMAChannelIndex = DMA_CHANGE_0、 //与此类似更改 dma_channel_3时、SPI 无法 TX
TxDMASourcedTrigger = DMA_TRIGGERSOURCE_23
}
};
const SPI_Config SPI_CONFIG[]={
{
.fxnTablePtr =&SPIUSCIADA_fxnTable、
.object = spiUSCIADMAObjects[0],
hwAttrs = spiUSCIADMAHWAttrs[0](&P)
}、
{
.fxnTablePtr =&SPIUSCIBDMA_fxnTable、
.object = spiUSCIBDMAObjects[0]、
hwAttrs = spiUSCIBDMAMHWAttrs[0](&P)
}、
{NULL、NULL、NULL}、
};
void MSP_EXP430F5529LP_initSPI (void)
{
//
//USCIA1
//
/*配置 CS 引脚以禁用 SPI 从设备*/
GPIO_setAsOutputPin (GPIO_PORT_P2、GPIO_PIN0);
GPIO_setOutputHighOnPin (GPIO_PORT_P2、GPIO_PIN0);
/* SPI CLK */
GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P4、GPIO_PIN0);
/* MOSI/SIMO *
GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P4、GPIO_PIN4);
/* MISO/SOMI *
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN5);
//
//USCIB1
//
//从器件
//GPIO_setAsInputPinWithPullUp电 阻器(GPIO_PORT_P2、GPIO_PIN4);
//GPIO_setOutputHighOnPin (GPIO_PORT_P2、GPIO_PIN4);
//GPIO_getInputPinValue (GPIO_PORT_P2、GPIO_PIN4);
// SPI CLK
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN3);
//MOSI/SIMO
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN1);
// MISO/SOMI
GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P4、GPIO_PIN2);
SPI_init();
}
您好 Rob
尽管 SPI_TRANSF()功能冲突的最终解决方案是使用不同的 DMA 通道,但您的分析没有任何问题,
当 SpiB_Slave 在回调模式下打开时、 semaphores (two_spi_semStructP) 一直被 spiB1_slave_taskFxn 任务占用、 并且我的 POST 代码可能有点问题
我的 SPIB1回调函数 只需执行一些 printf 处理。
无论从站还是主站,我都尝试将 semaphore_post (&two_spi_semStructP) 放置在 spiB1_transferCallbackFxn()或 spiA1_transferCallbackFxn()中 ,但仍然无法更改任何内容!
明天我将继续验证信号量的使用以保护四个 DMA 通道中的一个、您可以有时间查看我对 TOOMA 的响应、 非常感谢您的回复。
此致
XC.mo