The MCR20A Wireless UART application functions as an wireless UART bridge between two (one-to-one) or several (one to many) boards. The application can be used with both a TERM, or with software that is capable of opening a serial port and writing to or reading from it. The characters sent or received are not necessarily ASCII printable characters.

Dependencies:   fsl_phy_mcr20a fsl_smac mbed-rtos mbed

Fork of mcr20_wireless_uart by Freescale

By default, the application uses broadcast addresses for OTA communication. This way, the application can be directly downloaded and run without any user intervention. The following use case assumes no changes have been done to the project.

  • Two (or more) MCR20A platforms (plugged into the FRDM-K64F Freescale Freedom Development platform) have to be connected to the PC using the mini/micro-USB cables.
  • The code must be downloaded on the platforms via CMSIS-DAP (or other means).
  • After that, two or more TERM applications must be opened, and the serial ports must be configured with the same baud rate as the one in the project (default baud rate is 115200). Other necessary serial configurations are 8 bit, no parity, and 1 stop bit.
  • To start the setup, each platform must be reset, and one of the (user) push buttons found on the MCR20A platform must be pressed. The user can press any of the non-reset buttons on the FRDM-K64F Freescale Freedom Development platform as well. *This initiates the state machine of the application so user can start.

Documentation

SMAC Demo Applications User Guide

main.cpp

Committer:
FSL\B36402
Date:
2015-03-15
Revision:
15:990a8b5664e1
Parent:
3:a38ad504a18c
Child:
17:52cfd7db8da3

File content as of revision 15:990a8b5664e1:

#include "mbed.h"

#include "driverDebug.h"
#include "socket_api.h"
#include "net_interface.h"
#include "system_event.h"
#include "string.h"
#include "net_nwk_scan.h"
#include "socket_security.h"
#include "nwk_stats_api.h"
#include "multicast_api.h"
#include "nsdynmemLIB.h"
#include "randLIB.h"
#include "arm_hal_timer.h"
#include "common_functions.h"
#include "driverRFPhy.h"
#include "driverAtmelRFInterface.h"
#include "nsdl_support.h"
#include "node_cfg.h"

/*** DEBUG ******/
#define DEBUG       1
#if DEBUG
#define debug   printf
#else
#define debug(...)  ""
#endif  // DEBUG

/*******  Hardware Definition  **********/
#if NODE_CONTROLLER
  DigitalOut ledR(PTB22);      // RGB - Red LED
  DigitalOut ledG(PTE26);      // RGB - Green LED
  DigitalOut ledB(PTB21);      // RGB - Blue LED    
  InterruptIn TAP_INT(PTC6);  // INT1 from FXOS8700Q
#endif

/*******  Timers Definitions   ************/
#define RETRY_TIMER             1
#define NSP_REGISTRATION_TIMER  2
#if NODE_CONTROLLER 
  #define ACCELEROMETER_TIMER    3
#endif
#if NODE_HOME
  #define DOOR_CHECK_TIMER        4
#endif

void app_heap_error_handler(heap_fail_t event);
void tasklet_main(arm_event_s *event);
void button_main(arm_event_s *event);

#define APP_DEV_HEAP_SIZE 6000
static uint8_t app_defined_stack_heap[APP_DEV_HEAP_SIZE];
static int8_t main_tasklet_id = -1;

static const uint8_t app_MAC_address[8] = NODE_MAC_ADDRESS;
static int8_t rf_phy_device_register_id = -1;
static int8_t net_6lowpan_id = -1;
static uint32_t channel_list = 0x07FFF800; // All channels

int8_t coap_udp_socket = -1;

#define AUDP_SOCKET_PORT     61630
#define RECV_CTRL_UDP_PORT   1050    // receive
#define SEND_CTRL_UDP_PORT   1060    // send

/** Used for Receive Data source Address store*/
static ns_address_t app_src;
static sn_nsdl_addr_s sn_addr_s;

static int access_point_status = 0;

link_layer_setups_s app_link_info;
link_layer_address_s app_link_address_info;
network_layer_address_s app_nd_address_info;

/* Prototype functions  */
void NSDL_receive_socket(void *cb);
void NSP_registration(void);

extern void create_lqi_resource(uint8_t);
void* own_alloc(uint16_t size);
void own_free(void *ptr);

/***************  Application variables  ***********************/
uint8_t batteryLevel = 100;
enum LED {NONE, RED, GREEN, BLUE};
int ledState = NONE;


/* #defines, definitions and declarations according node profile  */

#if NODE_CONTROLLER
int8_t ctrl_udp_socket = -1;
void empty_udp_receive(void * cb);
void ctrl_udp_send(uint8_t cmd);

#include "FXOS8700Q_TD.h"

#define ACCEL_SAMPLE_TIME   200
FXOS8700Q accel( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); // Proper Ports and I2C Address for K64F Freedom board
bool accel_enable = 1;
   
void tap_detector_handler(void) {
   printf("Tap Detected!\r\n"); 
   
   switch(ledState) {
     case NONE:
        break;
     case RED: 
        ctrl_udp_send('R');   
        break;
     case GREEN:
        ctrl_udp_send('G');
        break;
     case BLUE:
        ctrl_udp_send('B');
        break;            
    }
}

void update_LED(void) {
  
  switch(ledState) {
    case NONE:
      ledState = GREEN;
      ledR = 1;
      ledG = 0;
      ledB = 1;
      break;
      
    case GREEN:
      ledState = RED;
      ledR = 0;
      ledG = 1;
      ledB = 1;
      break;
      
    case RED:
      ledState = BLUE;
      ledR = 1;
      ledG = 1;
      ledB = 0; 
      break;

    case BLUE:
      ledState = NONE;
      ledR = 1;
      ledG = 1;
      ledB = 1;
      break;                
  }       
}

#endif

#if 1
void printf_array(uint8_t *ptr , uint16_t len)
{
    uint16_t i;
    for(i=0; i<len; i++)
    {
        if(i)
        {
            if(i%16== 0)
            {
                debug("\r\n");
                if(len > 64)
                {
                    uint8_t x =254;
                    while(x--);
                }
            }
            else
            {
                debug(":");
            }
        }
        debug_hex(*ptr++);
    }
    debug("\r\n");
}



void debug_integer(uint8_t width, uint8_t base, int16_t n)
{
  uint8_t bfr[8];
  uint8_t *ptr = bfr;
  uint8_t ctr = 0;

  if (width > 7) width = 7;

  ptr += width;
  *ptr-- = 0;

  if (base == 16)
  {
      do
      {
          *ptr = n & 0x0F;
          if (*ptr < 10) *ptr += '0';
          else *ptr += ('A'-10);
          ptr--;
          n >>= 4;
          ctr++;
      }while((ctr & 1) || (ctr < width));
  }
  else
  {
      uint8_t negative = 0;
      if (n < 0)
      { negative = 1;
        n = -n;
      }
      ctr++;
      do
      {
        *ptr-- = (n % 10) + '0';
        n /= 10;
        ctr++;
      }while ((ctr < width) && n);
      if (negative)
      {
        *ptr-- = '-';
      }
      else
      {
        *ptr-- = ' ';
      }
  }
  ptr++;
  //debug_send(ptr);
    debug((const char *)ptr);
}


void printf_ipv6_address(uint8_t *addr_ptr)
{
    if(addr_ptr)
    {
        uint8_t i, d_colon = 0;
        uint16_t current_value = 0, last_value = 0;

        for(i=0; i< 16;i += 2)
        {
            current_value =  (*addr_ptr++ << 8);
            current_value += *addr_ptr++;

            if(i == 0)
            {
                last_value = current_value;
                debug_hex(current_value >> 8);
                debug_hex(current_value );
                debug(":");
            }
            else
            {
                if(current_value == 0)
                {
                    if(i== 14)
                    {
                        debug(":");
                        //debug_put('0');
                        debug("0");
                    }
                    else
                    {
                        if(last_value == 0)
                        {
                            if(d_colon == 0)
                            {
                                d_colon=1;
                            }
                        }
                        else
                        {
                            if(d_colon == 2)
                            {
                                //debug_put('0');
                                debug("0");
                                debug(":");
                            }
                        }
                    }
                }
                else
                {
                    if(last_value == 0)
                    {
                        if(d_colon == 1)
                        {
                            debug(":");
                            d_colon = 2;
                        }
                        else
                        {
                            //debug_put('0');
                            debug("0");
                            debug(":");
                        }
                    }
                    if(current_value > 0x00ff)
                    {
                        debug_hex(current_value >> 8);
                    }
                    debug_hex(current_value );
                    if(i< 14)
                    {
                        debug(":");
                    }
                }
                last_value = current_value;
            }
        }
    }
    else
    {
        debug("Address Print: pointer NULL");
    }
    debug("\r\n");
}
#endif

int main()
{
#if NODE_CONTROLLER      
  ledR = 1;
  ledG = 1;
  ledB = 1;
  TAP_INT.rise(&tap_detector_handler); 
#endif
 
  debug("\r\nApplication Start\r\n");
  ns_dyn_mem_init(app_defined_stack_heap, APP_DEV_HEAP_SIZE, app_heap_error_handler,0);
  rf_set_mac_address(app_MAC_address);
 
  // init RF interface
  debug("Init RF Interface...\r\n");
  rf_phy_device_register_id = rf_device_register();

  randLIB_seed_random();
    
  debug("Init ARM Timer...\r\n");
  arm_timer_init();//Init Timer
  
  //Init nanostack & Event OS
  debug("Init Net Core...\r\n");
  net_init_core();
  debug("Create Tasklets...\r\n");
  main_tasklet_id = arm_ns_tasklet_create(&tasklet_main);
  if(main_tasklet_id < 0)
  {
    //Tasklet cerate fail
    error("Tasklet create fail.."); 
    while(1); 
  }
  
  debug("Event Dispatch\r\n");
  event_dispatch();
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}
void app_heap_error_handler(heap_fail_t event)
{
    switch (event)
    {
        case NS_DYN_MEM_NULL_FREE:
            break;
        case NS_DYN_MEM_DOUBLE_FREE:
            break;

        case NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID:
            break;
        case NS_DYN_MEM_POINTER_NOT_VALID:
            break;

        case NS_DYN_MEM_HEAP_SECTOR_CORRUPTED:
            break;

        case NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED:
            break;
                
        default:

            break;
    }
    while(1);
}


/**
  * \brief Network state event handler.
  * \param event show network start response or current network state.
  *
  * - NET_READY: Save NVK peristant data to NVM and Net role
  * - NET_NO_BEACON: Link Layer Active Scan Fail, Stack is Already at Idle state
  * - NET_NO_ND_ROUTER: No ND Router at current Channel Stack is Already at Idle state
  * - NET_BORDER_ROUTER_LOST: Connection to Access point is lost wait for Scan Result
  * - NET_PARENT_POLL_FAIL: Host should run net start without any PAN-id filter and all channels
  * - NET_PANA_SERVER_AUTH_FAIL: Pana Authentication fail, Stack is Already at Idle state
  */
void app_parse_network_event(arm_event_s *event )
{
  arm_nwk_interface_status_type_e status = (arm_nwk_interface_status_type_e)event->event_data;
  switch (status)
  {
    case ARM_NWK_BOOTSTRAP_READY:
      /* NEtwork is ready and node is connected to Access Point */
      if(access_point_status==0)
      {
        uint8_t temp_ipv6[16];
        debug("Network Connection Ready\r\n");
        access_point_status=1;
        //Read Address

        if( arm_nwk_nd_address_read(net_6lowpan_id,&app_nd_address_info) != 0)
        {
          debug("ND Address read fail\r\n");
        }
        else
        {
          debug("ND Access Point: ");
          printf_ipv6_address(app_nd_address_info.border_router); //REVIEW

          debug("ND Prefix 64: ");
          printf_array(app_nd_address_info.prefix, 8);            //REVIEW

          if(arm_net_address_get(net_6lowpan_id,ADDR_IPV6_GP,temp_ipv6) == 0)
          {
            debug("GP IPv6: ");
            printf_ipv6_address(temp_ipv6);         //REVIEW
          }
        }

        if( arm_nwk_mac_address_read(net_6lowpan_id,&app_link_address_info) != 0)
        {
          debug("MAC Address read fail\r\n");
        }
        else
        {
          uint8_t temp[2];
          common_write_16_bit(app_link_address_info.mac_short,temp);
          debug("MAC 16-bit: ");
          printf_array(temp, 2);  //REVIEW
          common_write_16_bit(app_link_address_info.PANId,temp);
          debug("PAN-ID: ");
          printf_array(temp, 2);  //REVIEW
          debug("MAC 64-bit: ");
          printf_array(app_link_address_info.long_euid64, 8); //REVIEW
          debug("EUID64(Based on MAC 64-bit address): ");
          printf_array(app_link_address_info.euid64, 8);  //REVIEW
        }
      }
      break;
    
    case ARM_NWK_NWK_SCAN_FAIL:
      /* Link Layer Active Scan Fail, Stack is Already at Idle state */
      debug("Link Layer Scan Fail: No Beacons\r\n");
      access_point_status=0;
      //dnssd_disable(1);
      break;
    
    case ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL:
      /* No ND Router at current Channel Stack is Already at Idle state */
      debug("ND Scan/ GP REG fail\r\n");
      access_point_status=0;
      //dnssd_disable(1);
      break;
    
    case ARM_NWK_NWK_CONNECTION_DOWN:
      /* Connection to Access point is lost wait for Scan Result */
      debug("ND/RPL scan new network\r\n");
      access_point_status=0;
      break;

    case ARM_NWK_NWK_PARENT_POLL_FAIL:
      access_point_status=0;
      break;
    
    case ARM_NWK_AUHTENTICATION_FAIL:
      debug("Network authentication fail\r\n");
      access_point_status=0;
      break;
    
    default:
      debug_hex(status);    //REVIEW
      debug("Unknow event");
      break;
  }
  
  if(access_point_status == 0)
  {
    //Set Timer for new Trig
    timer_sys_event(RETRY_TIMER, 10000);
  }
}


/**
  * \brief Handler for events sent to the application.
  * \param event received event.
  *
  * - EV_NETWORK event, Network Event state event handler
  * - EV_INIT, Set Certificate Chain list, init multicast, Start net start if NVM have session
  * - EV_DEBUG, Terminal handler
  */
void tasklet_main(arm_event_s *event)
{
  if(event->sender == 0)
  {
    arm_library_event_type_e event_type;
    event_type = (arm_library_event_type_e)event->event_type;

    switch(event_type)
    {
      case ARM_LIB_NWK_INTERFACE_EVENT:
        /* Network Event state event handler */
        debug("Event: ARM_LIB_NWK_INTERFACE\r\n");
        app_parse_network_event(event);                  
        break;

      case ARM_LIB_TASKLET_INIT_EVENT:
        /*Init event from stack at start-up*/
        debug("Event: ARM_LIB_TASKLET_INIT\r\n");
#if NODE_CONTROLLER  
        timer_sys_event(ACCELEROMETER_TIMER, ACCEL_SAMPLE_TIME);
#endif  
        multicast_set_parameters(10,0,20,3,75 );

#if NODE_CONTROLLER
        /* open a socket to support control for REMOTE_NODE */                                             
        ctrl_udp_socket = socket_open(SOCKET_UDP, SEND_CTRL_UDP_PORT, empty_udp_receive); 
#endif

        net_6lowpan_id = arm_nwk_interface_init(NET_INTERFACE_RF_6LOWPAN, rf_phy_device_register_id, "6LoWPAN_BORDER_ROUTER");
        if(net_6lowpan_id < 0) 
        {
          debug("Interface Generate Fail\r\n");
          while(1);
        } 
        else 
        {
          //SET Bootsrap
          if(arm_nwk_interface_configure_6lowpan_bootstrap_set(net_6lowpan_id, NET_6LOWPAN_HOST, 1) != 0)  // Last parameter enables MLE protocol
          {
            //Bootsrap SET fail
            debug("Bootstrap Fail\r\n");
            while(1);
          }
          else
          {
            int8_t retval = -1;
            arm_nwk_6lowpan_gp_address_mode(net_6lowpan_id, NET_6LOWPAN_GP16_ADDRESS, NODE_SHORT_ADDRESS, 1);  // 5 = short address for link-layer // 1 = generate automatically if duplicate address is encountered
            arm_nwk_link_layer_security_mode(net_6lowpan_id, NET_SEC_MODE_NO_LINK_SECURITY, 0, 0);
            arm_nwk_6lowpan_link_scan_paramameter_set(rf_phy_device_register_id, channel_list, 5);
            retval = arm_nwk_interface_up(net_6lowpan_id);
            if(retval != 0)
            {
              //6Lowpan Bootsrap start fail
              debug("6LowPAN Bootstrap start Fail\r\n");
              while(1);
            }
            else
            {
              //6Lowpan Bootsrap start OK
              debug("6LowPAN Bootstrap Start OK\r\n");
            }  
            // open sockets
            coap_udp_socket = socket_open(SOCKET_UDP, AUDP_SOCKET_PORT, NSDL_receive_socket);
            // Start NSDL
            nsdl_run();     
          }
          timer_sys_event(NSP_REGISTRATION_TIMER, RD_UPDATE_PERIOD);
        }
        break;
                                    
      case ARM_LIB_SYSTEM_TIMER_EVENT:
        timer_sys_event_cancel(event->event_id);
        if (event->event_id == NSP_REGISTRATION_TIMER) 
        {   
          printf("Time to register...\r\n");                                    
          NSP_registration();
      #if BATTERY
          batteryLevel -= 10;
          if (batteryLevel == 0)
            batteryLevel = 100;
      #endif
          timer_sys_event(NSP_REGISTRATION_TIMER, RD_UPDATE_PERIOD);                                 
        } 
        else if (event->event_id == RETRY_TIMER) 
        {
          debug("Event: ARM_LIB_SYSTEM_TIMER (event_id = 1)\r\n");
          int8_t retval = -1;
          retval = arm_nwk_interface_up(net_6lowpan_id);
          if(retval != 0)
          {
            //6Lowpan Bootsrap start fail
            debug("6LowPAN Bootstrap Start Failure\r\n");
            while(1);
          }
          else
          {
            //6Lowpan Bootsrap start OK
            debug("6LowPAN Bootstrap Start OK\r\n");
          }             
        }
#if NODE_CONTROLLER        
        else if (event->event_id == ACCELEROMETER_TIMER)
        {
          if (accel.getAccX() < -0.85f && accel_enable) 
          {
            accel_enable = 0;
            update_LED();
          }  
          if (accel.getAccX() > -0.35f) 
            accel_enable = 1;
          
          timer_sys_event(ACCELEROMETER_TIMER, ACCEL_SAMPLE_TIME);   
        }    
#endif  

        break;
                                
      default:
        break;
    }
  }
}

void NSDL_receive_socket(void * cb)
{
  socket_callback_t * cb_res =0;
  int16_t length;
  cb_res = (socket_callback_t *) cb;
  uint8_t *payload;

  if(cb_res->event_type == SOCKET_DATA)
  {
    debug("LINK LQI:");
    debug_hex(cb_res->LINK_LQI);
    create_lqi_resource(cb_res->LINK_LQI);
    debug("\r\n");

    if ( cb_res->d_len > 0)
    {
      payload = (uint8_t *) own_alloc(cb_res->d_len);
      if(payload)
      {
        //Read data to the RX buffer
        length = socket_read(cb_res->socket_id, &app_src, payload, cb_res->d_len);  //replace rx_buffer payload
        if(length)
        {
          if(cb_res->socket_id == coap_udp_socket)
          {
            // Handles data received in UDP socket                      
            // Call application protocol parser.
            sn_addr_s.type = SN_NSDL_ADDRESS_TYPE_IPV6;
            sn_addr_s.addr_len = 16;
            sn_addr_s.port = app_src.identifier;
            sn_addr_s.addr_ptr = app_src.address;
            printf("Data 1\r\n");   
            if(sn_nsdl_process_coap(payload, length, &sn_addr_s))  // 0= ok, -1=failure
            {
              debug("Error processing CoAP packet\r\n");
            }
            printf("Data 4\r\n");   
          }
        }
        own_free(payload);
      }
    }
  }
#if 1       // enabled for debug
  else if(cb_res->event_type == SOCKET_TX_DONE)
  {
    //debug("*");
  }
  else if(cb_res->event_type == SOCKET_NO_ROUTE)
  {
    debug("SOCKET_NO_ROUTE\r\n");
  }
  else if(cb_res->event_type == SOCKET_TX_FAIL)
  {
    debug("SOCKET_TX_FAIL\r\n");
  }
#endif   
}

#if NODE_CONTROLLER 
void ctrl_udp_send(uint8_t cmd)
{
  uint8_t * payload = 0;
  ns_address_t address;
  /*SET UDP echo Port*/
  address.identifier = RECV_CTRL_UDP_PORT;  

  uint8_t node_address[16] = REMOTE_NODE;       
    
  payload = (uint8_t *) ns_dyn_mem_alloc(1);        
  if(payload)
  {
    uint8_t *ptr = payload;
     
    memcpy(address.address,node_address,16); 
    address.type = ADDRESS_IPV6;
    *ptr = cmd;
    if(socket_sendto(ctrl_udp_socket, &address, payload, (1)) != 0)
    {
      debug("Ctrl UDP Failed\r\n");
    }
    else
    {
      debug("Ctrl UDP Ok\r\n");
    }
    ns_dyn_mem_free(payload);
  }
  else
  {
    debug("No Heap for Ctrl UDP\r\n");
  }
}
// we don't expect to receive data
void empty_udp_receive(void * cb) {
    
}
#endif