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.

[参考译文] RTOS/MSP430F5529:TI-RTOS、两个 SPI (一个主器件一个从器件)同步问题!

Guru**** 2250420 points
Other Parts Discussed in Thread: MSP430F5529
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/696430/rtos-msp430f5529-ti-rtos-two-spi-one-master-one-slave-synchronization-issue

器件型号:MSP430F5529

工具/软件:TI-RTOS

大家好

最近、我在 MSP_EXP430F5529LP 开发 板上配置了 SPI 主器件和 SPI 从器    件、在 TI-RTOS 两个任务下、我发现两个 SPI 相互交互。  当我关闭其中一个任务而另一个 SPI 工作正常时, 我尝试添加信标以保护 SPI_TRANSF()功能,问题仍然存在, 我放置断点,发现问题出现在下图中,导致 SPI 传输返回错误,  SPI 从器件只能向外发送第一个字节。  谁能教我如何做、或者给我一个类似的例子、谢谢!

此致  

XC.mo

1。

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