Other Parts Discussed in Thread: CC1310,
我希望能產出一支程式,使用SCS的uart與設備透過RS485進行溝通,並將數據利用RF的TX傳送出去,我目前已經確定SCS的uart能夠利用scifWaitOnNbl(5000000);降低功耗5秒,但是我不知道如何關閉Cortex-M3,我有查看ti Driver 範例中的pinstanby,但是似乎sleep();無法滿足我的需求,希望能得到一些建議,或者SCS的uart的休眠如果有錯誤再麻煩告訴我。
謝謝,以下提供程式碼,希望能得到最好的建議。
說明一下,主要是通過uartTaskInit和rfTxTaskInit之間交互
/*
* Copyright (c) 2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/***** Includes *****/
/* Standard C Libraries */
#include <stdlib.h>
#include <unistd.h>
/* TI Drivers */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/uart/UARTCC26XX.h>
/* Driverlib Header files */
#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
/* Board Header files */
#include "Board.h"
/* Application Header files */
#include "RFQueue.h"
#include "smartrf_settings/smartrf_settings.h"
//#include DeviceFamily_constructPath(inc/hw_fcfg1.h)
//SCS include
#include <ti/devices/DeviceFamily.h>
#include "scif.h"
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/BIOS.h>
/***** Defines *****/
#define NO_PACKET 0
#define PACKET_RECEIVED 1
volatile uint8_t packetRxCb;
volatile size_t bytesReadCount;
/* Packet RX Configuration */
#define MAX_LENGTH 240 /* Max length byte the radio will accept */
#define NUM_DATA_ENTRIES 2 /* NOTE: Only two data entries supported at the moment */
#define NUM_APPENDED_BYTES 2 /* The Data Entries data field will contain:
* 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
* Max 30 payload bytes
* 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */
/* RFQueue */
static dataQueue_t dataQueue;
static rfc_dataEntryGeneral_t* currentDataEntry;
static uint8_t rfRxPacketLength;
static uint8_t* rfRxPacketDataPointer;
static uint8_t rfRxPacket[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
static uint8_t rfTxPacket[MAX_LENGTH + NUM_APPENDED_BYTES - 1];
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (rxDataEntryBuffer, 4);
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
MAX_LENGTH,
NUM_APPENDED_BYTES)];
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
MAX_LENGTH,
NUM_APPENDED_BYTES)];
#elif defined(__GNUC__)
static uint8_t
rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
MAX_LENGTH,
NUM_APPENDED_BYTES)]
__attribute__((aligned(4)));
#else
#error This compiler is not supported.
#endif
/* UART */
#define MAX_NUM_UART_RX_BYTES 1000
#define MAX_NUM_UART_TX_BYTES 1000
static int uartRxCount;
uint8_t UartRxBuf[MAX_NUM_UART_RX_BYTES]; // Receive buffer
uint8_t UartTxBuf[MAX_NUM_UART_TX_BYTES]; // Transmit buffer
UART_Handle uart;
UART_Params uartParams;
static char input[MAX_NUM_UART_RX_BYTES];
static char output[MAX_NUM_UART_TX_BYTES];
int32_t UARTwrite_semStatus;
int_fast16_t status = UART_STATUS_SUCCESS;
static int i,j;
// Uart TASK DATA
// Task data
static Task_Params uartTaskParams,rfTxTaskParams,rfRxTaskParams;
static Task_Struct uartTaskStruct,rfTxTaskStruct,rfRxTaskStruct;
static Char uartTaskStack[1024],rfTxTaskStack[1024],rfRxTaskStack[1024];
Semaphore_Struct uartTaskSem, rfTxTaskSem, rfRxTaskSem;
Semaphore_Handle uartTaskSemHandle, rfTxTaskSemHandle, rfRxTaskSemHandle;
/* RF handle */
static RF_Object rfObject;
static RF_Handle rfHandle;
static RF_CmdHandle rfTxPostHandle,rfRxPostHandle;
static RF_Params rfParams;
/* LED */
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;
PIN_Config pinTable[] =
{
Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_PIN_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
/***** Function definitions *****/
void ReceiveonUARTcallback(UART_Handle handle, void *UartRxBuf, size_t count, void *userArg, int_fast16_t status)
{
bytesReadCount = count;
}
void led_init()
{
ledPinHandle = PIN_open(&ledPinState, pinTable);
PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1));
usleep(300000);
PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1));
PIN_setOutputValue(ledPinHandle, Board_PIN_LED2,!PIN_getOutputValue(Board_PIN_LED2));
usleep(300000);
PIN_setOutputValue(ledPinHandle, Board_PIN_LED2,!PIN_getOutputValue(Board_PIN_LED2));
if (ledPinHandle == NULL)
{
while(1);
}
}
void uartTxRfRxPacket()
{
printf("uartTxRfRxPacket\n");
if(packetRxCb)
{
for(i=0;i<rfRxPacketLength;i++)
{
scifUartTxPutChar((char)rfRxPacket[i]);
}
packetRxCb = NO_PACKET;
Semaphore_post(rfRxTaskSemHandle);
}
}
void ReceivedOnRFcallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
if (e & RF_EventRxEntryDone)
{
PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 1);
/* Get current unhandled data entry */
currentDataEntry = RFQueue_getDataEntry(); //loads data from entry
/* Handle the packet data, located at ¤tDataEntry->data:
* - Length is the first byte with the current configuration
* - Data starts from the second byte */
rfRxPacketLength = *(uint8_t*)(¤tDataEntry->data); //gets the packet length (send over with packet)
rfRxPacketDataPointer = (uint8_t*)(¤tDataEntry->data + 1); //data starts from 2nd byte
/* Copy the payload + the status byte to the packet variable */
memcpy(rfRxPacket, rfRxPacketDataPointer, (rfRxPacketLength + 1));
/* Move read entry pointer to next entry */
RFQueue_nextEntry();
packetRxCb = PACKET_RECEIVED;
PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 0);
uartTxRfRxPacket();
}
}
void scCtrlReadyCallback(void) {
printf("scCtrlReadyCallback\n");
} // scCtrlReadyCallback
void scTaskAlertCallback(void) {
printf("scTaskAlertCallback\n");
// Clear the ALERT interrupt source
scifClearAlertIntSource();
// Echo all characters currently in the RX FIFO
int rxFifoCount = scifUartGetRxFifoCount();
uartRxCount = rxFifoCount;
i = 0;
while (rxFifoCount--)
{
UartRxBuf[i] = (char)scifUartRxGetChar();
i++;
}
// Clear the events that triggered this
scifUartClearEvents();
// Acknowledge the alert event
scifAckAlertEvents();
if(uartRxCount > 0)
{
//開啟rf tx
Semaphore_post(rfTxTaskSemHandle);
}
// Wake up the OS task
//Semaphore_post(uartTaskSemHandle);
} // scTaskAlertCallback
// CRC計算函數
uint16_t calculateCRC(uint8_t *data, int length) {
uint16_t crc = 0xFFFF;
for (i = 0; i < length; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc >>= 1;
crc ^= 0xA001; // 16位CRC多項式
} else {
crc >>= 1;
}
}
}
return crc;
}
void scUartTask(UArg a0, UArg a1) {
printf("scUartTask start\n");
// Initialize the Sensor Controller
scifOsalInit();
scifOsalRegisterCtrlReadyCallback(scCtrlReadyCallback);
scifOsalRegisterTaskAlertCallback(scTaskAlertCallback);
scifInit(&scifDriverSetup);
//scifStartRtcTicksNow(0x00010000 / 8);
uint8_t command[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x0A};
int commandLength = sizeof(command) / sizeof(command[0]);
uint16_t crc = calculateCRC(command, commandLength);
// 將CRC檢驗碼附加到數據報文
command[commandLength] = crc & 0xFF; // 低位字節
command[commandLength + 1] = (crc >> 8) & 0xFF; // 高位字節
int newCommandLength = commandLength + 2;
while(1)
{
//printf("Uart restart\n");
// Start the UART emulator
scifResetTaskStructs((1 << SCIF_UART_EMULATOR_TASK_ID), (1 << SCIF_STRUCT_CFG) | (1 << SCIF_STRUCT_INPUT) | (1 << SCIF_STRUCT_OUTPUT));
scifExecuteTasksOnceNbl(1 << SCIF_UART_EMULATOR_TASK_ID);
// Enable baud rate generation
scifUartSetBaudRate(9600);
// Enable RX (10 idle bit periods required before enabling start bit detection)
scifUartSetRxFifoThr(SCIF_UART_RX_FIFO_MAX_COUNT / 2);
scifUartSetRxTimeout(10 * 2);
scifUartSetRxEnableReqIdleCount(10 * 2);
scifUartRxEnable(1);
// Enable events (half full RX FIFO or 10 bit period timeout
scifUartSetEventMask(BV_SCIF_UART_ALERT_RX_FIFO_ABOVE_THR | BV_SCIF_UART_ALERT_RX_BYTE_TIMEOUT);
//printf("wait 0.5s\n");
scifWaitOnNbl(500000);
// 使用循環將整個帶CRC檢驗碼的數據報文傳輸到UART
for (i = 0; i < newCommandLength; i++) {
scifUartTxPutChar(command[i]);
}
//printf("scUartTask wait for semaphore post\n");
// Wait for an ALERT callback
//Semaphore_pend(uartTaskSemHandle, BIOS_WAIT_FOREVER);
//printf("wait 0.5s\n");
scifWaitOnNbl(500000);
//printf("scifUartStopEmulator\n");
scifUartStopEmulator();
scifUartSetBaudRate(0);
//printf("wait 5s\n");
scifWaitOnNbl(500000);
}
} // taskFxn
void uartTaskInit()
{
//Initialize Uart semaphore
Semaphore_construct(&uartTaskSem, 0, NULL);
uartTaskSemHandle = Semaphore_handle(&uartTaskSem);
// Configure the Uart task
Task_Params_init(&uartTaskParams);
uartTaskParams.stack = uartTaskStack;
uartTaskParams.stackSize = sizeof(uartTaskStack);
uartTaskParams.priority = 2;
Task_construct(&uartTaskStruct, scUartTask, &uartTaskParams, NULL);
}
void rfTxTask()
{
//RF_Params_init(&rfTxParams);
// TX指令參數設定
RF_cmdPropTx.pPkt = rfTxPacket;
RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
//rfTxHandle = RF_open(&rfTxObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfTxParams);
//設定頻率
//RF_postCmd(rfTxHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
while(1)
{
printf("rfTxTask wait for semaphore post\n");
Semaphore_pend(rfTxTaskSemHandle, BIOS_WAIT_FOREVER);
if(uartRxCount > 0)
{
RF_cmdPropTx.pktLen = uartRxCount;
int i;
for(i=0; i<uartRxCount; i++)
{
rfTxPacket[i] = UartRxBuf[i];
}
/*for(i=0;i<sizeof(rfTxPacket);i++)
{
printf("%c\n",rfTxPacket[i]);
}*/
RF_cancelCmd(rfHandle, rfRxPostHandle, 1);
PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 0);
rfRxPostHandle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx,RF_PriorityNormal, &ReceivedOnRFcallback,RF_EventRxEntryDone);
uartRxCount = 0;
for(i=0;i<sizeof(UartRxBuf);i++)
{
UartRxBuf[i] = '\0';
}
}
}
}
void rfTxTaskInit()
{
//Initialize RFTx semaphore
Semaphore_construct(&rfTxTaskSem, 0, NULL);
rfTxTaskSemHandle = Semaphore_handle(&rfTxTaskSem);
// Configure the RFTx task
Task_Params_init(&rfTxTaskParams);
rfTxTaskParams.stack = rfTxTaskStack;
rfTxTaskParams.stackSize = sizeof(rfTxTaskStack);
rfTxTaskParams.priority = 1;
Task_construct(&rfTxTaskStruct, rfTxTask, &rfTxTaskParams, NULL);
}
void rfInit()
{
RF_Params_init(&rfParams);
rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
//設定頻率
RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
}
void *mainThread(void *arg0)
{
while(ledPinHandle == NULL)
{
led_init();
}
uartTaskInit();
rfInit();
rfTxTaskInit();
}