SerialApp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. /**************************************************************************************************
  2. Filename: SerialApp.c
  3. Revised: $Date: 2009-03-29 10:51:47 -0700 (Sun, 29 Mar 2009) $
  4. Revision: $Revision: 19585 $
  5. Description - Serial Transfer Application (no Profile).
  6. Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /*********************************************************************
  34. This sample application is basically a cable replacement
  35. and it should be customized for your application. A PC
  36. (or other device) sends data via the serial port to this
  37. application's device. This device transmits the message
  38. to another device with the same application running. The
  39. other device receives the over-the-air message and sends
  40. it to a PC (or other device) connected to its serial port.
  41. This application doesn't have a profile, so it handles everything directly.
  42. Key control:
  43. SW1:
  44. SW2: initiates end device binding
  45. SW3:
  46. SW4: initiates a match description request
  47. *********************************************************************/
  48. /*********************************************************************
  49. * INCLUDES
  50. */
  51. #include "AF.h"
  52. #include "OnBoard.h"
  53. #include "OSAL_Tasks.h"
  54. #include "SerialApp.h"
  55. #include "ZDApp.h"
  56. #include "ZDObject.h"
  57. #include "ZDProfile.h"
  58. #include "hal_drivers.h"
  59. #include "hal_key.h"
  60. #if defined ( LCD_SUPPORTED )
  61. #include "hal_lcd.h"
  62. #endif
  63. #include "hal_led.h"
  64. #include "hal_uart.h"
  65. /*********************************************************************
  66. * MACROS
  67. */
  68. /*********************************************************************
  69. * CONSTANTS
  70. */
  71. #if !defined( SERIAL_APP_PORT )
  72. #define SERIAL_APP_PORT 0
  73. #endif
  74. #if !defined( SERIAL_APP_BAUD )
  75. #define SERIAL_APP_BAUD HAL_UART_BR_38400
  76. //#define SERIAL_APP_BAUD HAL_UART_BR_115200
  77. #endif
  78. // When the Rx buf space is less than this threshold, invoke the Rx callback.
  79. #if !defined( SERIAL_APP_THRESH )
  80. #define SERIAL_APP_THRESH 64
  81. #endif
  82. #if !defined( SERIAL_APP_RX_SZ )
  83. #define SERIAL_APP_RX_SZ 128
  84. #endif
  85. #if !defined( SERIAL_APP_TX_SZ )
  86. #define SERIAL_APP_TX_SZ 128
  87. #endif
  88. // Millisecs of idle time after a byte is received before invoking Rx callback.
  89. #if !defined( SERIAL_APP_IDLE )
  90. #define SERIAL_APP_IDLE 6
  91. #endif
  92. // Loopback Rx bytes to Tx for throughput testing.
  93. #if !defined( SERIAL_APP_LOOPBACK )
  94. #define SERIAL_APP_LOOPBACK FALSE
  95. #endif
  96. // This is the max byte count per OTA message.
  97. #if !defined( SERIAL_APP_TX_MAX )
  98. #define SERIAL_APP_TX_MAX 80
  99. #endif
  100. #define SERIAL_APP_RSP_CNT 4
  101. // This list should be filled with Application specific Cluster IDs.
  102. const cId_t SerialApp_ClusterList[SERIALAPP_MAX_CLUSTERS] =
  103. {
  104. SERIALAPP_CLUSTERID1,
  105. SERIALAPP_CLUSTERID2
  106. };
  107. const SimpleDescriptionFormat_t SerialApp_SimpleDesc =
  108. {
  109. SERIALAPP_ENDPOINT, // int Endpoint;
  110. SERIALAPP_PROFID, // uint16 AppProfId[2];
  111. SERIALAPP_DEVICEID, // uint16 AppDeviceId[2];
  112. SERIALAPP_DEVICE_VERSION, // int AppDevVer:4;
  113. SERIALAPP_FLAGS, // int AppFlags:4;
  114. SERIALAPP_MAX_CLUSTERS, // byte AppNumInClusters;
  115. (cId_t *)SerialApp_ClusterList, // byte *pAppInClusterList;
  116. SERIALAPP_MAX_CLUSTERS, // byte AppNumOutClusters;
  117. (cId_t *)SerialApp_ClusterList // byte *pAppOutClusterList;
  118. };
  119. const endPointDesc_t SerialApp_epDesc =
  120. {
  121. SERIALAPP_ENDPOINT,
  122. &SerialApp_TaskID,
  123. (SimpleDescriptionFormat_t *)&SerialApp_SimpleDesc,
  124. noLatencyReqs
  125. };
  126. /*********************************************************************
  127. * TYPEDEFS
  128. */
  129. /*********************************************************************
  130. * GLOBAL VARIABLES
  131. */
  132. uint8 SerialApp_TaskID; // Task ID for internal task/event processing.
  133. /*********************************************************************
  134. * EXTERNAL VARIABLES
  135. */
  136. /*********************************************************************
  137. * EXTERNAL FUNCTIONS
  138. */
  139. /*********************************************************************
  140. * LOCAL VARIABLES
  141. */
  142. static uint8 SerialApp_MsgID;
  143. static afAddrType_t SerialApp_TxAddr;
  144. static uint8 SerialApp_TxSeq;
  145. static uint8 SerialApp_TxBuf[SERIAL_APP_TX_MAX+1];
  146. static uint8 SerialApp_TxLen;
  147. static afAddrType_t SerialApp_RxAddr;
  148. static uint8 SerialApp_RxSeq;
  149. static uint8 SerialApp_RspBuf[SERIAL_APP_RSP_CNT];
  150. /*********************************************************************
  151. * LOCAL FUNCTIONS
  152. */
  153. static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
  154. static void SerialApp_HandleKeys( uint8 shift, uint8 keys );
  155. static void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt );
  156. static void SerialApp_Send(void);
  157. static void SerialApp_Resp(void);
  158. static void SerialApp_CallBack(uint8 port, uint8 event);
  159. /*********************************************************************
  160. * @fn SerialApp_Init
  161. *
  162. * @brief This is called during OSAL tasks' initialization.
  163. *
  164. * @param task_id - the Task ID assigned by OSAL.
  165. *
  166. * @return none
  167. */
  168. void SerialApp_Init( uint8 task_id )
  169. {
  170. halUARTCfg_t uartConfig;
  171. SerialApp_TaskID = task_id;
  172. SerialApp_RxSeq = 0xC3;
  173. afRegister( (endPointDesc_t *)&SerialApp_epDesc );
  174. RegisterForKeys( task_id );
  175. uartConfig.configured = TRUE; // 2x30 don't care - see uart driver.
  176. uartConfig.baudRate = SERIAL_APP_BAUD;
  177. uartConfig.flowControl = TRUE;
  178. uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver.
  179. uartConfig.rx.maxBufSize = SERIAL_APP_RX_SZ; // 2x30 don't care - see uart driver.
  180. uartConfig.tx.maxBufSize = SERIAL_APP_TX_SZ; // 2x30 don't care - see uart driver.
  181. uartConfig.idleTimeout = SERIAL_APP_IDLE; // 2x30 don't care - see uart driver.
  182. uartConfig.intEnable = TRUE; // 2x30 don't care - see uart driver.
  183. uartConfig.callBackFunc = SerialApp_CallBack;
  184. HalUARTOpen (SERIAL_APP_PORT, &uartConfig);
  185. #if defined ( LCD_SUPPORTED )
  186. HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );
  187. #endif
  188. ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );
  189. ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );
  190. }
  191. /*********************************************************************
  192. * @fn SerialApp_ProcessEvent
  193. *
  194. * @brief Generic Application Task event processor.
  195. *
  196. * @param task_id - The OSAL assigned task ID.
  197. * @param events - Bit map of events to process.
  198. *
  199. * @return Event flags of all unprocessed events.
  200. */
  201. UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
  202. {
  203. (void)task_id; // Intentionally unreferenced parameter
  204. if ( events & SYS_EVENT_MSG )
  205. {
  206. afIncomingMSGPacket_t *MSGpkt;
  207. while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SerialApp_TaskID )) )
  208. {
  209. switch ( MSGpkt->hdr.event )
  210. {
  211. case ZDO_CB_MSG:
  212. SerialApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
  213. break;
  214. case KEY_CHANGE:
  215. SerialApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
  216. break;
  217. case AF_INCOMING_MSG_CMD:
  218. SerialApp_ProcessMSGCmd( MSGpkt );
  219. break;
  220. default:
  221. break;
  222. }
  223. osal_msg_deallocate( (uint8 *)MSGpkt );
  224. }
  225. return ( events ^ SYS_EVENT_MSG );
  226. }
  227. if ( events & SERIALAPP_SEND_EVT )
  228. {
  229. SerialApp_Send();
  230. return ( events ^ SERIALAPP_SEND_EVT );
  231. }
  232. if ( events & SERIALAPP_RESP_EVT )
  233. {
  234. SerialApp_Resp();
  235. return ( events ^ SERIALAPP_RESP_EVT );
  236. }
  237. return ( 0 ); // Discard unknown events.
  238. }
  239. /*********************************************************************
  240. * @fn SerialApp_ProcessZDOMsgs()
  241. *
  242. * @brief Process response messages
  243. *
  244. * @param none
  245. *
  246. * @return none
  247. */
  248. static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
  249. {
  250. switch ( inMsg->clusterID )
  251. {
  252. case End_Device_Bind_rsp:
  253. if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
  254. {
  255. // Light LED
  256. HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
  257. }
  258. #if defined(BLINK_LEDS)
  259. else
  260. {
  261. // Flash LED to show failure
  262. HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
  263. }
  264. #endif
  265. break;
  266. case Match_Desc_rsp:
  267. {
  268. ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
  269. if ( pRsp )
  270. {
  271. if ( pRsp->status == ZSuccess && pRsp->cnt )
  272. {
  273. SerialApp_TxAddr.addrMode = (afAddrMode_t)Addr16Bit;
  274. SerialApp_TxAddr.addr.shortAddr = pRsp->nwkAddr;
  275. // Take the first endpoint, Can be changed to search through endpoints
  276. SerialApp_TxAddr.endPoint = pRsp->epList[0];
  277. // Light LED
  278. HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
  279. }
  280. osal_mem_free( pRsp );
  281. }
  282. }
  283. break;
  284. }
  285. }
  286. /*********************************************************************
  287. * @fn SerialApp_HandleKeys
  288. *
  289. * @brief Handles all key events for this device.
  290. *
  291. * @param shift - true if in shift/alt.
  292. * @param keys - bit field for key events.
  293. *
  294. * @return none
  295. */
  296. void SerialApp_HandleKeys( uint8 shift, uint8 keys )
  297. {
  298. zAddrType_t txAddr;
  299. if ( shift )
  300. {
  301. if ( keys & HAL_KEY_SW_1 )
  302. {
  303. }
  304. if ( keys & HAL_KEY_SW_2 )
  305. {
  306. }
  307. if ( keys & HAL_KEY_SW_3 )
  308. {
  309. }
  310. if ( keys & HAL_KEY_SW_4 )
  311. {
  312. }
  313. }
  314. else
  315. {
  316. if ( keys & HAL_KEY_SW_1 )
  317. {
  318. }
  319. if ( keys & HAL_KEY_SW_2 )
  320. {
  321. HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
  322. // Initiate an End Device Bind Request for the mandatory endpoint
  323. txAddr.addrMode = Addr16Bit;
  324. txAddr.addr.shortAddr = 0x0000; // Coordinator
  325. ZDP_EndDeviceBindReq( &txAddr, NLME_GetShortAddr(),
  326. SerialApp_epDesc.endPoint,
  327. SERIALAPP_PROFID,
  328. SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
  329. SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
  330. FALSE );
  331. }
  332. if ( keys & HAL_KEY_SW_3 )
  333. {
  334. }
  335. if ( keys & HAL_KEY_SW_4 )
  336. {
  337. HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
  338. // Initiate a Match Description Request (Service Discovery)
  339. txAddr.addrMode = AddrBroadcast;
  340. txAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
  341. ZDP_MatchDescReq( &txAddr, NWK_BROADCAST_SHORTADDR,
  342. SERIALAPP_PROFID,
  343. SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
  344. SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
  345. FALSE );
  346. }
  347. }
  348. }
  349. /*********************************************************************
  350. * @fn SerialApp_ProcessMSGCmd
  351. *
  352. * @brief Data message processor callback. This function processes
  353. * any incoming data - probably from other devices. Based
  354. * on the cluster ID, perform the intended action.
  355. *
  356. * @param pkt - pointer to the incoming message packet
  357. *
  358. * @return TRUE if the 'pkt' parameter is being used and will be freed later,
  359. * FALSE otherwise.
  360. */
  361. void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
  362. {
  363. uint8 stat;
  364. uint8 seqnb;
  365. uint8 delay;
  366. switch ( pkt->clusterId )
  367. {
  368. // A message with a serial data block to be transmitted on the serial port.
  369. case SERIALAPP_CLUSTERID1:
  370. // Store the address for sending and retrying.
  371. osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
  372. seqnb = pkt->cmd.Data[0];
  373. // Keep message if not a repeat packet
  374. if ( (seqnb > SerialApp_RxSeq) || // Normal
  375. ((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
  376. {
  377. // Transmit the data on the serial port.
  378. if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
  379. {
  380. // Save for next incoming message
  381. SerialApp_RxSeq = seqnb;
  382. stat = OTA_SUCCESS;
  383. }
  384. else
  385. {
  386. stat = OTA_SER_BUSY;
  387. }
  388. }
  389. else
  390. {
  391. stat = OTA_DUP_MSG;
  392. }
  393. // Select approproiate OTA flow-control delay.
  394. delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;
  395. // Build & send OTA response message.
  396. SerialApp_RspBuf[0] = stat;
  397. SerialApp_RspBuf[1] = seqnb;
  398. SerialApp_RspBuf[2] = LO_UINT16( delay );
  399. SerialApp_RspBuf[3] = HI_UINT16( delay );
  400. osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT );
  401. osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
  402. break;
  403. // A response to a received serial data block.
  404. case SERIALAPP_CLUSTERID2:
  405. if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&
  406. ((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG)))
  407. {
  408. SerialApp_TxLen = 0;
  409. osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  410. }
  411. else
  412. {
  413. // Re-start timeout according to delay sent from other device.
  414. delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
  415. osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay );
  416. }
  417. break;
  418. default:
  419. break;
  420. }
  421. }
  422. /*********************************************************************
  423. * @fn SerialApp_Send
  424. *
  425. * @brief Send data OTA.
  426. *
  427. * @param none
  428. *
  429. * @return none
  430. */
  431. static void SerialApp_Send(void)
  432. {
  433. #if SERIAL_APP_LOOPBACK
  434. if (SerialApp_TxLen < SERIAL_APP_TX_MAX)
  435. {
  436. SerialApp_TxLen += HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+SerialApp_TxLen+1,
  437. SERIAL_APP_TX_MAX-SerialApp_TxLen);
  438. }
  439. if (SerialApp_TxLen)
  440. {
  441. (void)SerialApp_TxAddr;
  442. if (HalUARTWrite(SERIAL_APP_PORT, SerialApp_TxBuf+1, SerialApp_TxLen))
  443. {
  444. SerialApp_TxLen = 0;
  445. }
  446. else
  447. {
  448. osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  449. }
  450. }
  451. #else
  452. if (!SerialApp_TxLen &&
  453. (SerialApp_TxLen = HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+1, SERIAL_APP_TX_MAX)))
  454. {
  455. // Pre-pend sequence number to the Tx message.
  456. SerialApp_TxBuf[0] = ++SerialApp_TxSeq;
  457. }
  458. if (SerialApp_TxLen)
  459. {
  460. if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_TxAddr,
  461. (endPointDesc_t *)&SerialApp_epDesc,
  462. SERIALAPP_CLUSTERID1,
  463. SerialApp_TxLen+1, SerialApp_TxBuf,
  464. &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
  465. {
  466. osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  467. }
  468. }
  469. #endif
  470. }
  471. /*********************************************************************
  472. * @fn SerialApp_Resp
  473. *
  474. * @brief Send data OTA.
  475. *
  476. * @param none
  477. *
  478. * @return none
  479. */
  480. static void SerialApp_Resp(void)
  481. {
  482. if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_RxAddr,
  483. (endPointDesc_t *)&SerialApp_epDesc,
  484. SERIALAPP_CLUSTERID2,
  485. SERIAL_APP_RSP_CNT, SerialApp_RspBuf,
  486. &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
  487. {
  488. osal_set_event(SerialApp_TaskID, SERIALAPP_RESP_EVT);
  489. }
  490. }
  491. /*********************************************************************
  492. * @fn SerialApp_CallBack
  493. *
  494. * @brief Send data OTA.
  495. *
  496. * @param port - UART port.
  497. * @param event - the UART port event flag.
  498. *
  499. * @return none
  500. */
  501. static void SerialApp_CallBack(uint8 port, uint8 event)
  502. {
  503. (void)port;
  504. if ((event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) &&
  505. #if SERIAL_APP_LOOPBACK
  506. (SerialApp_TxLen < SERIAL_APP_TX_MAX))
  507. #else
  508. !SerialApp_TxLen)
  509. #endif
  510. {
  511. SerialApp_Send();
  512. }
  513. }
  514. /*********************************************************************
  515. *********************************************************************/