2013年1月20日 星期日

[CC253x][Z-Stack] OSAL NV System - Item/data Length Limitation

    For some reasons, I have to store bulky data (slightly > 5kB, from ZigBee's aspect), receving from  remote, to NVRAM. In order to minimize the effort, I tried to leverage OSAL_NV API to speedup the work. The related API information can be found at "OS Abstraction Layer Application Programming Interface", SWRA194.pdf.

    By referencing other application using OSAL NV memory API, I added osal_nv_item_init() in my application initialization function. However, it returned NV_OPER_FAILED all the time. I traced the code and found that the error is due to written length limitation of OSAL NV system.


    CC2530 flash memory uses 2k page. Apparently OSAL NV doesn't manipulate data item cross page, i.e. item cannot be stored partially at page 1 and the rest at page 2. Thus, the maximum item size can be stored is 2048(byte) - 8(page header) - 8(item header) = 2032 bytes

Page header @ OSAL_nv.c

typedef struct
{
  uint16 active;
  uint16 inUse;
  uint16 xfer;
  uint16 spare;
} osalNvPgHdr_t;

Item header @ OSAL_nv.c

typedef struct
{
  uint16 id;
  uint16 len;   // Enforce Flash-WORD size on len.
  uint16 chk;   // Byte-wise checksum of the 'len' data bytes of the item.
  uint16 stat;  // Item status.
} osalNvHdr_t;



I am still thinking whether it's better to use OSAL NV API or writing customized helper functions to store my data > 2kB.






2013年1月7日 星期一

[ZigBee][CC2530] [Z-Stack][IAR] Generating Hex File Using Z-Stack for Release

    TI does provide comprehensive documents regarding its products, compared to many other chip vendors. However, too many documents without directory lead us lost ourselves.

    In Z-Stack Samples, we generate .d51 file under "EXE" directory by default. To generate hex file for mass production, I found there is useful introduction at How to configure the IAR EW 8051 to generate a hex file for CC2530 using Z-Stack? (plus link for CC2430/CC2431)



Step 1: Open the Z-stack workspace with IAR and locate the linker file f8w2530.xcl.
The f8w2530.xcl file can be found in the Tools file group in IAR.


  • To avoid change this file back and forth for debug and release, I copied it to the project folder and added to my release configuration (IAR->Project Option->Linker->Config Tab->Linker Configuration File, override default to the new .xcl)
  • at Output Tab of Linker, Click the “Override default” option in the “Output file” box and rename the xxx.a51 to xxx.hex 





Step 2: Include the linker file –M option by including the 3 lines as shown in the figure below.
// Include these two lines when generating a .hex file for banked code model:
-M(CODE)[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*\
_NR_OF_BANKS+_FIRST_BANK_ADDR=0x8000

For the rest steps you may follow "How to configure the IAR EW 8051 to generate a hex file for CC2530 using Z-Stack? (plus link for CC2430/CC2431)"


I was using


IAR Assembler for 8051
  8.10.3 (8.10.3.40338)

ZStack-2.5.1a

2013年1月4日 星期五

[ZigBee][CC2530] [Z-Stack] Combining SerialApp and TransmitApp - Multiple Endpoints in One ZigBee Device

    After playing around with Z-Stack samples, SerialApp and TransmitApp, I tried to combine these two sample applications to setup a template for my project.

    In the beginning, I thought it's an easy work which can be done within one or two days. However, it actually took me almost TWO WEEKS to work, because the original samples doesn't fit in multiple endpoints scheme.

    I used SerialApp as the basis and added TransmitApp (in fact, only TransmitApp.c and TransmitApp.h) in.

1. Follow "Create New Application For SmartRF05 + CC2530"(SWRA231) to create a new project based on SerialApp. In my case, the project name is OH6A.

2. Changes in  OSAL_OH6A.c are:

  • adding TransmitApp to the task array "tasksArr"


const pTaskEventHandlerFn tasksArr[] = {
  macEventLoop,
  nwk_event_loop,
  Hal_ProcessEvent,
#if defined( MT_TASK )
  MT_ProcessEvent,
#endif
  APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
  APSF_ProcessEvent,
#endif
  ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
  ZDNwkMgr_event_loop,
#endif
  SerialApp_ProcessEvent,
  TransmitApp_ProcessEvent
};



  • Invoking TransmitApp_Init() in the function "void osalInitTasks( void )"


3. I wish to use the same binding behavior as samples, thus, the key handlers has to be extend to accommodate multiple tasks

in onboard.c

  • change registeredKeysTaskID to uint8 array
uint8 registeredKeysTaskID[REGISTER_KEY_TASK_NUM_MAX];
  • modify RegisterForKeys() to allow multiple tasks to register to
uint8 RegisterForKeys( uint8 task_id )
{
char i;
for(i = 0; i < REGISTER_KEY_TASK_NUM_MAX; i++)
{
if(registeredKeysTaskID[i] == NO_TASK_ID)
{ registeredKeysTaskID[i] = task_id;
break;
}
}
if(i < REGISTER_KEY_TASK_NUM_MAX)
return (TRUE);
else
return (FALSE);
}
  • modify OnBoard_SendKeys to send the key press event to all registered tasks
uint8 OnBoard_SendKeys( uint8 keys, uint8 state )
{
        keyChange_t *msgPtr;

char i;
for(i = 0; (i < REGISTER_KEY_TASK_NUM_MAX) && (registeredKeysTaskID[i] != NO_TASK_ID); i++)
{
// Send the address to the task
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );
if ( msgPtr )
{
msgPtr->hdr.event = KEY_CHANGE;
msgPtr->state = state;
msgPtr->keys = keys;
osal_msg_send( registeredKeysTaskID[i], (uint8 *)msgPtr );
}
else
{
return ( ZFailure );
}
}
return ( ZSuccess );

}  

  • (OPTIONAL) I disabled SW2 (End_Device_Bind) in both SerialApp_HandleKeys()@SerialApp.c and TransmitApp_HandleKeys()@TransmitApp.c, since "One of the things I don’t like about this command is that if it returns success, the caller has no idea if the targets were bound or unbound. It’s a toggle!", quoted from Zigbee Wireless Networking, CH, Drew Gislason. (Don't know why "toggle" though but it's not the point in this experiment)
  • (OPTIONAL) compile option "RFD_RCVC_ALWAYS_ON=TRUE" is added to preprocessor.

    OK, it only took me a while to finish those steps above and I *THOUGHT* this experiment can be done by end of that day. It's NOT. TransmitApp seems working but apparently SerialApp doesn't.

    After spending many day and night debugging, I found that the root cause is when processing Match_Desc_rsp @SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )@SerialApp.c, the SerialApp_TxAddr.endPoint was assigned incorrect (actually, overwritten by the  endpoint of TransmitApp).

    In SerialApp_Init( uint8 task_id )Match_Desc_rsp event was registered by   ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp ). However, the callback/dispatch function,   handled = ZDO_SendMsgCBs( &inMsg )@ZDProfile.c is blindly dispatch ALL Match_Desc_rsp message to ALL registered task. Z-Stack should have dealt with matching Match_Desc_req with corresponding Match_desc_rsp, before sending back to registered task.

4. To quickly fix this problem (not graceful, but I don't want to modify Z-Stack anyway), in both SerialApp.c and TransmitApp.c, I tried to keep track of APS "Transaction sequence number" when sending Match_Desc_req and check the stored data when receiving Match_Desc_rsp. Fortunately OSAL is not preemptive so it can work.

Take TransmitApp as example, in TransmitApp.c:


  • adding global "byte TransmitApp_ZDP_TransID;" to store TransID
  • in function TransmitApp_HandleKeys(), saving global variable ZDP_TransID which is used by 


      HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
      // Initiate a Match Description Request (Service Discovery)
      dstAddr.addrMode = AddrBroadcast;
      dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
      TransmitApp_ZDP_TransID = ZDP_TransID;      ZDP_MatchDescReq( &dstAddr, NWK_BROADCAST_SHORTADDR,
                        TRANSMITAPP_PROFID,
                        TRANSMITAPP_MAX_CLUSTERS, (cId_t *)TransmitApp_ClusterList,
                        TRANSMITAPP_MAX_CLUSTERS, (cId_t *)TransmitApp_ClusterList,
                        FALSE );


  • in function TransmitApp_ProcessZDOMsgs(), checking the TransSeq within incoming msg with the stored TransID.
    case Match_Desc_rsp:
      {
        ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
        if ( pRsp )
        {

 if(TransmitApp_ZDP_TransID == inMsg->TransSeq)
          if ( pRsp->status == ZSuccess && pRsp->cnt )
          {
            TransmitApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
            TransmitApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
            // Take the first endpoint, Can be changed to search through endpoints
            TransmitApp_DstAddr.endPoint = pRsp->epList[0];
            // Light LED
            HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
          }
          osal_mem_free( pRsp );
        }
      }
      break;


After those change, I can finally get two endpoints work on the same ZigBee device, based on IT's Z-stack.









2012年12月9日 星期日

[ZigBee][CC2530] SerialApp Smple Application - Bidirectional!

Z-Stack Sample Applications are useful examples which we can verify the EDK and learn Z-Stack software.

SerialApp is a sample application which enables two CC2530EM to act as serial cable (RS-232) so we can use hyper terminals on two computers to interact with each other over the air.

However, the guide document, Z-Stack Sample Applications.pdf(SWRA201), is not clear so I found that the communication is one way, instead of bi-directional. Few guys had the same problem and posted it to E2E forum. The symptom is that the data only gets transferred from ZED to ZC, but not reversely.

To make bidirectional transmission,


you have to Push SW4 at ZED and then SW4 at ZC
OR, you have to Push SW2 at ZC and then SW2 at ZED

quote from Zigbee Wireless Networking, "Binding is unidirectional, in that the switch is bound to the light, but the light isn’t bound to the switch"

The suggestion was also posted in this thread - Bidirectional communication in Serialapp,

2012年12月3日 星期一

[Zigbee][CC2531] make USB firmware with IAR

In order to change CC2531 USB dongle to USB CDC device, I downloaded swrc088c.zip (The Texas Instruments LPRF USB Firmware Library (Rev. B) ) and tried to make a CDC firmware of it.

the first problem I met is that the IAR project file (\ide\rfusb_cc2531\iar\rf_modem.eww) was made by  older IAR version so my IAR (8.10.3) asked me to convert it to this version. After doing so, the make operation still didn't go through because of [ Error[e12]: Unable to open file 'lnk51ew_cc2531b.xcl' ].

After quick searching at e2e, the thread IAR 7.6 linker error did provide solution of it.


-Right click on the top level project file in the 'Workspace' window
-Select 'Options'
-From the 'Category' box on the left, select 'Linker'
-Select the 'Config' tab
-In the 'Linker command file' box, make sure 'Override defaults' is checked
-Choose the proper linker file


in my case, the file is IAR Systems\Embedded Workbench 6.0\8051\config\devices\Texas Instruments\lnk51ew_cc2531F256.xcl

After reboot the dongle and installing the device driver (swrc088c\driver\usb_cdc_driver_cc2511.inf), the CC2531 CDC was successfully running.