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:如何在回调模式下退出 SPI_TRANSMIT。

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

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1327739/launchxl-cc1310-how-can-exit-spi_transfer-in-callback-mode

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

您好!

我想知道如何在回调模式下退出 SPI_TRANSMIT。

CC1310 Launchpad 作为 SPI 从设备运行。

在获取 SPI 数据时、SPI 从器件不会不时调用回调。

此时、如何退出 SPI_TRANSMIT。 或者如何调用回调函数。

下面是我的 CC1310代码。  

当 SPI 从器件正常运行时、 "transferOK"变量将设置为"0"。 然后其余代码运行。

#define SPI_MSG_LENGTH  (200) + 3

#define DATA_ENTRY_HEADER_SIZE  8   // Constant header size of a Generic Data Entry
#define MAX_LENGTH              SPI_MSG_LENGTH // Set the length of the data entry
#define NUM_DATA_ENTRIES        1
#define NUM_APPENDED_BYTES      0

/* TX queue or RF Core to read data from */
static dataQueue_t dataQueue;
static rfc_dataEntryGeneral_t* currentDataEntry;
static uint8_t *pPacket;

static uint8_t txDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                 MAX_LENGTH,
                                                                 NUM_APPENDED_BYTES)];

/***** Variable declarations *****/
static bool            transferOK;
static bool            transferOK2;

uint8_t slaveRxBuffer[SPI_MSG_LENGTH];

/* Pin driver handle */
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;
PIN_Config ledPinTable[] = {
    Board_PIN_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

static PIN_Handle slaveRdyHandle;
static PIN_State slaveRdyState;
PIN_Config slaveRdyTable[] = {
    Board_DIO21 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

static PIN_Handle masterRdyHandle;
static PIN_State masterRdyState;
PIN_Config masterRdyTable[] = {
    Board_DIO15 | PIN_INPUT_EN,
    PIN_TERMINATE
};

static void SPIRxCallback(SPI_Handle handle, SPI_Transaction *transaction)
{
    transferOK2 = 0;

    if(transaction->status == SPI_TRANSFER_COMPLETED){ // Green
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,  !PIN_getOutputValue(Board_PIN_LED1));
    }

    else{
        PIN_setOutputValue(ledPinHandle, Board_PIN_LED0,  !PIN_getOutputValue(Board_PIN_LED0));
    }
}

void tx_callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
    if(e & RF_EventLastCmdDone)
    {

        //PIN_setOutputValue(ledPinHandle, Board_PIN_LED0,  !PIN_getOutputValue(Board_PIN_LED0));

    }

}

void *mainThread(void *arg0)
{
    // RF Setting
    RF_Object rfObject;
    RF_Handle rfHandle;

    RF_Params rfParams;
    RF_Params_init(&rfParams);

    // SPI Rx Setting
    SPI_Handle      slaveSpi;
    SPI_Params      spiParams;
    SPI_Transaction transaction;

    SPI_init();

    if( RFQueue_defineQueue(&dataQueue,
                            txDataEntryBuffer,
                            sizeof(txDataEntryBuffer),
                            NUM_DATA_ENTRIES,
                            MAX_LENGTH + NUM_APPENDED_BYTES))
    {
        /* Failed to allocate space for all data entries */
        while(true);
    }

    RF_cmdTxHS.pQueue = &dataQueue;
    RF_cmdTxHS.startTrigger.triggerType  = TRIG_NOW;
    RF_cmdTxHS.startTrigger.pastTrig = 1;
    RF_cmdTxHS.startTime = 0;

    currentDataEntry = (rfc_dataEntryGeneral_t*)&txDataEntryBuffer;
    currentDataEntry->length = SPI_MSG_LENGTH;
    pPacket = &currentDataEntry->data;

    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA1;
    spiParams.mode = SPI_SLAVE;
    spiParams.transferCallbackFxn = SPIRxCallback;
    spiParams.transferMode = SPI_MODE_CALLBACK;
    spiParams.bitRate = 4000000;
    slaveSpi = SPI_open(Board_SPI_SLAVE, &spiParams);
    if (slaveSpi == NULL) {
       while (1);
    }
    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop_hsm, (RF_RadioSetup*)&RF_cmdRadioSetup_hsm, &rfParams);

    /* Set the frequency */
    //{ "868.0  ", 0x0364, 0x0000, 0x0 },
    //{ "915.0  ", 0x0393, 0x0000, 0x0 },
    RF_cmdFs_preDef.frequency = 0x0393;
    RF_cmdFs_preDef.fractFreq = 0x0000;
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs_preDef, RF_PriorityNormal, NULL, 0);

    /* 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);
    }

    /* master Ready pin */
    masterRdyHandle = PIN_open(&masterRdyState, masterRdyTable);
    if(!masterRdyHandle) {
        /* Error initializing button pins */
        while(1);
    }

    /* Initialize slave SPI transaction structure */
    transaction.count = SPI_MSG_LENGTH;
    transaction.txBuf = NULL;
    transaction.rxBuf = (void *) slaveRxBuffer;

    while(1)
    {
        transferOK2 = 1;

        memset(slaveRxBuffer, 0, SPI_MSG_LENGTH + 1);

        transferOK = SPI_transfer(slaveSpi, &transaction);

        if (transferOK) {
            while(!PIN_getInputValue(Board_DIO15));

            PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 1);

            while(transferOK2);

            PIN_setOutputValue(slaveRdyHandle, Board_DIO21, 0);

            memcpy(pPacket, slaveRxBuffer, SPI_MSG_LENGTH + 1);

            RF_postCmd(rfHandle, (RF_Op*)&RF_cmdTxHS, RF_PriorityNormal, NULL, 0);

        }
        else {

        }
    }
}

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

    我还有一个问题。

    在进行 CSn 处理时、可获得 SPI 数据的长度是多少?

    我提到了"pislave"和"pimaster"示例。

    例如、在30字节发送期间它不控制 CSn 引脚。

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

    请参阅此处 SPI 驱动器的文档: SPI.h 文件参考(TI.com)

    恐怕我不能完全明白你到底要做什么,以及它是如何失败的。

    我建议您先从 SDK 中的 SPI 主设备和从设备示例开始、并使其按需要运行(正确、字节数、正确使用 CSn 等)、然后再开始将射频驱动程序纳入应用程序。

    如果您无法启动和运行主/从通信、您可以与我共享代码、以便我进行测试。

    它 需要能够在 CC1310 LP 上运行、我需要主机和从机代码。

    您需要使用要传输的 SPI 数据(或者如果不是 CC1310、您的主器件也要传输)数据图来指导您如何配置从器件来接收这些数据。

    Siri

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

    尊敬的 Siri:

    正如我理解的 SPI 从器件回调模式、SPI 从器件从主器件获取数据、直到指定计数。 (在代码中,"transaction.count = SPI_MSG_length")

    因此、我预计即使 SPI_TRANSMIT 失败、SPI 回调也会在 SPI 传输结束后始终调用。

    但回调有时不起作用。 因此我需要退出 SPI 传输。  

    在我的代码中、如果回调不起作用、则在"while (transferOK2)"之后无法工作。

    我需要类似"SPI_Params.transferTimeout"的功能。但它只能使用 SPI 阻断模式。 对吧?

    我问了回调模式下的"transfertimeout"函数。

    另一个问题是关于 SPI 帧格式。

    在 TRM 中、SPI 需要控制 CSn、如下所述。

    但在 SDK 示例"spislave_CC1310_LAUNCHXL_tirtos_ccs"和"spimaster_CC1310_LAUNCHXL_tirtos_ccs"中、  

    CSn 在发送30字节数据时不会失效。

    那么、什么是正确信息? 是否可以使用 SPI 从机发送约200字节数据而不使主机的 CSn 无效?

    下面是主 SPI 波形(Y:CSn,B:SPI 时钟,G:SPI MOSI)

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

     SPI_MODE_CALLCOM 中没有超时。  我发送给您的文档中有相关说明。

    如果您正在使用 SPI_MODE_CALLK 并将 TRANSACTION_COUNT 设置为20;在从器件上、您将在接收到20个字节后获得回调。

    这意味着、如果您在一个事务中仅传输来自主器件的10个字节(transaction.count = 10)、则在您从主器件完成两个传输之前不会在从器件上获得回调。

    这意味着如果您要在接收到20个字节之前取消 SPI 传输,则需要使用 SPI_transferCancel()

    我已经为您简化了主从示例、以便您可以使用这些示例并同时监控 SPI 线路和两个 LED、从而您可以更好地了解其工作原理。

    从机:

    #define THREADSTACKSIZE (1024)
    
    #define SPI_MSG_LENGTH  (20)
    
    unsigned char slaveRxBuffer[SPI_MSG_LENGTH];
    unsigned char slaveTxBuffer[SPI_MSG_LENGTH];
    
    sem_t slaveSem;
    
    void transferCompleteFxn(SPI_Handle handle, SPI_Transaction *transaction)
    {
        sem_post(&slaveSem);
    }
    
    void *slaveThread(void *arg0)
    {
        SPI_Handle      slaveSpi;
        SPI_Params      spiParams;
        SPI_Transaction transaction;
        uint32_t        i;
        bool            transferOK;
        int32_t         status;
    
        status = sem_init(&slaveSem, 0, 0);
        if (status != 0)
        {
            while(1);
        }
    
        GPIO_init();
        SPI_init();
    
        SPI_Params_init(&spiParams);
        spiParams.frameFormat = SPI_POL0_PHA1;
        spiParams.mode = SPI_SLAVE;
        spiParams.transferCallbackFxn = transferCompleteFxn;
        spiParams.transferMode = SPI_MODE_CALLBACK;
        slaveSpi = SPI_open(Board_SPI_SLAVE, &spiParams);
    
        if (slaveSpi == NULL)
        {
            while (1);
        }
    
        for(i = 0; i < SPI_MSG_LENGTH; i++)
            slaveTxBuffer[i] = SPI_MSG_LENGTH - i;
    
        while(1)
        {
            GPIO_write(Board_GPIO_LED1, 1);
            transaction.count = SPI_MSG_LENGTH;
            transaction.txBuf = (void *) slaveTxBuffer;
            transaction.rxBuf = (void *) slaveRxBuffer;
    
            transferOK = SPI_transfer(slaveSpi, &transaction);
    
            if (transferOK)
            {
                // Wait until transfer has completed
                sem_wait(&slaveSem);
                GPIO_toggle(Board_GPIO_LED0);
            }
            GPIO_write(Board_GPIO_LED1, 0);
        }
    }

    主站:

    #define THREADSTACKSIZE (1024)
    
    #define SPI_MSG_LENGTH  (20)
    
    unsigned char masterRxBuffer[SPI_MSG_LENGTH];
    unsigned char masterTxBuffer[SPI_MSG_LENGTH];
    
    sem_t transactionSem;
    
    void TransmitReceiveFxn(uint_least8_t index)
    {
        sem_post(&transactionSem);
    }
    
    uint8_t i = 0;
    
    void *masterThread(void *arg0)
    {
        SPI_Handle      masterSpi;
        SPI_Params      spiParams;
        SPI_Transaction transaction;
        bool            transferOK;
        int32_t         status;
    
        GPIO_init();
        SPI_init();
    
        GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
        GPIO_setCallback(Board_GPIO_BUTTON1, TransmitReceiveFxn);
        GPIO_enableInt(Board_GPIO_BUTTON1);
    
        status = sem_init(&transactionSem, 0, 0);
        if (status != 0)
        {
            while(1);
        }
    
        // Open SPI as master (default)
        SPI_Params_init(&spiParams);
        spiParams.frameFormat = SPI_POL0_PHA1;
        spiParams.bitRate = 2000000;
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        if (masterSpi == NULL)
        {
            while (1);
        }
    
        for(i = 0; i < SPI_MSG_LENGTH; i++)
            masterTxBuffer[i] = i + 1;
    
        while(1)
        {
            // Press a button to start a transaction
            sem_wait(&transactionSem);
    
            GPIO_write(Board_GPIO_LED1, 1);
    
            transaction.count = (SPI_MSG_LENGTH / 2); // Set different length to see how this affects the slave
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;
    
            transferOK = SPI_transfer(masterSpi, &transaction);
            if (transferOK)
            {
                GPIO_toggle(Board_GPIO_LED0);
            }
            GPIO_write(Board_GPIO_LED1, 0);
        }
    }

    Siri

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

    尊敬的 Siri:

    我已经知道这个例子。 这就是我提到过的。

    据我所知、如果 CC1310无法获取该 transaction.count 数据、则无法进行 SPI 回调、对吧?

    我需要找到其他方法来处理代码、而不考虑 SPI 数据的数量。

    顺便说一下、您能告诉我帧格式吗?

    另一个问题是关于 SPI 帧格式。

    在 TRM 中、SPI 需要控制 CSn、如下所述。

    但在 SDK 示例"spislave_CC1310_LAUNCHXL_tirtos_ccs"和"spimaster_CC1310_LAUNCHXL_tirtos_ccs"中、  

    CSn 在发送30字节数据时不会失效。

    那么、什么是正确信息? 是否可以使用 SPI 从机发送约200字节数据而不使主机的 CSn 无效?

    [/报价]

    谢谢你。

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

    我发布的示例不是 SDK 中的示例。 如果你锁定我发布的代码、你会看到这要简单得多。

    如果您不知道计数、则在回调模式下无法工作是不正确的。

    正确的是、您在到达 transaction.count 之前不会获得回调。 如果这对于您的应用是否可以接受、我无法回答。

    如果您要在实现在 transaction.count 中设置的字节数之前取消事务,则需要使用 SPI_transferCancel()

    例如 I POST、CSn 在整个传输过程中保持低电平。 如果 transaction.count 是30或200、则情况相同。 如果您已经测试了我发送给您的代码、您可以轻松地将 SPI_MSG_LENGTH 更改为200、然后看到它仍然可以正常工作

    如果您希望 CSn 为每个发送的字节变为低电平和高电平、只需将 TRANSACTION_COUNT 设置为1、并设置 SPI_TRANSMIT 的 SPI_MSG_LENGTH 个数

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

    我明白了您的意思。

    我希望在我的代码中插入异常处理。 例如连接不稳定或类似情况。

    谢谢你。