|
- /*!
- * \file board.c
- *
- * \brief Target board general functions implementation
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013-2017 Semtech
- *
- * \endcode
- *
- * \author Miguel Luis ( Semtech )
- *
- * \author Gregory Cristian ( Semtech )
- */
- #include "stm32l1xx.h"
- #include "utilities.h"
- #include "gpio.h"
- #include "adc.h"
- #include "spi.h"
- #include "i2c.h"
- #include "uart.h"
- #include "timer.h"
- #include "sysIrqHandlers.h"
- #include "board-config.h"
- #include "lpm-board.h"
- #include "rtc-board.h"
-
- #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
- #include "sx126x-board.h"
- #elif defined( LR1110MB1XXS )
- #include "lr1110-board.h"
- #elif defined( SX1272MB2DAS)
- #include "sx1272-board.h"
- #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
- #include "sx1276-board.h"
- #endif
- #include "board.h"
-
- #include <sysinit.h>
-
- #include <usb_device.h>
-
- /*!
- * Unique Devices IDs register set ( STM32L152x )
- */
- #define ID1 ( 0x1FF800D0 )
- #define ID2 ( 0x1FF800D4 )
- #define ID3 ( 0x1FF800E4 )
-
- /*!
- * LED GPIO pins objects
- */
- Gpio_t Led1;
- Gpio_t Led2;
-
- /*
- * MCU objects
- */
- Adc_t Adc;
- Uart_t Uart2;
-
- #if defined( LR1110MB1XXS )
- extern lr1110_t LR1110;
- #endif
-
- /*!
- * Initializes the unused GPIO to a know status
- */
- static void BoardUnusedIoInit( void );
-
- /*!
- * System Clock Configuration
- */
- static void SystemClockConfig( void );
-
- /*!
- * System Clock Re-Configuration when waking up from STOP mode
- */
- static void SystemClockReConfig( void );
-
- /*!
- * Flag to indicate if the MCU is Initialized
- */
- static bool McuInitialized = false;
-
- /*!
- * Flag used to indicate if board is powered from the USB
- */
- static bool UsbIsConnected = false;
-
- /*!
- * UART2 FIFO buffers size
- */
- #define UART2_FIFO_TX_SIZE 1024
- #define UART2_FIFO_RX_SIZE 1024
-
- uint8_t Uart2TxBuffer[UART2_FIFO_TX_SIZE];
- uint8_t Uart2RxBuffer[UART2_FIFO_RX_SIZE];
-
- void BoardCriticalSectionBegin( uint32_t *mask )
- {
- *mask = __get_PRIMASK( );
- __disable_irq( );
- }
-
- void BoardCriticalSectionEnd( uint32_t *mask )
- {
- __set_PRIMASK( *mask );
- }
-
- void BoardInitPeriph( void )
- {
-
- }
-
- void BoardInitMcu( void )
- {
- if( McuInitialized == false )
- {
- #if 0
- // LEDs
- GpioInit( &Led1, LED_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
- #else
- GPIO_InitTypeDef GPIO_InitStruct;
-
- __HAL_RCC_GPIOC_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3|GPIO_PIN_4, GPIO_PIN_RESET);
-
- /* configure PA3 and PA4 */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_3|GPIO_PIN_4,
- .Mode = GPIO_MODE_OUTPUT_PP,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- /* configure PB0, PB1, PB10 and PB11 */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11,
- .Mode = GPIO_MODE_INPUT,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
-
- /* configure PB8 */
- GPIO_InitStruct = (GPIO_InitTypeDef){
- .Pin = GPIO_PIN_8,
- .Mode = GPIO_MODE_OUTPUT_PP,
- .Pull = GPIO_NOPULL,
- .Speed = GPIO_SPEED_FREQ_LOW,
- };
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- #endif
-
- SystemClockConfig( );
-
- UsbIsConnected = true;
-
- FifoInit( &Uart2.FifoTx, Uart2TxBuffer, UART2_FIFO_TX_SIZE );
- FifoInit( &Uart2.FifoRx, Uart2RxBuffer, UART2_FIFO_RX_SIZE );
- // Configure your terminal for 8 Bits data (7 data bit + 1 parity bit), no parity and no flow ctrl
- UartInit( &Uart2, UART_2, UART_TX, UART_RX );
- UartConfig( &Uart2, RX_TX, 921600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
-
- RtcInit( );
-
- BoardUnusedIoInit( );
- if( GetBoardPowerSource( ) == BATTERY_POWER )
- {
- // Disables OFF mode - Enables lowest power mode (STOP)
- LpmSetOffMode( LPM_APPLI_ID, LPM_DISABLE );
- }
- }
- else
- {
- SystemClockReConfig( );
- }
-
- AdcInit( &Adc, PB_15 ); // Just initialize ADC
-
- /* setup routing */
- __HAL_RI_IOSWITCH_CLOSE(RI_IOSWITCH_CH21);
- __HAL_RI_SWITCHCONTROLMODE_ENABLE();
-
- #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
- SpiInit( &SX126x.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
- SX126xIoInit( );
- #elif defined( LR1110MB1XXS )
- SpiInit( &LR1110.spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
- lr1110_board_init_io( &LR1110 );
- #elif defined( SX1272MB2DAS )
- SpiInit( &SX1272.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
- SX1272IoInit( );
- #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
- SpiInit( &SX1276.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
- SX1276IoInit( );
- #endif
-
- if( McuInitialized == false )
- {
- McuInitialized = true;
- #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
- SX126xIoDbgInit( );
- // WARNING: If necessary the TCXO control is initialized by SX126xInit function.
- #elif defined( LR1110MB1XXS )
- lr1110_board_init_dbg_io( &LR1110 );
- // WARNING: If necessary the TCXO control is initialized by SX126xInit function.
- #elif defined( SX1272MB2DAS )
- SX1272IoDbgInit( );
- SX1272IoTcxoInit( );
- #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
- SX1276IoDbgInit( );
- SX1276IoTcxoInit( );
- #endif
- }
- }
- SYSINIT_VF(initmcu, SI_SUB_HAL, SI_ORDER_SECOND, BoardInitMcu);
-
- void BoardResetMcu( void )
- {
- CRITICAL_SECTION_BEGIN( );
-
- //Restart system
- NVIC_SystemReset( );
- }
-
- void BoardDeInitMcu( void )
- {
- AdcDeInit( &Adc );
-
- #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
- SpiDeInit( &SX126x.Spi );
- SX126xIoDeInit( );
- #elif defined( LR1110MB1XXS )
- SpiDeInit( &LR1110.spi );
- lr1110_board_deinit_io( &LR1110 );
- #elif defined( SX1272MB2DAS )
- SpiDeInit( &SX1272.Spi );
- SX1272IoDeInit( );
- #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
- SpiDeInit( &SX1276.Spi );
- SX1276IoDeInit( );
- #endif
- }
-
- uint32_t BoardGetRandomSeed( void )
- {
- return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) );
- }
-
- void BoardGetUniqueId( uint8_t *id )
- {
- id[7] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 24;
- id[6] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 16;
- id[5] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 8;
- id[4] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) );
- id[3] = ( ( *( uint32_t* )ID2 ) ) >> 24;
- id[2] = ( ( *( uint32_t* )ID2 ) ) >> 16;
- id[1] = ( ( *( uint32_t* )ID2 ) ) >> 8;
- id[0] = ( ( *( uint32_t* )ID2 ) );
- }
-
- /*!
- * Factory power supply
- */
- #define VDDA_VREFINT_CAL ( ( uint32_t ) 3000 ) // mV
-
- /*!
- * VREF calibration value
- */
- #define VREFINT_CAL ( *( uint16_t* ) ( ( uint32_t ) 0x1FF800F8 ) )
-
- /*
- * Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at
- * a temperature of 110 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV).
- */
- #define TEMP30_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007A ) )
-
- /* Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at
- *a temperature of 30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
- #define TEMP110_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007E ) )
-
- /* Vdda value with which temperature sensor has been calibrated in production
- (+-10 mV). */
- #define VDDA_TEMP_CAL ( ( uint32_t ) 3000 )
-
- /*!
- * Battery thresholds
- */
- #define BATTERY_MAX_LEVEL 3000 // mV
- #define BATTERY_MIN_LEVEL 2400 // mV
- #define BATTERY_SHUTDOWN_LEVEL 2300 // mV
-
- #define BATTERY_LORAWAN_UNKNOWN_LEVEL 255
- #define BATTERY_LORAWAN_MAX_LEVEL 254
- #define BATTERY_LORAWAN_MIN_LEVEL 1
- #define BATTERY_LORAWAN_EXT_PWR 0
-
- #define COMPUTE_TEMPERATURE( TS_ADC_DATA, VDDA_APPLI ) \
- ( ( ( ( ( ( ( int32_t )( ( TS_ADC_DATA * VDDA_APPLI ) / VDDA_TEMP_CAL ) - ( int32_t ) TEMP30_CAL_ADDR ) ) * \
- ( int32_t )( 110 - 30 ) ) \
- << 8 ) / \
- ( int32_t )( TEMP110_CAL_ADDR - TEMP30_CAL_ADDR ) ) + \
- ( 30 << 8 ) )
-
- static uint16_t BatteryVoltage = BATTERY_MAX_LEVEL;
-
- uint16_t BoardBatteryMeasureVoltage( void )
- {
- uint16_t vref = 0;
-
- // Read the current Voltage
- vref = AdcReadChannel( &Adc, ADC_CHANNEL_VREFINT );
-
- // Compute and return the Voltage in millivolt
- return ( ( ( uint32_t ) VDDA_VREFINT_CAL * VREFINT_CAL ) / vref );
- }
-
- uint32_t BoardGetBatteryVoltage( void )
- {
- return BatteryVoltage;
- }
-
- uint8_t BoardGetBatteryLevel( void )
- {
- uint8_t batteryLevel = 0;
-
- BatteryVoltage = BoardBatteryMeasureVoltage( );
-
- if( GetBoardPowerSource( ) == USB_POWER )
- {
- batteryLevel = BATTERY_LORAWAN_EXT_PWR;
- }
- else
- {
- if( BatteryVoltage >= BATTERY_MAX_LEVEL )
- {
- batteryLevel = BATTERY_LORAWAN_MAX_LEVEL;
- }
- else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) )
- {
- batteryLevel =
- ( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1;
- }
- else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) )
- {
- batteryLevel = 1;
- }
- else // if( BatteryVoltage <= BATTERY_SHUTDOWN_LEVEL )
- {
- batteryLevel = BATTERY_LORAWAN_UNKNOWN_LEVEL;
- }
- }
- return batteryLevel;
- }
-
- int16_t BoardGetTemperature( void )
- {
- uint16_t tempRaw = 0;
-
- BatteryVoltage = BoardBatteryMeasureVoltage( );
-
- tempRaw = AdcReadChannel( &Adc, ADC_CHANNEL_TEMPSENSOR );
-
- // Compute and return the temperature in degree celcius * 256
- return ( int16_t ) COMPUTE_TEMPERATURE( tempRaw, BatteryVoltage );
- }
-
- static void BoardUnusedIoInit( void )
- {
- HAL_DBGMCU_EnableDBGSleepMode( );
- HAL_DBGMCU_EnableDBGStopMode( );
- HAL_DBGMCU_EnableDBGStandbyMode( );
- }
-
- void SystemClockConfig( void )
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
- RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
- RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
-
- __HAL_RCC_PWR_CLK_ENABLE( );
-
- __HAL_PWR_VOLTAGESCALING_CONFIG( PWR_REGULATOR_VOLTAGE_SCALE1 );
-
- RCC_OscInitStruct = (RCC_OscInitTypeDef){
- .OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE,
- .HSEState = RCC_HSE_ON,
- .LSIState = RCC_LSI_ON,
- .PLL.PLLState = RCC_PLL_ON,
- .PLL.PLLSource = RCC_PLLSOURCE_HSE,
- .PLL.PLLMUL = RCC_PLL_MUL12,
- .PLL.PLLDIV = RCC_PLL_DIV3,
- };
- if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
- {
- assert_param( LMN_STATUS_ERROR );
- }
-
- RCC_ClkInitStruct = (RCC_ClkInitTypeDef){
- .ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2,
- .SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK,
- .AHBCLKDivider = RCC_SYSCLK_DIV1,
- .APB1CLKDivider = RCC_HCLK_DIV1,
- .APB2CLKDivider = RCC_HCLK_DIV1,
- };
- if( HAL_RCC_ClockConfig( &RCC_ClkInitStruct, FLASH_LATENCY_1 ) != HAL_OK )
- {
- assert_param( LMN_STATUS_ERROR );
- }
-
- PeriphClkInit = (RCC_PeriphCLKInitTypeDef){
- .PeriphClockSelection = RCC_PERIPHCLK_RTC,
- .RTCClockSelection = RCC_RTCCLKSOURCE_LSI,
- };
-
- if( HAL_RCCEx_PeriphCLKConfig( &PeriphClkInit ) != HAL_OK )
- {
- assert_param( LMN_STATUS_ERROR );
- }
-
- HAL_SYSTICK_Config( HAL_RCC_GetHCLKFreq( ) / 1000 );
-
- HAL_SYSTICK_CLKSourceConfig( SYSTICK_CLKSOURCE_HCLK );
-
- // SysTick_IRQn interrupt configuration
- HAL_NVIC_SetPriority( SysTick_IRQn, 0, 0 );
- }
-
- void SystemClockReConfig( void )
- {
- __HAL_RCC_PWR_CLK_ENABLE( );
- __HAL_PWR_VOLTAGESCALING_CONFIG( PWR_REGULATOR_VOLTAGE_SCALE1 );
-
- // Enable HSI
- __HAL_RCC_HSI_ENABLE( );
-
- // Wait till HSI is ready
- while( __HAL_RCC_GET_FLAG( RCC_FLAG_HSIRDY ) == RESET )
- {
- }
-
- // Enable PLL
- __HAL_RCC_PLL_ENABLE( );
-
- // Wait till PLL is ready
- while( __HAL_RCC_GET_FLAG( RCC_FLAG_PLLRDY ) == RESET )
- {
- }
-
- // Select PLL as system clock source
- __HAL_RCC_SYSCLK_CONFIG ( RCC_SYSCLKSOURCE_PLLCLK );
-
- // Wait till PLL is used as system clock source
- while( __HAL_RCC_GET_SYSCLK_SOURCE( ) != RCC_SYSCLKSOURCE_STATUS_PLLCLK )
- {
- }
- }
-
- uint8_t GetBoardPowerSource( void )
- {
- if( UsbIsConnected == false )
- {
- return BATTERY_POWER;
- }
- else
- {
- return USB_POWER;
- }
- }
-
- /**
- * \brief Enters Low Power Stop Mode
- *
- * \note ARM exists the function when waking up
- */
- void LpmEnterStopMode( void)
- {
- CRITICAL_SECTION_BEGIN( );
-
- BoardDeInitMcu( );
-
- // Disable the Power Voltage Detector
- HAL_PWR_DisablePVD( );
-
- // Clear wake up flag
- SET_BIT( PWR->CR, PWR_CR_CWUF );
-
- // Enable Ultra low power mode
- HAL_PWREx_EnableUltraLowPower( );
-
- // Enable the fast wake up from Ultra low power mode
- HAL_PWREx_EnableFastWakeUp( );
-
- CRITICAL_SECTION_END( );
-
- // Enter Stop Mode
- HAL_PWR_EnterSTOPMode( PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI );
- }
-
- /*!
- * \brief Exists Low Power Stop Mode
- */
- void LpmExitStopMode( void )
- {
- // Disable IRQ while the MCU is not running on HSI
- CRITICAL_SECTION_BEGIN( );
-
- // Initilizes the peripherals
- BoardInitMcu( );
-
- CRITICAL_SECTION_END( );
- }
-
- /*!
- * \brief Enters Low Power Sleep Mode
- *
- * \note ARM exits the function when waking up
- */
- void LpmEnterSleepMode( void)
- {
- HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
- }
-
- void BoardLowPowerHandler( void )
- {
- __disable_irq( );
- /*!
- * If an interrupt has occurred after __disable_irq( ), it is kept pending
- * and cortex will not enter low power anyway
- */
-
- LpmEnterLowPower( );
-
- __enable_irq( );
- }
-
- #if !defined ( __CC_ARM )
-
- /*
- * Function to be used by stdout for printf etc
- */
- int _write( int fd, const void *buf, size_t count )
- {
- while( UartPutBuffer( &Uart2, ( uint8_t* )buf, ( uint16_t )count ) != 0 ){ };
- return count;
- }
-
- /*
- * Function to be used by stdin for scanf etc
- */
- int _read( int fd, const void *buf, size_t count )
- {
- size_t bytesRead = 0;
- while( UartGetBuffer( &Uart2, ( uint8_t* )buf, count, ( uint16_t* )&bytesRead ) != 0 ){ };
- // Echo back the character
- while( UartPutBuffer( &Uart2, ( uint8_t* )buf, ( uint16_t )bytesRead ) != 0 ){ };
- return bytesRead;
- }
-
- #else
-
- #include <stdio.h>
-
- // Keil compiler
- int fputc( int c, FILE *stream )
- {
- while( UartPutChar( &Uart2, ( uint8_t )c ) != 0 );
- return c;
- }
-
- int fgetc( FILE *stream )
- {
- uint8_t c = 0;
- while( UartGetChar( &Uart2, &c ) != 0 );
- // Echo back the character
- while( UartPutChar( &Uart2, c ) != 0 );
- return ( int )c;
- }
-
- #endif
-
- #ifdef USE_FULL_ASSERT
-
- #include <stdio.h>
-
- /*
- * Function Name : assert_failed
- * Description : Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * Input : - file: pointer to the source file name
- * - line: assert_param error line source number
- * Output : None
- * Return : None
- */
- void assert_failed( uint8_t* file, uint32_t line )
- {
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %lu\n", file, line) */
-
- printf( "Wrong parameters value: file %s on line %lu\n", ( const char* )file, line );
- /* Infinite loop */
- while( 1 )
- {
- }
- }
- #endif
|