// *******************************************************************
// * simple-main.c
// *
// * This file provides a definition for main() for non-RTOS applications.
// *
// * Copyright 2014 Silicon Laboratories, Inc. *80*
// *******************************************************************
#include PLATFORM_HEADER
#include "app/framework/include/af.h"
// Our entry point is typically main(), except during testing.
#ifdef EMBER_TEST
#define MAIN nodeMain
#else
#define MAIN main
#endif
int MAIN(MAIN_FUNCTION_PARAMETERS)
{
halInit();
emberAfMainInit();
return emberAfMain(MAIN_FUNCTION_ARGUMENTS);
}
在插件中会选择是否生产simple-main , 这个便是入口函数;
主要分三段:
1、硬件初始化
2、主要是串口初始化
3、开始执行Znet
先看第一步硬件初始化:
// halInit is called on first initial boot, not on wakeup from sleep.
//这个函数只有在初始化的时候调用, 而不是唤醒之后调用
void halInit(void)
{
//When the Cortex-M3 exits reset, interrupts are enable. Explicitly
//disable them for the rest of Init.
//关闭中断
__disable_irq();
// Configure BASEPRI to be at the interrupts disabled level so that when we
// turn interrupts back on nothing fires immediately.
// 也是关闭中断, 会判断一个是否使用寄存器来关闭, __disable_irq 这个是cm3内核关闭全局中断
INTERRUPTS_OFF();
// Bootloader might be at the base of flash, or even in the NULL_BTL case,
// the BAT/AAT will be at the beginning of the image.
// Setting the vectorTable is required.
// 设置矢量表,用STM32 OTA的应用程序段都要做矢量偏移,这个类似
SCB->VTOR = (uint32_t)halAppAddressTable.baseTable.vectorTable;
// Always Configure Interrupt Priorities. This is necessary for key behavior
// such as fault Handlers to be serviced at the correct priority levels.
// 设置NV中断
#define EXCEPTION(vectorNumber, functionName, deviceIrqn, deviceIrqHandler, priorityLevel, subpriority) \
NVIC_SetPriority(deviceIrqn, NVIC_EncodePriority(PRIGROUP_POSITION, priorityLevel, subpriority));
#include NVIC_CONFIG
#undef EXCEPTION
//Now that all the individual priority bits are set, we have to set the
//distinction between preemptive priority and non-preemptive subpriority
//This sets the priority grouping binary position.
//PRIGROUP_POSITION is defined inside of nvic-config.h.
//设置中断组
NVIC_SetPriorityGrouping(PRIGROUP_POSITION);
// Always Configure System Handlers Control and Configuration
SCB->CCR |= SCB_CCR_STKALIGN_Msk; //
#if defined(SCB_CCR_DIV_0_TRP_Msk)
SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk;
#endif
#if defined(SCB_SHCSR_USGFAULTENA_Msk)
SCB->SHCSR = (SCB_SHCSR_USGFAULTENA_Msk
| SCB_SHCSR_BUSFAULTENA_Msk
| SCB_SHCSR_MEMFAULTENA_Msk);
#endif
//使能内存保护单元
halInternalEnableMPU();
// Determine and record the reason for the reset. Because this code uses
// static variables in RAM, it must be performed after RAM segements are
// initialized, but the RESETINFO segment is left uninitialized.
halInternalClassifyReset();
// Zero out the EMHEAP segment.
{
// IAR warns about "integer conversion resulted in truncation" if
// _EMHEAP_SEGMENT_SIZE is used directly in MEMSET(). This segment
// should always be smaller than a 16bit size.
MEMSET(_EMHEAP_SEGMENT_BEGIN, 0, (_EMHEAP_SEGMENT_SIZE & 0xFFFFu));
}
// Zero out the APP_RAM segment.
{
// IAR warns about "integer conversion resulted in truncation" if
// _APP_RAM_SEGMENT_SIZE is used directly in MEMSET(). This segment
// should always be smaller than a 16bit size.
MEMSET(_APP_RAM_SEGMENT_BEGIN, 0, (_APP_RAM_SEGMENT_SIZE & 0xFFFFu));
}
__enable_irq();
/* Configure board. Select either EBI or SPI mode. */
CHIP_Init();
#ifdef _EFR_DEVICE
EMU_UnlatchPinRetention();
#endif
halConfigInit();
RTCDRV_Init();
#ifdef _EFR_DEVICE
#ifndef HAL_CONFIG
halInternalInitBoard();
#endif
TEMPDRV_Init();
EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
em4Init.em4State = emuEM4Hibernate;
EMU_EM4Init(&em4Init);
halInternalEm4Wakeup();
#elif defined(_EZR_DEVICE)
halInternalStartSymbolTimer(); // TODO: move to macInit or emRadioInit
#endif
//初始化系统时钟
halInternalStartSystemTimer();
#if (PHY_RAIL || PHY_DUALRAIL)
RAIL_TxPowerCurvesConfig_t txPowerCurvesConfig = { RAIL_Curves24Hp, RAIL_CurvesSg, RAIL_Curves24Lp, RAIL_PiecewiseSegments };
RAIL_InitTxPowerCurves(&txPowerCurvesConfig);
#endif//(PHY_RAIL || PHY_DUALRAIL)
}
总的来说, 第一步主要就是初始化芯片内部的一些配置,比如中断,MPU,时钟等等,这部分建议不要修改。
第二步:
void emberAfMainInit(void)
{
SETUP_FAKE_EEPROM_FOR_SIMULATION();
INTERRUPTS_ON(); // Safe to enable interrupts at this point
emberSerialInit(APP_SERIAL, BAUD_RATE, PARITY_NONE, 1);
emberAfCorePrintln("Reset info: 0x%x (%p)",
halGetResetInfo(),
halGetResetString());
#if defined(EXTENDED_RESET_INFO)
emberAfCorePrintln("Extended Reset info: 0x%2X (%p)",
halGetExtendedResetInfo(),
halGetExtendedResetString());
if (halResetWasCrash()) {
halPrintCrashSummary(serialPort);
halPrintCrashDetails(serialPort);
halPrintCrashData(serialPort);
}
#endif
}
这不总的来说,就是初始化串口的,打印一下复位原因。
接下来才是正戏。