initial commit
This commit is contained in:
407
project/ble_peripheral/ble_app_vivaMayo/main.c
Normal file
407
project/ble_peripheral/ble_app_vivaMayo/main.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*******************************************************************************
|
||||
* @file main.c
|
||||
* @brief MEDiThings VivaMayo - Main Application Entry Point
|
||||
* @author Charles KWON <charleskwon@medithings.co.kr>
|
||||
* @date 2025-01-30
|
||||
* @copyright (c) 2025 Medithings Inc. All rights reserved.
|
||||
*
|
||||
* @version 1.17
|
||||
* @note 2025-01-30 Refactored into modular structure (Charles KWON)
|
||||
* @note 2025-12-31 Added comprehensive function documentation (Charles KWON)
|
||||
* @note 2025-11-27 Firmware cleanup and refactoring (Charles KWON)
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "debug_print.h"
|
||||
#include "app_uart.h"
|
||||
|
||||
/* Nordic SDK */
|
||||
#include "nordic_common.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_soc.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_pwr_mgmt.h"
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
#include "app_timer.h"
|
||||
#include "app_error.h"
|
||||
#include "bsp.h"
|
||||
#include "bsp_btn_ble.h"
|
||||
#include "ble_nus.h"
|
||||
|
||||
/* Application Modules */
|
||||
#include "ble/ble_core.h"
|
||||
#include "ble/ble_services.h"
|
||||
#include "ble/ble_data_tx.h"
|
||||
#include "power/power_ctrl.h"
|
||||
#include "peripheral/uart_handler.h"
|
||||
#include "config/device_config.h"
|
||||
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
#include "ble/ble_security.h"
|
||||
#include "nrf_ble_lesc.h"
|
||||
#endif
|
||||
|
||||
/* Hardware and Measurement Modules */
|
||||
#include "main.h"
|
||||
#include "main_timer.h"
|
||||
#include "battery_saadc.h"
|
||||
#include "measurements.h"
|
||||
#include "full_agc.h"
|
||||
#include "meas_pd_voltage_simple.h"
|
||||
#include "meas_pd_voltage_half.h"
|
||||
/* #include "meas_pd_voltage_full.h" */ /* Moved to unuse/ - FEATURE_PRINTF=0, not used */
|
||||
#include "meas_pd_voltage_custom.h"
|
||||
#include "meas_pd_imm.h"
|
||||
#include "meas_pd_48.h"
|
||||
#include "power_control.h"
|
||||
#include "cat_interface.h"
|
||||
#include "fstorage.h"
|
||||
#include "drivers/w25q32/w25q32.h"
|
||||
|
||||
/* Crypto */
|
||||
#include "nrf_crypto.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* @section BUILD_CONFIG Build Configuration
|
||||
* @brief Compile-time feature flags and debug settings
|
||||
* @details Controls boot mode selection between minimal (Power+BLE only) and
|
||||
* full initialization (includes EEPROM and all peripherals).
|
||||
|
||||
* Set DEBUG_MINIMAL_BOOT=1 for rapid debugging without EEPROM dependency.
|
||||
******************************************************************************/
|
||||
|
||||
#define DEBUG_MINIMAL_BOOT 1 /**< 1: Power+BLE only (no EEPROM), 0: Full boot */
|
||||
|
||||
/*******************************************************************************
|
||||
* @section CONSTANTS Symbolic Constants
|
||||
* @brief Application-wide constant definitions
|
||||
* @details Magic numbers and compile-time constants used for error handling,
|
||||
* fault detection, and system-level operations.
|
||||
******************************************************************************/
|
||||
|
||||
#define DEAD_BEEF 0xDEADBEEF
|
||||
|
||||
/*******************************************************************************
|
||||
* @section GLOBALS Global Variables
|
||||
* @brief Shared runtime state and data buffers
|
||||
* @details BLE transmission buffers, command type state, and cross-module
|
||||
* flags. External declarations reference state from other modules.
|
||||
* @warning Global state should be accessed with care in interrupt context.
|
||||
******************************************************************************/
|
||||
|
||||
char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
|
||||
uint16_t ble_bin_buff[BLE_NUS_MAX_DATA_LEN/2];
|
||||
which_cmd_t cmd_type_t;
|
||||
|
||||
/* External state flags from other modules */
|
||||
extern bool ble_got_new_data;
|
||||
extern bool motion_data_once;
|
||||
extern bool adc_enabled;
|
||||
extern bool con_single;
|
||||
extern bool info4;
|
||||
extern uint8_t add_cycle;
|
||||
extern bool motion_raw_data_enabled;
|
||||
|
||||
/*******************************************************************************
|
||||
* @section FWD_DECL Forward Declarations
|
||||
* @brief Static function prototypes
|
||||
* @details Internal initialization and handler functions declared here for
|
||||
* proper ordering. Visibility limited to this translation unit.
|
||||
******************************************************************************/
|
||||
|
||||
static void timers_init(void);
|
||||
static void log_init(void);
|
||||
static void power_management_init(void);
|
||||
static void buttons_leds_init(bool * p_erase_bonds);
|
||||
#if !DEBUG_MINIMAL_BOOT
|
||||
static void gpio_init(void);
|
||||
#endif
|
||||
static void idle_state_handle(void);
|
||||
|
||||
/*******************************************************************************
|
||||
* @section ASSERT Assert Handler
|
||||
* @brief System fault callback for SDK assertions
|
||||
* @details Invoked by Nordic SDK on fatal errors. Provides fault location
|
||||
* (file and line) for debugging via app_error_handler.
|
||||
******************************************************************************/
|
||||
|
||||
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
|
||||
{
|
||||
app_error_handler(DEAD_BEEF, line_num, p_file_name);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section INIT Initialization Functions
|
||||
* @brief System and peripheral initialization routines
|
||||
* @details Configures logging, power management, timers, and BSP components.
|
||||
* Call order is critical - see main() for proper sequencing.
|
||||
******************************************************************************/
|
||||
|
||||
static void log_init(void)
|
||||
{
|
||||
ret_code_t err_code = NRF_LOG_INIT(NULL);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
NRF_LOG_DEFAULT_BACKENDS_INIT();
|
||||
}
|
||||
|
||||
static void power_management_init(void)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
err_code = nrf_pwr_mgmt_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
static void timers_init(void)
|
||||
{
|
||||
ret_code_t err_code = app_timer_init();
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
/* Power control timers */
|
||||
power_ctrl_timers_init();
|
||||
|
||||
/* Application timers */
|
||||
main_timer_init();
|
||||
battery_timer_init();
|
||||
imm_check_timer_init();
|
||||
m48_check_timer_init();
|
||||
full_agc_timer_init();
|
||||
full_agc_send_timer_init();
|
||||
mea_send_timer_init();
|
||||
power_timer_init();
|
||||
w25q_test_timer_init();
|
||||
|
||||
/* full_timer_init() - Moved to unuse/, FEATURE_PRINTF=0 so not used */
|
||||
}
|
||||
|
||||
static void buttons_leds_init(bool * p_erase_bonds)
|
||||
{
|
||||
bsp_event_t startup_event;
|
||||
|
||||
uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, power_bsp_event_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
err_code = bsp_btn_ble_init(NULL, &startup_event);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
*p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section PWR_HOLD Power Hold Initialization
|
||||
* @brief Latches power supply on boot
|
||||
* @details Configures P0.08 (POWER_HOLD) as output HIGH to maintain VCC.
|
||||
* CRITICAL: Must be the first call in main() - any delay risks
|
||||
* power loss if button is released before latch is set.
|
||||
* @note Uses direct register access for minimum latency.
|
||||
******************************************************************************/
|
||||
static void power_hold_init(void)
|
||||
{
|
||||
/* P0.08 = POWER_HOLD, configure as output and set HIGH to maintain power */
|
||||
NRF_P0->DIRSET = (1 << 8);
|
||||
NRF_P0->OUTSET = (1 << 8);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section MIN_GPIO Minimal GPIO Initialization (Debug Mode)
|
||||
* @brief Reduced GPIO setup for rapid debugging
|
||||
* @details Initializes only essential pins: POWER_BUTTON input, POWER_HOLD
|
||||
* output, and power control GPIOs. Skips LEDs, PD array, gain
|
||||
* switches, and EEPROM control for faster boot.
|
||||
* @pre DEBUG_MINIMAL_BOOT must be set to 1
|
||||
******************************************************************************/
|
||||
static void minimal_gpio_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_input(POWER_BUTTON, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_output(POWER_HOLD);
|
||||
nrf_gpio_pin_set(POWER_HOLD);
|
||||
power_gpio_init();
|
||||
LOG_PRINTF("[GPIO] Minimal OK\r\n");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section MIN_CFG Default Configuration Loader (Debug Mode)
|
||||
* @brief Loads hardcoded defaults bypassing EEPROM
|
||||
* @details Sets factory defaults for serial number, passkey, PD timing,
|
||||
* and bonding state. Used when EEPROM is unavailable or for
|
||||
* rapid iteration during development.
|
||||
* @pre DEBUG_MINIMAL_BOOT must be set to 1
|
||||
******************************************************************************/
|
||||
static void load_default_config(void)
|
||||
{
|
||||
/* Direct assignment of variables defined in device_config.h */
|
||||
memset(SERIAL_NO, 0, sizeof(SERIAL_NO));
|
||||
memcpy(SERIAL_NO, "2025VIVAM00001", 14);
|
||||
|
||||
memset(m_static_passkey, 0, sizeof(m_static_passkey));
|
||||
memcpy(m_static_passkey, "123456", 6);
|
||||
|
||||
m_pd_delay_us = 8000;
|
||||
m_pd_adc_cnt = 8;
|
||||
bond_data_delete = true;
|
||||
|
||||
LOG_PRINTF("[CFG] Default (S/N=%s)\r\n", SERIAL_NO);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section FULL_GPIO Full GPIO Initialization (Production Mode)
|
||||
* @brief Complete peripheral GPIO configuration
|
||||
* @details Initializes all hardware interfaces: LEDs, photodiode array (PD),
|
||||
* trigger switches, AGC gain control, power management, and EEPROM.
|
||||
* All outputs are set to safe default states (LEDs off, PD off).
|
||||
* @pre DEBUG_MINIMAL_BOOT must be set to 0
|
||||
******************************************************************************/
|
||||
#if !DEBUG_MINIMAL_BOOT
|
||||
static void gpio_init(void)
|
||||
{
|
||||
nrf_gpio_cfg_input(POWER_BUTTON, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
LED_CONFIG();
|
||||
LED_ALLOFF();
|
||||
|
||||
PD_CONFIG();
|
||||
PD_ALLOFF();
|
||||
|
||||
trig_r_CONFIG();
|
||||
trig_SW(false);
|
||||
|
||||
GAIN_SW_CONFIG();
|
||||
AGC_GAIN_SW(false);
|
||||
|
||||
power_gpio_init();
|
||||
eeprom_control(OFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* @section IDLE Idle State Handler
|
||||
* @brief Low-power idle loop processing
|
||||
* @details Handles security operations (LESC if enabled), flushes NRF_LOG
|
||||
* buffer, then enters System ON sleep via nrf_pwr_mgmt_run().
|
||||
* CPU wakes on any enabled interrupt (BLE, timer, GPIO).
|
||||
******************************************************************************/
|
||||
|
||||
static void idle_state_handle(void)
|
||||
{
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
security_idle_state_handle();
|
||||
#endif
|
||||
|
||||
if (NRF_LOG_PROCESS() == false) {
|
||||
nrf_pwr_mgmt_run();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* @section MAIN Application Entry Point
|
||||
* @brief System initialization and main loop
|
||||
* @details Boot sequence: Power latch → UART → Logging → GPIO → Timers →
|
||||
* Config → BSP → Power Mgmt → BLE Stack → GAP → GATT → Services →
|
||||
* Advertising → Connection Params → Power Button Handler.
|
||||
* Main loop runs idle_state_handle() for low-power operation.
|
||||
* @note Initialization order is critical for proper hardware bringup.
|
||||
******************************************************************************/
|
||||
|
||||
/* LED slow blink macro (approximately 0.5 second period) */
|
||||
#define LED_BLINK() do { \
|
||||
NRF_P0->OUTSET = (1 << 12); \
|
||||
for (volatile uint32_t _d = 0; _d < 1000000; _d++); \
|
||||
NRF_P0->OUTCLR = (1 << 12); \
|
||||
for (volatile uint32_t _d = 0; _d < 1000000; _d++); \
|
||||
} while(0)
|
||||
|
||||
#define LED_PAUSE() do { \
|
||||
for (volatile uint32_t _d = 0; _d < 2000000; _d++); \
|
||||
} while(0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
bool erase_bonds_local = false;
|
||||
#endif
|
||||
|
||||
/* Configure LED output (P0.12) */
|
||||
NRF_P0->DIRSET = (1 << 12);
|
||||
|
||||
power_hold_init();
|
||||
|
||||
if (power_off_duble_prohibit) return 0;
|
||||
cnt_s = 0;
|
||||
|
||||
uart_handler_init();
|
||||
nrf_delay_ms(100); /* Wait for UART peripheral stabilization */
|
||||
log_init();
|
||||
|
||||
g_log_enable = true; /* Enable boot logging (set to false to disable boot logs) */
|
||||
|
||||
LOG_PRINTF("\r\n\r\n");
|
||||
LOG_PRINTF("========================================\r\n");
|
||||
LOG_PRINTF(" vivaMayo UART OK\r\n");
|
||||
LOG_PRINTF("========================================\r\n");
|
||||
|
||||
#if DEBUG_MINIMAL_BOOT
|
||||
LOG_PRINTF("[1] GPIO (minimal)\r\n");
|
||||
minimal_gpio_init();
|
||||
#else
|
||||
LOG_PRINTF("[1] GPIO (full)\r\n");
|
||||
gpio_init();
|
||||
#endif
|
||||
info4 = false;
|
||||
|
||||
LOG_PRINTF("[2] Timers\r\n");
|
||||
timers_init();
|
||||
|
||||
LOG_PRINTF("[4] Buttons/LEDs\r\n");
|
||||
#if FEATURE_SECURE_CONNECTION
|
||||
buttons_leds_init(&erase_bonds_local);
|
||||
erase_bonds = erase_bonds_local;
|
||||
#else
|
||||
bool dummy_erase;
|
||||
buttons_leds_init(&dummy_erase);
|
||||
#endif
|
||||
|
||||
LOG_PRINTF("[5] PWR\r\n"); nrf_delay_ms(10);
|
||||
power_management_init();
|
||||
LOG_PRINTF("[6] BLE\r\n"); nrf_delay_ms(10);
|
||||
ble_stack_init();
|
||||
|
||||
/* Flash Storage - must be after BLE stack (SoftDevice required) */
|
||||
/* and before GAP params (to use loaded config for device name) */
|
||||
LOG_PRINTF("[6.5] FDS\r\n"); nrf_delay_ms(10);
|
||||
fs_storage_init();
|
||||
config_load();
|
||||
|
||||
LOG_PRINTF("[6.6] Config\r\n");
|
||||
load_device_configuration();
|
||||
|
||||
/* W25Q32 Flash - NOT initialized during boot
|
||||
* Initialize via BLE command after advertising starts
|
||||
* (부팅 시 SPIM + BSP 이벤트 충돌로 SYSTEM OFF 발생 방지) */
|
||||
|
||||
LOG_PRINTF("[7] GAP\r\n"); nrf_delay_ms(10);
|
||||
gap_params_init();
|
||||
gatt_init();
|
||||
services_init();
|
||||
LOG_PRINTF("[8] ADV\r\n"); nrf_delay_ms(10);
|
||||
advertising_init();
|
||||
conn_params_init();
|
||||
power_ctrl_timers_start();
|
||||
/* advertising_start() is invoked from power_ctrl.c after 5ms delay */
|
||||
|
||||
nrf_delay_ms(20);
|
||||
LOG_PRINTF("=== READY ===\r\n");
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* Main Loop: Idle State Handler
|
||||
*----------------------------------------------------------*/
|
||||
for (;;)
|
||||
{
|
||||
idle_state_handle();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user