LoRaWAN class B application example for the NucleoL073.
#include <stdio.h>
#include "utilities.h"
#include "board.h"
#include "gpio.h"
#include "Commissioning.h"
#include "NvmCtxMgmt.h"
#ifndef ACTIVE_REGION
#warning "No active region defined, LORAMAC_REGION_EU868 will be used as default."
#define ACTIVE_REGION LORAMAC_REGION_EU868
#endif
#define LOCAL_MULTICAST_SETUP_ENABLED 0
#define LOCAL_MULTICAST_SETUP_DISABLE_SLOT_HOP 0
#define APP_TX_DUTYCYCLE 30000
#define APP_TX_DUTYCYCLE_RND 5000
#define LORAWAN_DEFAULT_DATARATE DR_0
#define LORAWAN_DEFAULT_PING_SLOT_PERIODICITY 0
#define LORAWAN_CONFIRMED_MSG_ON false
#define LORAWAN_ADR_ON 1
#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
#define LORAWAN_DUTYCYCLE_ON true
#endif
#define LORAWAN_APP_PORT 2
#if( OVER_THE_AIR_ACTIVATION == 0 )
static uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
#endif
static uint8_t AppPort = LORAWAN_APP_PORT;
static uint8_t AppDataSize = 1;
static uint8_t AppDataSizeBackup = 1;
#define LORAWAN_APP_DATA_MAX_SIZE 242
static uint8_t AppDataBuffer[LORAWAN_APP_DATA_MAX_SIZE];
static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
static uint32_t TxDutyCycleTime;
static TimerEvent_t TxNextPacketTimer;
static bool AppLedStateOn = false;
static TimerEvent_t Led1Timer;
static TimerEvent_t Led2Timer;
static TimerEvent_t LedBeaconTimer;
static bool NextTx = true;
static uint8_t IsMacProcessPending = 0;
static enum eDeviceState
{
DEVICE_STATE_RESTORE,
DEVICE_STATE_START,
DEVICE_STATE_JOIN,
DEVICE_STATE_SEND,
DEVICE_STATE_REQ_DEVICE_TIME,
DEVICE_STATE_REQ_PINGSLOT_ACK,
DEVICE_STATE_REQ_BEACON_TIMING,
DEVICE_STATE_BEACON_ACQUISITION,
DEVICE_STATE_SWITCH_CLASS,
DEVICE_STATE_CYCLE,
DEVICE_STATE_SLEEP
}DeviceState, WakeUpState;
struct ComplianceTest_s
{
bool Running;
uint8_t State;
bool IsTxConfirmed;
uint8_t AppPort;
uint8_t AppDataSize;
uint8_t *AppDataBuffer;
uint16_t DownLinkCounter;
bool LinkCheck;
uint8_t DemodMargin;
uint8_t NbGateways;
}ComplianceTest;
typedef enum
{
LORAMAC_HANDLER_UNCONFIRMED_MSG = 0,
LORAMAC_HANDLER_CONFIRMED_MSG = !LORAMAC_HANDLER_UNCONFIRMED_MSG
}LoRaMacHandlerMsgTypes_t;
typedef struct LoRaMacHandlerAppData_s
{
LoRaMacHandlerMsgTypes_t MsgType;
uint8_t Port;
uint8_t BufferSize;
uint8_t *Buffer;
}LoRaMacHandlerAppData_t;
LoRaMacHandlerAppData_t AppData =
{
.MsgType = LORAMAC_HANDLER_UNCONFIRMED_MSG,
.Buffer = NULL,
.BufferSize = 0,
.Port = 0
};
extern Gpio_t Led1;
extern Gpio_t Led2;
const char* MacStatusStrings[] =
{
"OK",
"Busy",
"Service unknown",
"Parameter invalid",
"Frequency invalid",
"Datarate invalid",
"Frequency or datarate invalid",
"No network joined",
"Length error",
"Region not supported",
"Skipped APP data",
"Duty-cycle restricted",
"No channel found",
"No free channel found",
"Busy beacon reserved time",
"Busy ping-slot window time",
"Busy uplink collision",
"Crypto error",
"FCnt handler error",
"MAC command error",
"ClassB error",
"Confirm queue error",
"Multicast group undefined",
"Unknown error",
};
const char* EventInfoStatusStrings[] =
{
"OK",
"Error",
"Tx timeout",
"Rx 1 timeout",
"Rx 2 timeout",
"Rx1 error",
"Rx2 error",
"Join failed",
"Downlink repeated",
"Tx DR payload size error",
"Downlink too many frames loss",
"Address fail",
"MIC fail",
"Multicast fail",
"Beacon locked",
"Beacon lost",
"Beacon not found"
};
void PrintHexBuffer( uint8_t *buffer, uint8_t size )
{
uint8_t newline = 0;
for( uint8_t i = 0; i < size; i++ )
{
if( newline != 0 )
{
printf( "\n" );
newline = 0;
}
printf( "%02X ", buffer[i] );
if( ( ( i + 1 ) % 16 ) == 0 )
{
newline = 1;
}
}
printf( "\n" );
}
static void JoinNetwork( void )
{
printf( "\n###### ===== MLME-Request - MLME_JOIN ==== ######\n" );
printf( "STATUS : %s\n", MacStatusStrings[status] );
{
printf( "###### ===== JOINING ==== ######\n" );
DeviceState = DEVICE_STATE_SLEEP;
}
else
{
{
}
DeviceState = DEVICE_STATE_CYCLE;
}
}
static void PrepareTxFrame( uint8_t port )
{
switch( port )
{
case 2:
{
AppDataSizeBackup = AppDataSize = 1;
AppDataBuffer[0] = AppLedStateOn;
}
break;
case 224:
if( ComplianceTest.LinkCheck == true )
{
ComplianceTest.LinkCheck = false;
AppDataSize = 3;
AppDataBuffer[0] = 5;
AppDataBuffer[1] = ComplianceTest.DemodMargin;
AppDataBuffer[2] = ComplianceTest.NbGateways;
ComplianceTest.State = 1;
}
else
{
switch( ComplianceTest.State )
{
case 4:
ComplianceTest.State = 1;
break;
case 1:
AppDataSize = 2;
AppDataBuffer[0] = ComplianceTest.DownLinkCounter >> 8;
AppDataBuffer[1] = ComplianceTest.DownLinkCounter;
break;
}
}
break;
default:
break;
}
}
static bool SendFrame( void )
{
{
}
else
{
if( IsTxConfirmed == false )
{
}
else
{
}
}
AppData.MsgType = ( mcpsReq.
Type ==
MCPS_CONFIRMED ) ? LORAMAC_HANDLER_CONFIRMED_MSG : LORAMAC_HANDLER_UNCONFIRMED_MSG;
printf( "\n###### ===== MCPS-Request ==== ######\n" );
printf( "STATUS : %s\n", MacStatusStrings[status] );
{
}
{
return false;
}
return true;
}
static void OnTxNextPacketTimerEvent( void* context )
{
TimerStop( &TxNextPacketTimer );
{
{
JoinNetwork( );
}
else
{
DeviceState = WakeUpState;
NextTx = true;
}
}
}
static void OnLed1TimerEvent( void* context )
{
TimerStop( &Led1Timer );
GpioWrite( &Led1, 0 );
}
static void OnLed2TimerEvent( void* context )
{
TimerStop( &Led2Timer );
GpioWrite( &Led2, 0 );
}
static void OnLedBeaconTimerEvent( void* context )
{
GpioWrite( &Led2, 1 );
TimerStart( &Led2Timer );
TimerStart( &LedBeaconTimer );
}
{
printf( "\n###### ===== MCPS-Confirm ==== ######\n" );
printf(
"STATUS : %s\n", EventInfoStatusStrings[mcpsConfirm->
Status] );
{
}
else
{
{
{
break;
}
{
break;
}
{
break;
}
default:
break;
}
GpioWrite( &Led1, 1 );
TimerStart( &Led1Timer );
}
printf(
"\n###### ===== UPLINK FRAME %lu ==== ######\n", mcpsConfirm->
UpLinkCounter );
printf( "\n" );
printf(
"CLASS : %c\n",
"ABC"[mibReq.
Param.
Class] );
printf( "\n" );
printf( "TX PORT : %d\n", AppData.Port );
if( AppData.BufferSize != 0 )
{
printf( "TX DATA : " );
if( AppData.MsgType == LORAMAC_HANDLER_CONFIRMED_MSG )
{
printf(
"CONFIRMED - %s\n", ( mcpsConfirm->
AckReceived != 0 ) ?
"ACK" :
"NACK" );
}
else
{
printf( "UNCONFIRMED\n" );
}
PrintHexBuffer( AppData.Buffer, AppData.BufferSize );
}
printf( "\n" );
printf(
"DATA RATE : DR_%d\n", mcpsConfirm->
Datarate );
{
}
printf(
"TX POWER : %d\n", mcpsConfirm->
TxPower );
{
printf("CHANNEL MASK: ");
#if defined( REGION_AS923 ) || defined( REGION_CN779 ) || \
defined( REGION_EU868 ) || defined( REGION_IN865 ) || \
defined( REGION_KR920 ) || defined( REGION_EU433 ) || \
defined( REGION_RU864 )
for( uint8_t i = 0; i < 1; i++)
#elif defined( REGION_AU915 ) || defined( REGION_US915 ) || defined( REGION_CN470 )
for( uint8_t i = 0; i < 5; i++)
#else
#error "Please define a region in the compiler options."
#endif
{
}
printf("\n");
}
printf( "\n" );
}
{
printf( "\n###### ===== MCPS-Indication ==== ######\n" );
printf(
"STATUS : %s\n", EventInfoStatusStrings[mcpsIndication->
Status] );
{
return;
}
{
{
break;
}
{
break;
}
{
break;
}
{
break;
}
default:
break;
}
{
OnTxNextPacketTimerEvent( NULL );
}
if( ComplianceTest.Running == true )
{
ComplianceTest.DownLinkCounter++;
}
if( mcpsIndication->
RxData ==
true )
{
switch( mcpsIndication->
Port )
{
case 1:
case 2:
{
AppLedStateOn = mcpsIndication->
Buffer[0] & 0x01;
}
break;
case 224:
if( ComplianceTest.Running == false )
{
( mcpsIndication->
Buffer[0] == 0x01 ) &&
( mcpsIndication->
Buffer[1] == 0x01 ) &&
( mcpsIndication->
Buffer[2] == 0x01 ) &&
( mcpsIndication->
Buffer[3] == 0x01 ) )
{
IsTxConfirmed = false;
AppPort = 224;
AppDataSizeBackup = AppDataSize;
AppDataSize = 2;
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.LinkCheck = false;
ComplianceTest.DemodMargin = 0;
ComplianceTest.NbGateways = 0;
ComplianceTest.Running = true;
ComplianceTest.State = 1;
#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
#endif
}
}
else
{
ComplianceTest.State = mcpsIndication->
Buffer[0];
switch( ComplianceTest.State )
{
case 0:
IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
AppPort = LORAWAN_APP_PORT;
AppDataSize = AppDataSizeBackup;
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.Running = false;
#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
#endif
break;
case 1:
AppDataSize = 2;
break;
case 2:
IsTxConfirmed = true;
ComplianceTest.State = 1;
break;
case 3:
IsTxConfirmed = false;
ComplianceTest.State = 1;
break;
case 4:
AppDataBuffer[0] = 4;
for( uint8_t i = 1; i < MIN( AppDataSize, LORAWAN_APP_DATA_MAX_SIZE ); i++ )
{
AppDataBuffer[i] = mcpsIndication->
Buffer[i] + 1;
}
break;
case 5:
{
printf( "\n###### ===== MLME-Request - MLME_LINK_CHECK ==== ######\n" );
printf( "STATUS : %s\n", MacStatusStrings[status] );
}
break;
case 6:
{
IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
AppPort = LORAWAN_APP_PORT;
AppDataSize = AppDataSizeBackup;
ComplianceTest.DownLinkCounter = 0;
ComplianceTest.Running = false;
#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
#endif
JoinNetwork( );
}
break;
case 7:
{
{
printf( "\n###### ===== MLME-Request - MLME_TXCW ==== ######\n" );
printf( "STATUS : %s\n", MacStatusStrings[status] );
}
{
printf( "\n###### ===== MLME-Request - MLME_TXCW1 ==== ######\n" );
printf( "STATUS : %s\n", MacStatusStrings[status] );
}
ComplianceTest.State = 1;
}
break;
case 8:
{
WakeUpState = DEVICE_STATE_SEND;
DeviceState = DEVICE_STATE_SEND;
}
break;
case 9:
{
DeviceState = DEVICE_STATE_SEND;
}
break;
case 10:
{
WakeUpState = DEVICE_STATE_SEND;
DeviceState = DEVICE_STATE_SEND;
}
break;
case 11:
{
WakeUpState = DEVICE_STATE_SEND;
DeviceState = DEVICE_STATE_SEND;
}
break;
default:
break;
}
}
break;
default:
break;
}
}
GpioWrite( &Led2, 1 );
TimerStart( &Led2Timer );
const char *slotStrings[] = { "1", "2", "C", "C Multicast", "B Ping-Slot", "B Multicast Ping-Slot" };
printf(
"\n###### ===== DOWNLINK FRAME %lu ==== ######\n", mcpsIndication->
DownLinkCounter );
printf(
"RX WINDOW : %s\n", slotStrings[mcpsIndication->
RxSlot] );
printf(
"RX PORT : %d\n", mcpsIndication->
Port );
{
printf( "RX DATA : \n" );
}
printf( "\n" );
printf(
"DATA RATE : DR_%d\n", mcpsIndication->
RxDatarate );
printf(
"RX RSSI : %d\n", mcpsIndication->
Rssi );
printf(
"RX SNR : %d\n", mcpsIndication->
Snr );
printf( "\n" );
}
{
printf( "\n###### ===== MLME-Confirm ==== ######\n" );
printf(
"STATUS : %s\n", EventInfoStatusStrings[mlmeConfirm->
Status] );
{
}
{
{
{
printf( "###### ===== JOINED ==== ######\n" );
printf( "\nOTAA\n\n" );
printf( "\n\n" );
printf( "\n" );
#if defined( USE_BEACON_TIMING )
DeviceState = DEVICE_STATE_REQ_BEACON_TIMING;
#else
DeviceState = DEVICE_STATE_REQ_DEVICE_TIME;
#endif
}
else
{
JoinNetwork( );
}
break;
}
{
{
if( ComplianceTest.Running == true )
{
ComplianceTest.LinkCheck = true;
ComplianceTest.NbGateways = mlmeConfirm->
NbGateways;
}
}
break;
}
{
WakeUpState = DEVICE_STATE_SEND;
DeviceState = DEVICE_STATE_BEACON_ACQUISITION;
NextTx = true;
break;
}
{
WakeUpState = DEVICE_STATE_SEND;
DeviceState = DEVICE_STATE_BEACON_ACQUISITION;
NextTx = true;
break;
}
{
{
WakeUpState = DEVICE_STATE_REQ_PINGSLOT_ACK;
}
else
{
#if defined( USE_BEACON_TIMING )
WakeUpState = DEVICE_STATE_REQ_BEACON_TIMING;
#else
WakeUpState = DEVICE_STATE_REQ_DEVICE_TIME;
#endif
}
break;
}
{
{
printf( "\n\n###### ===== Switch to Class B done. ==== ######\n\n" );
WakeUpState = DEVICE_STATE_SEND;
DeviceState = WakeUpState;
NextTx = true;
}
else
{
WakeUpState = DEVICE_STATE_REQ_PINGSLOT_ACK;
}
break;
}
default:
break;
}
}
{
{
printf( "\n###### ===== MLME-Indication ==== ######\n" );
printf(
"STATUS : %s\n", EventInfoStatusStrings[mlmeIndication->
Status] );
}
{
}
{
{
OnTxNextPacketTimerEvent( NULL );
break;
}
{
printf( "\n\n###### ===== Switch to Class A done. ==== ######\n\n" );
#if defined( USE_BEACON_TIMING )
WakeUpState = DEVICE_STATE_REQ_BEACON_TIMING;
#else
WakeUpState = DEVICE_STATE_REQ_DEVICE_TIME;
#endif
TimerStop( &LedBeaconTimer );
printf( "\n###### ===== BEACON LOST ==== ######\n" );
break;
}
{
{
TimerStart( &LedBeaconTimer );
printf(
"\n###### ===== BEACON %lu ==== ######\n", mlmeIndication->
BeaconInfo.
Time.Seconds );
printf( "GW INFO : " );
printf( "\n" );
printf( "\n" );
}
else
{
TimerStop( &LedBeaconTimer );
printf( "\n###### ===== BEACON NOT RECEIVED ==== ######\n" );
}
break;
}
default:
break;
}
}
void OnMacProcessNotify( void )
{
IsMacProcessPending = 1;
}
int main( void )
{
uint8_t devEui[8] = { 0 };
uint8_t joinEui[8] = { 0 };
uint8_t sePin[4] = { 0 };
BoardInitMcu( );
BoardInitPeriph( );
{
printf( "LoRaMac wasn't properly initialized, error: %s", MacStatusStrings[status] );
while ( 1 )
{
}
}
#if ( LOCAL_MULTICAST_SETUP_ENABLED == 1 )
uint8_t localMcAppSKey[] = LORAWAN_APP_S_KEY;
uint8_t localMcNwkSKey[] = LORAWAN_NWK_S_ENC_KEY;
uint32_t localMcAddress = 0x01020304;
#if( LOCAL_MULTICAST_SETUP_DISABLE_SLOT_HOP == 1 )
const uint32_t frequencies[] = { 923200000, 923300000, 505300000, 786000000, 434665000, 869525000, 921900000, 866550000, 923300000, 869100000 };
#else
const uint32_t frequencies[] = { 923200000, 0 , 0, 786000000, 434665000, 869525000, 921900000, 866550000, 0, 69100000 };
#endif
{
.IsEnabled = true,
.Address = localMcAddress,
.McKeys =
{
.Session =
{
.McAppSKey = localMcAppSKey,
.McNwkSKey = localMcNwkSKey,
},
},
.FCountMin = 0,
.FCountMax = UINT32_MAX,
.RxParams.ClassB =
{
.Frequency = frequencies[ACTIVE_REGION],
.Datarate = dataRates[ACTIVE_REGION],
}
};
{
uint8_t mcChannelSetupStatus = 0x00;
{
if( ( mcChannelSetupStatus & 0xFC ) == 0x00 )
{
printf("MC #%d setup, OK\n", ( mcChannelSetupStatus & 0x03 ) );
}
else
{
printf("MC #%d setup, ERROR - ", ( mcChannelSetupStatus & 0x03 ) );
if( ( mcChannelSetupStatus & 0x10 ) == 0x10 )
{
printf("MC group UNDEFINED - ");
}
else
{
printf("MC group OK - ");
}
if( ( mcChannelSetupStatus & 0x08 ) == 0x08 )
{
printf("MC Freq ERROR - ");
}
else
{
printf("MC Freq OK - ");
}
if( ( mcChannelSetupStatus & 0x04 ) == 0x04 )
{
printf("MC datarate ERROR\n");
}
else
{
printf("MC datarate OK\n");
}
}
}
else
{
printf( "MC Rx params setup, error: %s \n", MacStatusStrings[status] );
}
}
else
{
printf( "MC setup, error: %s \n", MacStatusStrings[status] );
}
#endif
DeviceState = DEVICE_STATE_RESTORE;
WakeUpState = DEVICE_STATE_START;
printf( "###### ===== ClassB demo application v1.0.0 ==== ######\n\n" );
while( 1 )
{
if( Radio.IrqProcess != NULL )
{
Radio.IrqProcess( );
}
switch( DeviceState )
{
case DEVICE_STATE_RESTORE:
{
if( NvmCtxMgmtRestore( ) == NVMCTXMGMT_STATUS_SUCCESS )
{
printf( "\n###### ===== CTXS RESTORED ==== ######\n\n" );
}
else
{
#if( OVER_THE_AIR_ACTIVATION == 0 )
mibReq.
Param.
AbpLrWanVersion.Value = ABP_ACTIVATION_LRWAN_VERSION;
#if( STATIC_DEVICE_ADDRESS != 1 )
srand1( BoardGetRandomSeed( ) );
DevAddr = randr( 0, 0x01FFFFFF );
#endif
#endif // #if( OVER_THE_AIR_ACTIVATION == 0 )
}
DeviceState = DEVICE_STATE_START;
break;
}
case DEVICE_STATE_START:
{
TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent );
TimerInit( &Led1Timer, OnLed1TimerEvent );
TimerSetValue( &Led1Timer, 25 );
TimerInit( &Led2Timer, OnLed2TimerEvent );
TimerSetValue( &Led2Timer, 25 );
TimerInit( &LedBeaconTimer, OnLedBeaconTimerEvent );
TimerSetValue( &LedBeaconTimer, 5000 );
#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
#endif
{
{
DeviceState = DEVICE_STATE_JOIN;
}
else
{
DeviceState = DEVICE_STATE_SEND;
NextTx = true;
}
}
break;
}
case DEVICE_STATE_JOIN:
{
for( int i = 1; i < 8; i++ )
{
}
printf( "\n" );
for( int i = 1; i < 8; i++ )
{
}
printf( "\n" );
for( int i = 1; i < 4; i++ )
{
}
printf( "\n\n" );
#if( OVER_THE_AIR_ACTIVATION == 0 )
printf( "###### ===== JOINED ==== ######\n" );
printf( "\nABP\n\n" );
printf( "DevAddr : %08lX\n", DevAddr );
printf( "\n\n" );
#if defined( USE_BEACON_TIMING )
DeviceState = DEVICE_STATE_REQ_BEACON_TIMING;
#else
DeviceState = DEVICE_STATE_REQ_DEVICE_TIME;
#endif
#else
JoinNetwork( );
#endif
break;
}
case DEVICE_STATE_REQ_DEVICE_TIME:
{
if( NextTx == true )
{
{
WakeUpState = DEVICE_STATE_SEND;
}
}
DeviceState = DEVICE_STATE_SEND;
break;
}
case DEVICE_STATE_REQ_BEACON_TIMING:
{
if( NextTx == true )
{
{
WakeUpState = DEVICE_STATE_SEND;
}
}
DeviceState = DEVICE_STATE_SEND;
break;
}
case DEVICE_STATE_BEACON_ACQUISITION:
{
if( NextTx == true )
{
NextTx = false;
}
DeviceState = DEVICE_STATE_SEND;
break;
}
case DEVICE_STATE_REQ_PINGSLOT_ACK:
{
if( NextTx == true )
{
{
WakeUpState = DEVICE_STATE_SEND;
}
}
DeviceState = DEVICE_STATE_SEND;
break;
}
case DEVICE_STATE_SEND:
{
if( NextTx == true )
{
PrepareTxFrame( AppPort );
NextTx = SendFrame( );
}
DeviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_CYCLE:
{
DeviceState = DEVICE_STATE_SLEEP;
if( ComplianceTest.Running == true )
{
TxDutyCycleTime = 5000;
}
else
{
TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND );
}
TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
TimerStart( &TxNextPacketTimer );
break;
}
case DEVICE_STATE_SLEEP:
{
if( NvmCtxMgmtStore( ) == NVMCTXMGMT_STATUS_SUCCESS )
{
printf( "\n###### ===== CTXS STORED ==== ######\n" );
}
CRITICAL_SECTION_BEGIN( );
if( IsMacProcessPending == 1 )
{
IsMacProcessPending = 0;
}
else
{
BoardLowPowerHandler( );
}
CRITICAL_SECTION_END( );
break;
}
default:
{
DeviceState = DEVICE_STATE_START;
break;
}
}
}
}