Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
|
Here we going to see the demo of "Wireless UART" demo on Rapid IoT Kit. we know that Rapid IoT has build with two MCU, KW41z & K64F. For this demo you should have SDK for KW41z, I have used SDK_2.2.0_FRDM-KW41Z.
Things Required:MCUXpressoIDE -> Download it from here
SDK for Rapid-IoT-Kit -> Download it from here
SDK for KW41z -> Download it from here
Android or IOS App - IoT Toolbox here
Steps to Follow:The first step to Import "wireless uart" project from KW41z SDK examples.
The next step, you have to disable the keyboard functionality (keyboard.h)
/* * Name: gKeyBoardSupported_d * Description: Enables/disables the switches based keyboard */#ifndef gKeyBoardSupported_d#define gKeyBoardSupported_d 0#endif
Rapid IoT kit hardware does not have 4 LED's interface with KW41 so some changes are required as below
Also remove usage of Led3 & Led4 usages from everywhere.
/** Name: gLEDsOnTargetBoardDefault_c* Description: Default value for LEDs count located on a* generic target board*/#ifndef gLEDsOnTargetBoardDefault_c#define gLEDsOnTargetBoardDefault_c 2#endif
Next step we need to add below code, so that K41z will start the advertising automatically after power on.
/* BLE Host Stack Init */ if (Ble_Initialize(App_GenericCallback) != gBleSuccess_c) { panic(0,0,0,0); return; }
LED_StopFlashingAllLeds(); Led1Flashing();
BleApp_Start(gGapPeripheral_c);
Now we can compile the code and flash it in Rapid IoT Kit for KW41z.
The next part is Import the "Hello World" example from Rapid IoT Kit SDK
Next step change the baud-rate for FSCI Interface (UART 4)
/* FSCI Interface Configuration structure */static const gFsciSerialConfig_t mFsciSerials[] ={ { .baudrate = gUARTBaudRate115200_c, .interfaceType = gSerialMgrUart_c, .interfaceChannel = 4, .virtualInterface = 0 },
Also some changes in FsciCommunication.c & hello_world.c please refer the attached source.
Compile the code then flash it into Rapid Kit for K64F, and the demo is ready. Now you can use "IoT Toolbox" Android or IOS App to send text to Kit.
Working demo of video is here:
/*
* Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of the copyright holder 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 HOLDER 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.
*/
/*==================================================================================================
Include Files
==================================================================================================*/
#include <stdio.h>
#include "fsl_device_registers.h"
#include "fsl_os_abstraction.h"
#include "fsl_sysmpu.h"
#include "fsl_port.h"
#include "pin_mux.h"
#if WDOG_ENABLE
#include "fsl_wdog.h"
#endif
#ifndef FRDM_K64F_KW41Z
#include "PhyInterface.h"
#include "MacInterface.h"
#endif
/* FSL Framework */
#include "LED.h"
#include "rgb_led.h"
#include "backlight.h"
#include "sensors.h"
#include "nvm_adapter.h"
#include "TimersManager.h"
#include "Keyboard.h"
#include "SerialManager.h"
#include "Panic.h"
#include "fsl_os_abstraction.h"
#include "app_init.h"
#include "app_config.h"
#include "thread_network.h"
#include "thread_cfg.h"
#include "debug_log.h"
#if THREAD_USE_THCI
#include "thci.h"
#include "FsciInterface.h"
#endif
#if THREAD_USE_SHELL
#include "shell_ip.h"
#endif
#ifdef FRDM_K64F_KW41Z
#include "FsciInterface.h"
#include "cmd_threadip.h"
#include "shell_ip.h"
#if gHybridApp_d
#include "cmd_ble.h"
#include "ble_shell.h"
#endif
#if SHELL_DEBUGGER
#include "shell_peripherals.h"
#endif
#if LWIP_IPV6
#include "lwip/opt.h"
#include "lwip/tcpip.h"
#include "lwip/ethip6.h"
#include "lwip/dhcp.h"
#include "lwip/mld6.h"
#include "lwip/prot/dhcp.h"
#include "netif/ethernet.h"
#include "ethernetif.h"
#endif
#endif
/* Display */
#include "BUTTON.h"
#include "CHECKBOX.h"
#include "DROPDOWN.h"
#include "GUI.h"
#include "MULTIPAGE.h"
#include "RADIO.h"
#include "SLIDER.h"
#include "emwin_support.h"
extern void APP_Init(void);
extern void APP_Handler(void);
#if gLpmIncluded_d
extern void App_SedWakeUpFromKeyBoard(void);
#endif
#if THCI_USB_ENABLE && THR_SOFTWARE_RESET_ENABLE
extern void THCI_ResetCpuEvent(resetCpuStatus_t resetStatus, uint32_t timeoutUs);
#endif
/*==================================================================================================
Private macros
==================================================================================================*/
#define gFSCI_IpStackOpGCnf_c 0xCFU
/*! FSCI utility Confirmations/Indications */
#define gFSCI_CnfOpcodeGroup_c 0xA4
/*! FSCI operation group for GATT Database (application) */
#define gFsciBleL2capOpcodeGroup_c 0x41
/*! FSCI operation group for GATT */
#define gFsciBleGattOpcodeGroup_c 0x44
/*! FSCI operation group for GATT Database (application) */
#define gFsciBleGattDbAppOpcodeGroup_c 0x45
/*! FSCI operation group for GAP */
#define gFsciBleGapOpcodeGroup_c 0x47
/* ATTENTION: the following static configuration is not used, as DHCP is used instead */
/* IP address configuration. */
#define configIP_ADDR0 192
#define configIP_ADDR1 168
#define configIP_ADDR2 0
#define configIP_ADDR3 142
/* Netmask configuration. */
#define configNET_MASK0 255
#define configNET_MASK1 255
#define configNET_MASK2 255
#define configNET_MASK3 0
/* Gateway address configuration. */
#define configGW_ADDR0 192
#define configGW_ADDR1 168
#define configGW_ADDR2 0
#define configGW_ADDR3 1
/*==================================================================================================
Private type definitions
==================================================================================================*/
/*==================================================================================================
Private prototypes
==================================================================================================*/
static void fsciThciRegister(uint32_t fsciInterfaceId);
static void fsciBleRegister(uint32_t fsciInterfaceId);
static void THCI_RxCb(void *pData, void *param, uint32_t interfaceId);
static void BLE_FSCI_RxCb(void *pData, void *param, uint32_t interfaceId);
static void APP_HandleMcuResetOnIdle(void);
#if gLpmIncluded_d
static void APP_HandleLowPowerOnIdle(void);
#endif
#if WDOG_ENABLE
static void APP_WDOG_Init(void);
static void APP_WDOG_Refresh(void);
#endif
/*==================================================================================================
Private global variables declarations
==================================================================================================*/
void (*pfAppKeyboardHandler)(void *) = NULL;
#if WDOG_ENABLE
/* Configure watchdog. */
const wdog_config_t wdogConfig =
{
.enableWdog = TRUE, /* Watchdog mode */
.timeoutValue = 0x4096U, /* Watchdog overflow time is about 4s*/
.enableWindowMode = FALSE, /* Disable window function */
.windowValue = 0, /* Watchdog window value */
.prescaler = kWDOG_ClockPrescalerDivide1, /* Watchdog clock prescaler */
.enableUpdate = TRUE, /* Update register enabled */
.clockSource = kWDOG_LpoClockSource, /* Watchdog clock source is LPO 1KHz */
#if defined(FSL_FEATURE_WDOG_HAS_WAITEN) && FSL_FEATURE_WDOG_HAS_WAITEN
.workMode.enableWait = TRUE, /* Enable watchdog in wait mode */
#endif
.workMode.enableStop = FALSE, /* Enable watchdog in stop mode */
.workMode.enableDebug = FALSE, /* Disable watchdog in debug mode */
};
static WDOG_Type *wdog_base = WDOG;
#endif
/*!< reset MCU timestamp <microseconds> */
static uint64_t gSwResetTimestamp = 0;
/*!< boolean - nvm format */
static bool_t gResetToFactory = FALSE;
/* FSCI Interface Configuration structure */
static const gFsciSerialConfig_t mFsciSerials[] =
{
{
.baudrate = gUARTBaudRate115200_c,
.interfaceType = gSerialMgrUart_c,
.interfaceChannel = 4,
.virtualInterface = 0
},
#if gHybridApp_d
{
.baudrate = gUARTBaudRate115200_c,
.interfaceType = gSerialMgrUart_c,
.interfaceChannel = 4,
.virtualInterface = 1
}
#endif
};
#if 0
static struct netif fsl_netif0;
/* IPv6 multicast group FF03::3EAD */
static const ip_addr_t realmlocal_mcast_3ead =
IPADDR6_INIT(PP_HTONL(0xFF030000UL),
PP_HTONL(0x00000000UL),
PP_HTONL(0x00000000UL),
PP_HTONL(0x00003EADUL)
);
#endif
/*==================================================================================================
Public global variables declarations
==================================================================================================*/
taskMsgQueue_t appThreadMsgQueue;
osaSemaphoreId_t gOtaSem;
char lcdtext[32];
char *lcdp = lcdtext;
char linecount= 9;
int wuartreceived = 0;
/*==================================================================================================
Public functions
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/
/* Functions required for emwin / Display */
uint32_t DSPI2_GetFreq(void)
{
return CLOCK_GetBusClkFreq();
}
void Clear_Buffer(void){
int i=0;
for(i=0;i<32;i++){
lcdtext[i]='\0';
}
}
void Init_Display()
{
Display_Connect(); /* triggers GUI_Init() */
Backlight_SetLevel(BLIGHT_LEVEL_HIGH);
GUI_SetBkColor(GUI_BLACK);
GUI_SetColor(GUI_WHITE);
}
#define GUI_FONT_TITLE GUI_Font8x18
#define GUI_FONT_NORMAL GUI_Font8x16
void main_task(uint32_t param)
{
static uint8_t mainInitialized = FALSE;
if (!mainInitialized)
{
mainInitialized = TRUE;
#if WDOG_ENABLE
/* Init watchdog module */
APP_WDOG_Init();
#endif
/* Init memory blocks manager */
MEM_Init();
/* Init timers module */
TMR_Init();
TMR_TimeStampInit();
SerialManager_Init();
#ifdef FRDM_K64F_KW41Z
/* Initialize shell for Thread commands */
SHELLComm_Init(&appThreadMsgQueue);
/* Initialize FSCI (on two virtual interfaces if hybrid mode is on) */
FSCI_Init((void *)&mFsciSerials);
#if gHybridApp_d
/* Initialize shell for BLE commands */
BleApp_Init();
#endif
#if SHELL_DEBUGGER
/* Initialize shell get and set commands*/
Cmd_Init();
#endif
#endif
}
/* Register Handler for events coming from KW41Z on interface 0 */
fsciThciRegister(0);
#if gHybridApp_d
/* Register Handler for BLE events coming from KW41Z on virtual interface 1 */
fsciBleRegister(1);
#endif
/* Create semaphore to disable (lock) UI manager while running OTA */
gOtaSem = OSA_SemaphoreCreate(0U);
if (NULL == gOtaSem)
{
panic(0,0,0,0);
}
/* Initialize all sensors */
Init_all_sensors();
/* Init Led module */
LED_Init();
/* Turn on LCD display */
Init_Display();
/* Display a Message */
GUI_SetFont(&GUI_Font8x18);
GUI_SetBkColor(GUI_WHITE);
GUI_Clear();
GUI_SetColor(GUI_BLUE);
GUI_DispString("\n Rapid IoT\n\n");
GUI_DispString(" WUART Demo!\n\n");
/* Write to the terminal through the shell */
shell_write("\r\n\n** Running Rapid IoT - WUART Demo! **\n\n\r");
/* Main Application Loop (idle state) */
while (1)
{
if(wuartreceived){
shell_write("\n");
shell_write(lcdp);
if(linecount>8)
{
GUI_Clear();
GUI_DispString("\n");
linecount=0;
}
GUI_DispString(" ");
GUI_DispString(lcdp);
wuartreceived = 0;
linecount++;
Clear_Buffer();
}
/* Debug Checks, Leader LED restore check */
DBG_Check();
/* Reset MCU */
APP_HandleMcuResetOnIdle();
/* For BareMetal break the while(1) after 1 run */
if (gUseRtos_c == 0)
{
break;
}
}
}
bool_t SERIAL_TAP_IP6_SEND(struct pbuf *p, struct netif *inp)
{
struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
SerialTun_IPPacketSendRequest_t req =
{
.Size = SIZEOF_ETH_HDR + p->tot_len,
.Data = (uint8_t *)p->payload - SIZEOF_ETH_HDR
};
// TCP traffic is not sent to the black-box
if (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_TCP)
{
SerialTun_IPPacketSendRequest(&req, 0);
// UDP traffic is not processed by LwIP
if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP)
{
pbuf_free(p);
return TRUE;
}
}
// not eaten traffic to be processed by LwIP
return FALSE;
}
/*!*************************************************************************************************
\fn APP_ResetMcuOnTimeout
\brief Reset the MCU on timeout
\param [in] timeoutMs timeout in milliseconds
\param [in] resetToFactory
\return None
***************************************************************************************************/
void APP_ResetMcuOnTimeout(uint32_t timeoutMs, bool_t resetToFactory)
{
gResetToFactory = resetToFactory;
gSwResetTimestamp = TMR_GetTimestamp();
gSwResetTimestamp += (timeoutMs * 1000); /* microseconds*/
}
/*!*************************************************************************************************
\fn APP_GetResetMcuTimeout
\brief Return the interval time until a MCU reset occurs
\return the time interval; 0 means that no Mcu reset was programmed
***************************************************************************************************/
uint32_t APP_GetResetMcuTimeout(void)
{
uint32_t timeInterval = 0;
if (gSwResetTimestamp > TMR_GetTimestamp())
{
timeInterval = (uint32_t)((gSwResetTimestamp - TMR_GetTimestamp())
/ 1000);
}
return timeInterval;
}
/*==================================================================================================
Private functions
==================================================================================================*/
static void fsciThciRegister(uint32_t fsciInterfaceId)
{
if (FSCI_RegisterOpGroup(gFSCI_IpStackOpGCnf_c,
gFsciMonitorMode_c,
THCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciThciRegister, 0, 0);
}
}
static void fsciBleRegister(uint32_t fsciInterfaceId)
{
/* Register Generic FSCI */
if (FSCI_RegisterOpGroup(gFSCI_CnfOpcodeGroup_c,
gFsciMonitorMode_c,
BLE_FSCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciBleRegister, 0, 0);
}
/* Register L2CAP command handler */
if (FSCI_RegisterOpGroup(gFsciBleL2capOpcodeGroup_c,
gFsciMonitorMode_c,
BLE_FSCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciBleRegister, 0, 0);
}
/* Register GATT command handler */
if (FSCI_RegisterOpGroup(gFsciBleGattOpcodeGroup_c,
gFsciMonitorMode_c,
BLE_FSCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciBleRegister, 0, 0);
}
/* Register GATT Database (application) command handler */
if (FSCI_RegisterOpGroup(gFsciBleGattDbAppOpcodeGroup_c,
gFsciMonitorMode_c,
BLE_FSCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciBleRegister, 0, 0);
}
/* Register GAP command handler */
if (FSCI_RegisterOpGroup(gFsciBleGapOpcodeGroup_c,
gFsciMonitorMode_c,
BLE_FSCI_RxCb,
NULL,
fsciInterfaceId) != gFsciSuccess_c)
{
panic(0, (uint32_t)fsciBleRegister, 0, 0);
}
}
static void THCI_RxCb
(
void *pData,
void *param,
uint32_t interfaceId
)
{
thrEvtContainer_t container; // this could be allocated instead
KHC_ThreadIP_RX_MsgHandler(pData, &container, interfaceId);
SHELL_ThrEventNotify(&container);
}
static void BLE_FSCI_RxCb
(
void *pData,
void *param,
uint32_t interfaceId
)
{
#if gHybridApp_d
bleEvtContainer_t container; // this could be allocated instead
KHC_BLE_RX_MsgHandler(pData, &container, interfaceId);
SHELL_BleEventNotify(&container);
#endif
}
/*!*************************************************************************************************
\fn APP_HandleMcuResetOnIdle
\brief Reset the MCU on idle
\param [in]
\return None
***************************************************************************************************/
static void APP_HandleMcuResetOnIdle(void)
{
if ((gSwResetTimestamp) && (gSwResetTimestamp < TMR_GetTimestamp()))
{
gSwResetTimestamp = 0;
/* disable interrupts */
OSA_InterruptDisable();
#if THCI_USB_ENABLE && THR_SOFTWARE_RESET_ENABLE
THR_SoftwareReset(0, gResetToFactory);
/* inform application */
THCI_ResetCpuEvent(gResetCpuSuccess_c, 0);
#else
if (gResetToFactory)
{
/* Erase NVM Datasets */
//NvFormat();
}
ResetMCU();
#endif
/* Enable interrupts */
OSA_InterruptEnable();
}
}
/*!*************************************************************************************************
\fn APP_HandleLowPowerOnIdle
\brief Handle low power on idle
\param [in]
\return None
***************************************************************************************************/
#if gLpmIncluded_d
static void APP_HandleLowPowerOnIdle(void)
{
if (PWR_CheckIfDeviceCanGoToSleep())
{
PWRLib_WakeupReason_t wakeupReason;
wakeupReason = PWR_EnterLowPower();
if (wakeupReason.Bits.FromKeyBoard)
{
/* Protection to the LLWD pin enabled on both edges */
static bool_t wakeUpFlag = FALSE;
if (TRUE == wakeUpFlag)
{
wakeUpFlag = FALSE;
App_SedWakeUpFromKeyBoard();
}
else
{
wakeUpFlag = TRUE;
}
PWR_AllowDeviceToSleep();
}
}
}
#endif
/*!*************************************************************************************************
\fn static void APP_WDOG_Init(void)
\brief Init watch dog if enabled
***************************************************************************************************/
#if WDOG_ENABLE
static void APP_WDOG_Init(void)
{
uint32_t i = 0;
WDOG_Init(wdog_base, &wdogConfig);
/* Accessing register by bus clock */
for (i = 0; i < 256; i++)
{
(void)WDOG->RSTCNT;
}
}
/*!*************************************************************************************************
\fn static void APP_WDOG_Refresh(void)
\brief Refresh watch dog if enabled
***************************************************************************************************/
static void APP_WDOG_Refresh(void)
{
uint32_t wdogTimer = (uint32_t)((((uint32_t)wdog_base->TMROUTH) << 16U) | (wdog_base->TMROUTL));
/* Restart the watchdog so it doesn't reset */
if (wdogTimer > (wdogConfig.timeoutValue >> 3U))
{
WDOG_Refresh(wdog_base);
}
}
#endif
/*==================================================================================================
Private debug functions
==================================================================================================*/
/*!
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* \file
*
* This is a source file for the FSCI communication.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o 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.
*
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
*/
/************************************************************************************
*************************************************************************************
* Include
*************************************************************************************
************************************************************************************/
#include "FsciCommunication.h"
#include "FsciInterface.h"
#include "FsciCommands.h"
#include "FunctionLib.h"
#include "MemManager.h"
#include "Panic.h"
#include "TimersManager.h"
#include "fsl_os_abstraction.h"
#include "thci.h"
#if gNvStorageIncluded_d
#include "NVM_Interface.h"
#endif
#if gFsciIncluded_c
/************************************************************************************
*************************************************************************************
* Private macros
*************************************************************************************
************************************************************************************/
#define gFsciUseBlockingTx_c 1
#define MIN_VALID_PACKET_LEN (sizeof(clientPacketHdr_t))
#define FSCI_txCallback MEM_BufferFree
#define FSCI_rxCallback FSCI_receivePacket
#ifndef mFsciRxAckTimeoutMs_c
#define mFsciRxAckTimeoutMs_c 100 /* milliseconds */
#endif
#ifndef mFsciTxRetryCnt_c
#define mFsciTxRetryCnt_c 4
#endif
#ifndef mFsciRxRestartTimeoutMs_c
#define mFsciRxRestartTimeoutMs_c 50 /* milliseconds */
#endif
/************************************************************************************
*************************************************************************************
* Private prototypes
*************************************************************************************
************************************************************************************/
fsci_packetStatus_t FSCI_checkPacket( clientPacket_t *pData, uint16_t bytes, uint8_t* pVIntf );
#if gFsciRxAck_c && gFsciRxAckTimeoutUseTmr_c
static void FSCI_RxAckExpireCb(void *param);
#endif
#if gFsciRxTimeout_c && !mFsciRxTimeoutUsePolling_c
static void FSCI_RxRxTimeoutCb(void *param);
#endif
static void FSCI_SendPacketToSerialManager(uint32_t fsciInterface, uint8_t *pPacket, uint16_t packetLen);
/************************************************************************************
*************************************************************************************
* Private type definitions
*************************************************************************************
************************************************************************************/
/************************************************************************************
*************************************************************************************
* Public memory declarations
*************************************************************************************
************************************************************************************/
uint8_t gFsciTxBlocking = FALSE;
uint8_t gFsciTxDisable = FALSE;
/* Holds the SMGR interface Id associated with the FSCI interface (index) */
uint8_t gFsciSerialInterfaces[gFsciMaxInterfaces_c];
extern char lcdtext[32];
extern int wuartreceived;
#if gFsciMaxVirtualInterfaces_c
/* Holds the virtual interface Id for the FSCI interface (index) */
uint8_t gFsciVirtualInterfaces[gFsciMaxInterfaces_c];
#endif
#if gFsciHostSupport_c
#if gFsciHostSyncUseEvent_c && !USE_RTOS
#undef gFsciHostSyncUseEvent_c
#endif
#if gFsciHostSyncUseEvent_c
osaEventId_t gFsciHostSyncRspEventId;
#endif
clientPacket_t *pFsciHostSyncRsp = NULL;
bool_t gFsciHostWaitingSyncRsp = FALSE;
opGroup_t gFsciHostWaitingOpGroup = 0;
opCode_t gFsciHostWaitingOpCode = 0;
#endif
/************************************************************************************
*************************************************************************************
* Private memory declarations
*************************************************************************************
************************************************************************************/
static fsciComm_t mFsciCommData[gFsciMaxInterfaces_c];
static uint8_t mFsciSrcInterface = mFsciInvalidInterface_c;
/************************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
************************************************************************************/
#if gFsciHostSupport_c
void FSCI_HostSyncLock(uint32_t fsciInstance, opGroup_t OG, opCode_t OC)
{
OSA_MutexLock(mFsciCommData[fsciInstance].syncHostMutexId, osaWaitForever_c);
gFsciHostWaitingSyncRsp = TRUE;
gFsciHostWaitingOpGroup = OG;
gFsciHostWaitingOpCode = OC;
pFsciHostSyncRsp = NULL;
}
void FSCI_HostSyncUnlock(uint32_t fsciInstance)
{
gFsciHostWaitingSyncRsp = FALSE;
pFsciHostSyncRsp = NULL;
OSA_MutexUnlock(mFsciCommData[fsciInstance].syncHostMutexId);
}
#endif
/*! *********************************************************************************
* \brief Initialize the serial interface.
*
* \param[in] initStruct pointer to a gFsciSerialConfig_t structure
*
********************************************************************************** */
void FSCI_commInit( gFsciSerialConfig_t* pSerCfg )
{
uint32_t i;
#if gFsciMaxVirtualInterfaces_c
uint32_t j;
#endif
if (NULL == pSerCfg)
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
return;
}
FLib_MemSet( mFsciCommData, 0x00, sizeof(mFsciCommData) );
#if gFsciHostSupport_c && gFsciHostSyncUseEvent_c
if( (gFsciHostSyncRspEventId = OSA_EventCreate(TRUE)) == NULL )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
return;
}
#endif
#if gFsciHostSupport_c && !gFsciHostSyncUseEvent_c
TMR_TimeStampInit();
#endif
for ( i = 0; i < gFsciMaxInterfaces_c; i++ )
{
gFsciSerialInterfaces[i] = gSerialMgrInvalidIdx_c;
#if gFsciMaxVirtualInterfaces_c
gFsciVirtualInterfaces[i] = pSerCfg[i].virtualInterface;
if( pSerCfg[i].virtualInterface >= gFsciMaxInterfaces_c )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
break;
}
/* Check if the serial interface was allready initialized */
for( j = 0; j < i; j++ )
{
if( (pSerCfg[i].interfaceType == pSerCfg[j].interfaceType) &&
(pSerCfg[i].interfaceChannel == pSerCfg[j].interfaceChannel) )
{
gFsciSerialInterfaces[i] = gFsciSerialInterfaces[j];
}
}
if( gFsciSerialInterfaces[i] == gSerialMgrInvalidIdx_c )
#endif
{
Serial_InitInterface(&gFsciSerialInterfaces[i],
pSerCfg[i].interfaceType,
pSerCfg[i].interfaceChannel );
Serial_SetRxCallBack( gFsciSerialInterfaces[i], FSCI_rxCallback, (void*)i);
Serial_SetBaudRate ( gFsciSerialInterfaces[i], pSerCfg[i].baudrate );
#if gFsciHostSupport_c
if( (mFsciCommData[i].syncHostMutexId = OSA_MutexCreate()) == NULL )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
break;
}
#endif
#if gFsciRxAck_c
if( (mFsciCommData[i].syncTxRxAckMutexId = OSA_MutexCreate()) == NULL )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
break;
}
#if gFsciRxAckTimeoutUseTmr_c
mFsciCommData[i].ackWaitTmr = TMR_AllocateTimer();
if( gTmrInvalidTimerID_c == mFsciCommData[i].ackWaitTmr )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
break;
}
#else
TMR_TimeStampInit();
#endif
mFsciCommData[i].txRetryCnt = mFsciTxRetryCnt_c;
mFsciCommData[i].ackReceived = FALSE;
mFsciCommData[i].ackWaitOngoing = FALSE;
#endif
#if gFsciRxTimeout_c
#if mFsciRxTimeoutUsePolling_c
TMR_TimeStampInit();
#else
mFsciCommData[i].rxRestartTmr = TMR_AllocateTimer();
if( gTmrInvalidTimerID_c == mFsciCommData[i].rxRestartTmr )
{
panic( ID_PANIC(0,0), (uint32_t)FSCI_commInit, 0, 0 );
break;
}
#endif
mFsciCommData[i].rxOngoing = FALSE;
mFsciCommData[i].rxTmrExpired = FALSE;
#endif
}
}
}
/*! *********************************************************************************
* \brief Receives data from the serial interface and checks to see if we have a valid pachet.
*
* \param[in] param the fsciInterface on which the data has been received
*
********************************************************************************** */
void FSCI_receivePacket( void* param )
{
uint16_t readBytes;
uint8_t c;
static uint8_t bytesReceived=0;
if( gSerial_Success_c != Serial_GetByteFromRxBuffer( gFsciSerialInterfaces[(uint32_t)param], &c, &readBytes ) )
{
return;
}
while( readBytes && !wuartreceived)
{
if(c == '\r'){
bytesReceived = 0;
wuartreceived = 1;
}
else
{
lcdtext[bytesReceived++] =c;
} /* if (!startOfFrameSeen) */
if ( gSerial_Success_c != Serial_GetByteFromRxBuffer( gFsciSerialInterfaces[(uint32_t)param], &c, &readBytes ) )
{
break;
}
}
}
/*! *********************************************************************************
* \brief Send packet over the serial interface, after computing Checksum.
*
* \param[in] pPacket pointer to the packet to be sent over the serial interface
* \param[in] fsciInterface the interface on which the packet should be sent
*
********************************************************************************** */
void FSCI_transmitFormatedPacket( void *pPacket, uint32_t fsciInterface )
{
clientPacket_t *pPkt = pPacket;
uint32_t size;
uint32_t virtInterface = FSCI_GetVirtualInterface(fsciInterface);
uint8_t checksum;
pPkt->structured.header.startMarker = gFSCI_StartMarker_c;
size = sizeof(clientPacketHdr_t) + pPkt->structured.header.len + 1 /* CRC */;
/* Compute Checksum */
checksum = FSCI_computeChecksum( pPkt->raw+1, size - 2);
pPkt->structured.payload[pPkt->structured.header.len] = checksum;
if( virtInterface )
{
#if gFsciMaxVirtualInterfaces_c
pPkt->structured.payload[pPkt->structured.header.len] += virtInterface;
pPkt->structured.payload[pPkt->structured.header.len+1] = checksum^(checksum + virtInterface);
size += sizeof(checksum);
#else
(void)virtInterface;
#endif
}
/* send message to Serial Manager */
FSCI_SendPacketToSerialManager(fsciInterface, pPkt->raw, size);
}
/*! *********************************************************************************
* \brief Encode and send messages over the serial interface
*
* \param[in] OG operation Group
* \param[in] OC operation Code
* \param[in] pMsg pointer to payload
* \param[in] msgLen length of the payload
* \param[in] fsciInterface the interface on which the packet should be sent
*
********************************************************************************** */
void FSCI_transmitPayload( uint8_t OG, uint8_t OC, void *pMsg, uint16_t msgLen, uint32_t fsciInterface )
{
uint8_t* buffer_ptr = NULL;
uint16_t buffer_size, index;
uint8_t checksum, checksum2;
clientPacketHdr_t header;
uint32_t virtInterface = FSCI_GetVirtualInterface(fsciInterface);
if( gFsciTxDisable || (msgLen > gFsciMaxPayloadLen_c) )
{
return;
}
/* Compute size */
buffer_size = sizeof(clientPacketHdr_t) + msgLen + 2*sizeof(checksum);
#if gFsciUseEscapeSeq_c
buffer_size = buffer_size*2;
#endif
/* Allocate buffer */
buffer_ptr = MEM_BufferAlloc( buffer_size );
if( NULL == buffer_ptr )
{
return;
}
/* Message header */
header.startMarker = gFSCI_StartMarker_c;
header.opGroup = OG;
header.opCode = OC;
header.len = msgLen;
/* Compute CRC for TX packet, on opcode group, opcode, payload length, and payload fields */
checksum = FSCI_computeChecksum((uint8_t*)&header + 1, sizeof(header) - 1);
checksum ^= FSCI_computeChecksum((uint8_t*)pMsg, msgLen);
if( virtInterface )
{
checksum2 = checksum^(checksum + virtInterface);
checksum += virtInterface;
}
index = 0;
#if gFsciUseEscapeSeq_c
index += FSCI_encodeEscapeSeq( (uint8_t*)&header, sizeof(header), &buffer_ptr[index] );
index += FSCI_encodeEscapeSeq( pMsg, msgLen, &buffer_ptr[index]);
/* Store the Checksum*/
index += FSCI_encodeEscapeSeq( (uint8_t*)&checksum, sizeof(checksum), &buffer_ptr[index] );
if( virtInterface )
{
index += FSCI_encodeEscapeSeq( (uint8_t*)&checksum2, sizeof(checksum2), &buffer_ptr[index] );
}
buffer_ptr[index++] = gFSCI_EndMarker_c;
#else /* gFsciUseEscapeSeq_c */
FLib_MemCpy( &buffer_ptr[index], &header, sizeof(header) );
index += sizeof(header);
FLib_MemCpy( &buffer_ptr[index], pMsg, msgLen );
index += msgLen;
/* Store the Checksum */
buffer_ptr[index++] = checksum;
if( virtInterface )
{
buffer_ptr[index++] = checksum2;
}
#endif /* gFsciUseEscapeSeq_c */
/* send message to Serial Manager */
FSCI_SendPacketToSerialManager(fsciInterface, buffer_ptr, index);
}
/*! *********************************************************************************
* \brief Get a FSCI formatted packet from a payload message
*
* \param[in] OG operation Group
* \param[in] OC operation Code
* \param[in] pMsg pointer to payload
* \param[in] msgLen length of the payload
* \param[out] pOutLen the actual length of the formatted packet
*
********************************************************************************** */
uint8_t* FSCI_GetFormattedPacket(uint8_t OG, uint8_t OC, void *pMsg, uint16_t msgLen, uint16_t *pOutLen)
{
uint8_t* pBuff = NULL;
clientPacketHdr_t header;
uint16_t index = 0;
uint8_t checksum = 0;
if( (msgLen > gFsciMaxPayloadLen_c) || (NULL == pOutLen) ||
(msgLen && (NULL == pMsg)) )
{
return NULL;
}
else
{
pBuff = MEM_BufferAlloc(sizeof(header) + msgLen + sizeof(checksum));
if( pBuff )
{
header.startMarker = gFSCI_StartMarker_c;
header.opGroup = OG;
header.opCode = OC;
header.len = msgLen;
FLib_MemCpy(pBuff, &header, sizeof(header));
index += sizeof(header);
FLib_MemCpy(pBuff+index, pMsg, msgLen);
index += msgLen;
checksum = FSCI_computeChecksum(pBuff+1, sizeof(header)-1 + msgLen);
pBuff[index++] = checksum;
*pOutLen = index;
return pBuff;
}
else
{
return NULL;
}
}
}
/************************************************************************************
*************************************************************************************
* Private functions
*************************************************************************************
************************************************************************************/
/*! *********************************************************************************
* \brief Returnd the virtual interface associated with the specified fsciInterface.
*
* \param[in] fsciInterface the interface on which the packet should be sent
*
* \return the Virtual Interface Id
*
********************************************************************************** */
uint32_t FSCI_GetVirtualInterface(uint32_t fsciInterface)
{
#if gFsciMaxVirtualInterfaces_c
return gFsciVirtualInterfaces[fsciInterface];
#else
return 0;
#endif
}
/*! *********************************************************************************
* \brief Determines the FSCI interface for a received packet.
*
* \param[in] hwInterface the serial interface on which the packet was received.
* \param[in] virtualInterface the virtual interface of the received packet
*
* \return the FSCI interface
*
********************************************************************************** */
uint32_t FSCI_GetFsciInterface(uint32_t hwInterface, uint32_t virtualInterface)
{
#if gFsciMaxVirtualInterfaces_c
uint32_t i;
for( i = 0; i < gFsciMaxInterfaces_c; i++)
{
if( (virtualInterface == gFsciVirtualInterfaces[i]) && (hwInterface == gFsciSerialInterfaces[i]) )
{
hwInterface = i;
break;
}
}
#endif
return hwInterface;
}
/*! *********************************************************************************
* \brief Checks to see if we have a valid packet
*
* \param[in] pData The message containing the incoming data packet to be handled.
* \param[in] bytes the number of bytes inside the buffer
* \param[Out] pVIntf pointer to the location where the virtual interface Id will be stored
*
* \return the status of the packet
*
********************************************************************************** */
fsci_packetStatus_t FSCI_checkPacket( clientPacket_t *pData, uint16_t bytes, uint8_t* pVIntf )
{
uint8_t checksum = 0;
uint16_t len;
if ( bytes < MIN_VALID_PACKET_LEN )
{
return PACKET_IS_TO_SHORT; /* Too short to be valid. */
}
if ( bytes >= sizeof(clientPacket_t) )
{
printf("framing_error1!\r\n");
return FRAMING_ERROR;
}
if ( NULL == pData )
{
return INTERNAL_ERROR;
}
/* The packet's len field does not count the STX, the opcode group, the */
/* opcode, the len field, or the checksum. */
len = pData->structured.header.len;
/* If the length appears to be too long, it might be because the external */
/* client is sending a packet that is too long, or it might be that we're */
/* out of sync with the external client. Assume we're out of sync. */
if ( len > gFsciMaxPayloadLen_c )
{
printf("framing_error2!\r\n");
return FRAMING_ERROR;
}
if ( bytes < len + sizeof(clientPacketHdr_t) + sizeof(checksum) )
{
return PACKET_IS_TO_SHORT;
}
/* If the length looks right, make sure that the checksum is correct. */
if( bytes >= len + sizeof(clientPacketHdr_t) + sizeof(checksum) )
{
checksum = FSCI_computeChecksum(pData->raw+1, len + sizeof(clientPacketHdr_t)-1);
*pVIntf = pData->structured.payload[len] - checksum;
}
if( bytes == len + sizeof(clientPacketHdr_t) + sizeof(checksum) )
{
if( 0 == *pVIntf )
{
return PACKET_IS_VALID;
}
#if gFsciMaxVirtualInterfaces_c
else
{
if( *pVIntf < gFsciMaxVirtualInterfaces_c )
{
return PACKET_IS_TO_SHORT;
}
}
#endif
}
#if gFsciMaxVirtualInterfaces_c
/* Check virtual interface */
if( bytes == len + sizeof(clientPacketHdr_t) + 2*sizeof(checksum) )
{
checksum ^= checksum + *pVIntf;
if( pData->structured.payload[len+1] == checksum )
{
return PACKET_IS_VALID;
}
}
#endif
printf("framing_error3!\r\n");
return FRAMING_ERROR;
}
/*! *********************************************************************************
* \brief This function performs a XOR over the message to compute the CRC
*
* \param[in] pBuffer - pointer to the messae
* \param[in] size - the length of the message
*
* \return the CRC of the message
*
********************************************************************************** */
uint8_t FSCI_computeChecksum( void *pBuffer, uint16_t size )
{
uint16_t index;
uint8_t checksum = 0;
for ( index = 0; index < size; index++ )
{
checksum ^= ((uint8_t*)pBuffer)[index];
}
return checksum;
}
/*! *********************************************************************************
* \brief This function performs the encoding of a message, using the Escape Sequence
*
* \param[in] pDataIn, pointer to the messae to be encoded
* \param[in] len, the length of the message
* \param[out] pDataOut, pointer to the encoded message
*
* \return The number of bytes added in the new buffer
*
********************************************************************************** */
#if gFsciUseEscapeSeq_c
uint32_t FSCI_encodeEscapeSeq( uint8_t* pDataIn, uint32_t len, uint8_t* pDataOut )
{
uint32_t index, new_index = 0;
if( NULL != pDataOut )
{
for ( index = 0; index < len; index++ )
{
if( (pDataIn[index] == gFSCI_StartMarker_c) ||
(pDataIn[index] == gFSCI_EndMarker_c) ||
(pDataIn[index] == gFSCI_EscapeChar_c) )
{
pDataOut[new_index++] = gFSCI_EscapeChar_c;
pDataOut[new_index++] = pDataIn[index] ^ gFSCI_EscapeChar_c;
}
else
{
pDataOut[new_index++] = pDataIn[index];
}
}
}
return new_index;
}
#endif
/*! *********************************************************************************
* \brief This function performs the decoding of a message, using the Escape Sequence
*
* \param[in] pData pointer to the messae to be encoded
* \param[in] len the length of the message
*
*
********************************************************************************** */
#if gFsciUseEscapeSeq_c
void FSCI_decodeEscapeSeq( uint8_t* pData, uint32_t len )
{
uint32_t index, new_index;
/* Find the first gFSCI_EscapeChar_c */
for ( index = 0; index < len; index++ )
if ( pData[index] == gFSCI_EscapeChar_c )
break;
new_index = index;
/* If a gFSCI_EscapeChar_c was found, decode the packet in place */
while ( index < len )
{
if ( pData[index] == gFSCI_EscapeChar_c )
{
index++; /* skip over the gFSCI_EscapeChar_c */
if ( index < len )
pData[new_index++] = pData[index++] ^ gFSCI_EscapeChar_c;
}
else if ( new_index != index )
{
pData[new_index++] = pData[index++];
}
}
}
#endif
#if gFsciRxAck_c && gFsciRxAckTimeoutUseTmr_c
/*! *********************************************************************************
* \brief This function is the callback of an Ack wait expire for a fsci interface
*
* \param[in] param fsci interface on which the Ack was expected
*
********************************************************************************** */
static void FSCI_RxAckExpireCb(void *param)
{
if( mFsciCommData[(uint32_t)param].txRetryCnt )
{
mFsciCommData[(uint32_t)param].txRetryCnt--;
}
/* Allow retransmission */
mFsciCommData[(uint32_t)param].ackWaitOngoing = FALSE;
}
#endif
#if gFsciRxTimeout_c && !mFsciRxTimeoutUsePolling_c
/*! *********************************************************************************
* \brief This function is the callback of an Rx timeout expired for a fsci interface
*
* \param[in] param fsci interface on which no bytes were received
*
********************************************************************************** */
static void FSCI_RxRxTimeoutCb(void *param)
{
mFsciCommData[(uint32_t)param].rxTmrExpired = TRUE;
}
#endif
/*! *********************************************************************************
* \brief This function is used to send a FSCI packet to the serial manager
*
* \param[in] fsciInterface fsci interface on which the packet is to be sent
* \param[in] pPacket serial packet to be sent
* \param[in] packetLen lenght of the serial packet in bytes
*
********************************************************************************** */
static void FSCI_SendPacketToSerialManager(uint32_t fsciInterface, uint8_t *pPacket, uint16_t packetLen)
{
#if gFsciRxAck_c
fsciComm_t *pCommData = &mFsciCommData[fsciInterface];
#if !gFsciRxAckTimeoutUseTmr_c
uint64_t ackWaitStartTs;
uint64_t currentTs;
#endif
#endif
#if gFsciRxAck_c
OSA_MutexLock(pCommData->syncTxRxAckMutexId, osaWaitForever_c);
pCommData->ackReceived = FALSE;
pCommData->txRetryCnt = mFsciTxRetryCnt_c;
while( pCommData->txRetryCnt )
{
Serial_SyncWrite(gFsciSerialInterfaces[fsciInterface], pPacket, packetLen);
pCommData->ackWaitOngoing = TRUE;
/* Allow the FSCI interface to receive ACK packet,
if last packet was received on the same interface */
if( mFsciSrcInterface == fsciInterface )
{
pCommData->pPacketFromClient = NULL;
}
#if gFsciRxAckTimeoutUseTmr_c
/* Start timer for ACK wait */
TMR_StartSingleShotTimer(pCommData->ackWaitTmr, mFsciRxAckTimeoutMs_c, FSCI_RxAckExpireCb, (void*)fsciInterface);
/* Wait for timer to expire or Ack to be received */
while( pCommData->ackWaitOngoing && !pCommData->ackReceived )
{
FSCI_receivePacket((void*)fsciInterface);
}
if( pCommData->ackReceived )
{
TMR_StopTimer(pCommData->ackWaitTmr);
pCommData->ackWaitOngoing = FALSE;
break;
}
#else
/* Get initial timestamp and poll until mFsciRxAckTimeoutMs_c has passed */
ackWaitStartTs = TMR_GetTimestamp();
while( !pCommData->ackReceived )
{
FSCI_receivePacket((void*)fsciInterface);
currentTs = TMR_GetTimestamp();
if( ((currentTs - ackWaitStartTs) / 1000) > mFsciRxAckTimeoutMs_c )
{
pCommData->ackWaitOngoing = FALSE;
if( pCommData->txRetryCnt )
{
pCommData->txRetryCnt--;
}
break; /* Timeout expired */
}
}
if( pCommData->ackReceived )
{
pCommData->ackWaitOngoing = FALSE;
break; /* Success */
}
#endif
}
MEM_BufferFree(pPacket);
OSA_MutexUnlock(pCommData->syncTxRxAckMutexId);
#else /* gFsciRxAck_c */
#if gFsciUseBlockingTx_c
if( gFsciTxBlocking )
{
Serial_SyncWrite(gFsciSerialInterfaces[fsciInterface], pPacket, packetLen);
MEM_BufferFree(pPacket);
}
else
#endif /* gFsciUseBlockingTx_c */
{
if(gSerial_Success_c != Serial_AsyncWrite( gFsciSerialInterfaces[fsciInterface], pPacket, packetLen, (pSerialCallBack_t)FSCI_txCallback, pPacket))
{
MEM_BufferFree(pPacket);
}
}
#endif /* gFsciRxAck_c */
}
#endif /* gFsciIncluded_c */
Comments
Please log in or sign up to comment.