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.

[参考译文] LAUNCHXL-CC1310:无 RTOS 的 CC1310 SPI 从器件回调模式

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

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1321641/launchxl-cc1310-cc1310-spi-slave-callback-mode-without-rtos

器件型号:LAUNCHXL-CC1310
主题中讨论的其他器件:CC1310

大家好!

我尝试合并 SPI 从器件和 RF Tx 模块、

我在代码中连接到 SPI 从器件阻塞模式。 它正在运行、但运行不正确。

我想与 SPI 主器件同步。

我需要设置不具有重叠的读取位置。  

我认为 SPI 从器件回调模式可以使用中断模式。 但它不起作用。

我有一些问题。

1. 如何在非 RTOS 中使用 SPI 从站回调? 如果无法实现、如何同步 SPI 主器件?

2.您有 SPI 从时序图吗?

以下是我的代码部分。

------------------------------------------------------------------------------------------------------------------------------------------------

void *mainThread (void *arg0)
{
//射频设置
RF_Params rfParams;
rf_params_init (&rfParams);

RF_cmdPropTx.pktLen = SPI_MSG_LENGTH;
rf_cmdPropTx.pPkt = RFTxBuffer;//数据包;
RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;

// SPI Rx 设置
SPI_Handle slaveSpi;
SPI_Params spiParams;
SPI_Transaction 传输;

GPIO_init ();
SPI_INIT();
uart_init();

静态 UART_Handle UART;
静态 UART_Params uartParams;

/*创建一个数据处理关闭的 UART 模块。 */
uart_params_init (&uartParams);
uartParams.writeDataMode = UART_DATA_binary;
uartParams.readDataMode = UART_DATA_binary;
uartParams.readReturnMode = UART_RETURN_FULL;
uartParams.readEcho = uart_echo_off;
uartParams.baudrate = 115200;

UART = UART_OPEN (Board_UART0、&uartParams);

if (uart == NULL){
/* uart_open()失败*/
while (1);

SPI_PARAMS_INIT (&spiParams);
spiParams.dataSize = 8;
spiParams.bitrate = 4000000;
spiParams.frameFormat = SPI_POL0_PHA0;
spiParams.mode = SPI_SLAVE;
spiParams.transferCallbackFxn =回调;
spiParams.transferMode = SPI_MODE_CALLBACK;
slaveSpi = SPI_open (Board_SPI_SLAVE、&spiParams);
if (slaveSpi == NULL){
while (1);

/*打开 LED 引脚*/
ledPinHandle1 = PIN_OPEN (&ledPinState1、pinTable1);
ledPinHandle2 = PIN_OPEN (&ledPinStatus2、pinTable2);
如果(ledPinHandle1 == NULL || ledPinHandle2 == NULL)
{
while (1);

/*请求访问对讲机*/
rfHandle = rf_open (&rfObject、&rf_prop、(RF_RadioSetup*)&RF_cmdPropRadioDivSetup、&rfParams);

/*设置频率*/
RF_postCmd (rfHandle、(RF_Op*)和 RF_cmdfs、RF_PriorityNormal、NULL、0);

/*初始化从器件 SPI 事务结构*/
transaction.count = SPI_MSG_LENGTH;
transaction.txBuf = NULL;
transaction.rxBuf =(void *) slaveRxBuffer;

while (1)
{
// spi_transfer (slaveSpi、&transaction);

// if (packetRxCb){
// RF_postCmd (rfHandle、(RF_Op*)和 RF_cmdPropTx、RF_PriorityNormal、NULL、0);
// packetRxCb = false;
//}
SPI_TRANSMIT (slaveSpi、&TRANSACTION);
如果(转让确定){
memcpy (RFTxBuffer、slaveRxBuffer、SPI_MSG_LENGTH);
UART_WRITE (UART、(&RFTxBuffer)、SPI_MSG_LENGTH);
UART_WRITE (UART、"\n\n"、2);
转让 OK = false;

PIN_setOutputValue (ledPinHandle1、Board_PIN_LED1、!PIN_getOutputValue (Board_PIN_LED1));

否则{
PIN_setOutputValue (ledPinHandle2、Board_PIN_LED2、!PIN_getOutputValue (Board_PIN_LED2));



空回调(SPI_Handle handle、SPI_Transaction * transaction)
{
if (transaction->status == spi_transfer_completed){
转让 OK = true;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Chanbin、

    nortos 中不支持 spimaster 和 spislave 示例。 但如果看一下这些示例的 RTOS 版本、就会看到、通常有一个额外的 Ready GPIO 引脚用于在主器件和从器件之间同步。 请使用您实现的 nortos 示例中的相同逻辑。  

    dev.ti.com/.../node

    此致、

    SID

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Sid。

    感谢您的回复。

    我明白了。 我将尝试使用"Ready GPIO"。

    顺便说一下、它是否有任何与 CS 引脚相关的自举中断? 否则、我将使用4引脚 SPI。

    还有一点、"孤岛"是否有诸如 WDEL 的时序图? 或者、它与 spimaster 图相同吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Chanbin、

    可以在技术参考手册的第20.4.4节中找到 SPI 的时序图: https://www.ti.com/lit/ug/swcu117i/swcu117i.pdf

    自旋体和自旋管具有相同的时序图。  

    如果您要求由于 CS 线路上的活动而唤醒 SPI 从设备、请参阅驱动程序文件。 请参阅标题为

    "在从模式下使用 SPI_MODE_CALLBACK 通过芯片选择唤醒取消置位"

    https://dev.ti.com/tirex/content/simplelink_cc13x0_sdk_4_20_02_07/docs/tidrivers/doxygen/html/_s_p_i_c_c26_x_x_d_m_a_8h.html

    如果您正在寻找一种由从器件控制 CS 线路的解决方案、则无法实现。

    另外、我还想指出有关孤岛模式的勘误表、请对其进行研究。  

    www.ti.com/.../swrz062f.pdf

    此致、

    SID

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sid:

    "使用 SPI_MODE_CALLBACK 在从模式下通过芯片选择唤醒取消置位" 是我需要的解决方案。

    但是、在运行到回调函数之前、它有很多延迟。

    在我的情况下、SPI 接收大约200字节的4Mbps 速度和随机位置。 和通过射频发送接收的数据。

    所以我想快速处理。  

    以下是我的代码。 图片是 SPI 和回调位置波形。

    如何快速处理?

    /***** Function definitions *****/
    // Chip select callback
    static void chipSelectCallback(PIN_Handle handle, PIN_Id pinId)
    {
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
    
        PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 0);
    
        // Release the chip select pin
        PIN_remove(handle, pinId);
    
        // Open SPI driver
        slaveSpi = SPI_open(Board_SPI_SLAVE, &spiParams);
    
        // Issue echo transfer
        SPI_transfer(slaveSpi, &transaction);
    
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 0);
    
    }
    
    // SPI transfer callback
    static void transferCallback(SPI_Handle handle, SPI_Transaction *transaction)
    {
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, 1);
    
        uint32_t cmdStatus = transaction->status;
        //if(cmdStatus != SPI_TRANSFER_COMPLETED){
        //   while(1);
        //}
    
        // Close the SPI driver
        SPI_close(handle);
    
        memcpy(RFTxBuffer, slaveRxBuffer, SPI_MSG_LENGTH);
    
        RF_EventMask terminationReason = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx,RF_PriorityNormal, NULL, 0);
    
        PIN_add(slaveCsnHandle, slaveCsnTable[0]);
    
        PIN_registerIntCb(slaveCsnHandle, &chipSelectCallback);
    
        //transferOK = true;
        PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 1);
    
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, 0);
    }
    
    void *mainThread(void *arg0)
    {
        // RF Setting
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_init();
        SPI_init();
    
        RF_cmdPropTx.pktLen = SPI_MSG_LENGTH;
        RF_cmdPropTx.pPkt = RFTxBuffer;//packet;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    
        SPI_Params_init(&spiParams);
        spiParams.dataSize = 8;
        spiParams.bitRate = 4000000;
        spiParams.frameFormat = SPI_POL0_PHA0;
        spiParams.mode = SPI_SLAVE;
        spiParams.transferCallbackFxn = transferCallback;
        spiParams.transferMode = SPI_MODE_CALLBACK;
        //slaveSpi = SPI_open(Board_SPI_SLAVE, &spiParams);
        //if (slaveSpi == NULL) {
        //    while (1);
        //}
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        /* Initialize slave SPI transaction structure */
        transaction.count = SPI_MSG_LENGTH;
        transaction.txBuf = NULL;
        transaction.rxBuf = (void *) slaveRxBuffer;
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            /* Error initializing board LED pins */
            while(1);
        }
    
        /* slave Ready pin */
        slaveRdyHandle = PIN_open(&slaveRdyState, slaveRdyTable);
        if(!slaveRdyHandle) {
            /* Error initializing button pins */
            while(1);
        }
    
        /* slave CSN pin */
        slaveCsnHandle = PIN_open(&slaveCsnState, slaveCsnTable);
        if(!slaveCsnHandle) {
            /* Error initializing button pins */
            while(1);
        }
    
        /* Setup callback for Csn pins */
        if (PIN_registerIntCb(slaveCsnHandle, &chipSelectCallback) != 0) {
            /* Error registering button callback function */
            while(1);
        }
    
        PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 1);
        while(1)
        {
            //GPIO_write(Board_SPI_SLAVE_READY, 1);
            //transferOK = SPI_transfer(slaveSpi, &transaction);
    
    //        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, !PIN_getOutputValue(Board_PIN_LED1));
    
            HwiP_Params_init
            if (0) {
                memcpy(RFTxBuffer, slaveRxBuffer, SPI_MSG_LENGTH);
    
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
    
                RF_EventMask terminationReason = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx,RF_PriorityNormal, NULL, 0);
    
                transferOK = 0;
    
                PIN_add(slaveCsnHandle, slaveCsnTable[0]);
    
                PIN_registerIntCb(slaveCsnHandle, &chipSelectCallback);
    
                PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 1);
    
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 0);
    
            }
            else {
                /*
                GPIO_write(Board_SPI_SLAVE_READY, 0);
                GPIO_toggle(Board_GPIO_LED0);
                */
            }
        }
    }

    绿色: MOSI /蓝色: SCK /黄色: CSN /红色:通知回调函数正在运行。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Changim:

    只是为了说明一下、您是否希望芯片选择回调触发更快?

    此致、
    SID

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、sid:

    是的、我需要芯片选择回调的速度更快。

    我还有一个问题。

    下面是我的条件中的 SPI 主器件波形。

    最后一个 SPI 时钟为8位、连续传输模式比其他时钟稍长。

    还可以吗? 或者可能有问题吗?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Chanbin、  

    在 使用 SPI_MODE_CALLAR 在从模式下实现片上唤醒选择取消置位的解决方案中、您要有效地做的是在引脚驱动器和 SPI 驱动器之间共享引脚。  

    1.您正在设置一个称为 chipSelectCallback 的引脚回调函数、该函数在引脚无效时被触发。 在该回调函数中、您现在将引脚移交给 SPI 驱动器、现在从器件已准备好通过 SPI 线路接收数据。  

    2.在发生 SPI 事务时触发 SPI 传输回调函数。 在此回调中、您执行了一个非常耗时的 memcpy、并且在将引脚移交回引脚驱动器之前发布了无线电命令。 将引脚转移到引脚驱动器后、主器件会再次等待 CSn 引脚被主器件取消置位。 如果它被取消置位,则触发 chipSelectCallback。

    在我的情况下、SPI 接收大约200字节的4Mbps 速度和随机位置。 和通过射频发送接收的数据。

    所以我想快速处理。  

    [/报价]

    您说"快速处理"是什么意思? 如果您讨论的是无线电 TX 发生得更快、那么您可能应该减小数据包长度、以便在回调中复制较少的数据。

    如果您说的是芯片选择回调本身、那么在 SPI 传输之后、您应该在主器件中更快地使 CSn 线无效、您可以找到实际工作完成一些迭代的时间。

    最后一个采用8位和连续传输模式的 SPI 时钟比其他时钟长一点。

    请看一下我在上一个答案中链接的技术参考手册中一些帧格式的时序图。  

    技术参考手册的第20.4.4节提供了 SPI 的时序图: https://www.ti.com/lit/ug/swcu117i/swcu117i.pdf

    请查看 TRM 的20.4.4.5部分。

    此致、

    SID

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Sid:

    我认为 只要 CSn 失效、芯片选择回调调用就会立即生效。

    我明白你对回调函数的理解。

    我将尝试正确插入回调函数和控制计时。

    顺便说一下、我已经看到 TRM 中 SPI 的时序图。

    共有3个图 SPI 时序图。

    所有它们最多只能具有16位。 (我认为应该在16位后控制 CSn。)

    CC1310的 SPI 是否有在无需控制 CSn 的情况下获取16位数据的方法?

    感谢您的帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Chanbin、

    似乎正确、最大帧大小最大为16位长。 FSS 信号会在每个16位帧之间切换。  

    此致、

    SID

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 sid。

    我解决了有关 SPI 的问题。