1 /*!
2  * \file      board.c
3  *
4  * \brief     Target board general functions implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  * \endcode
18  *
19  * \author    Miguel Luis ( Semtech )
20  *
21  * \author    Gregory Cristian ( Semtech )
22  */
23 #include "stm32l4xx.h"
24 #include "utilities.h"
25 #include "gpio.h"
26 #include "adc.h"
27 #include "spi.h"
28 #include "i2c.h"
29 #include "uart.h"
30 #include "timer.h"
31 #include "sysIrqHandlers.h"
32 #include "board-config.h"
33 #include "lpm-board.h"
34 #include "rtc-board.h"
35 
36 #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
37     #include "sx126x-board.h"
38 #elif defined( LR1110MB1XXS )
39     #include "lr1110-board.h"
40 #elif defined( SX1272MB2DAS)
41     #include "sx1272-board.h"
42 #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
43     #include "sx1276-board.h"
44 #endif
45 #include "board.h"
46 
47 /*!
48  * Unique Devices IDs register set ( STM32L4xxx )
49  */
50 #define         ID1                                 ( 0x1FFF7590 )
51 #define         ID2                                 ( 0x1FFF7594 )
52 #define         ID3                                 ( 0x1FFF7594 )
53 
54 /*!
55  * LED GPIO pins objects
56  */
57 Gpio_t Led1;
58 Gpio_t Led2;
59 
60 /*
61  * MCU objects
62  */
63 Adc_t  Adc;
64 Uart_t Uart2;
65 
66 #if defined( LR1110MB1XXS )
67     extern lr1110_t LR1110;
68 #endif
69 
70 /*!
71  * Initializes the unused GPIO to a know status
72  */
73 static void BoardUnusedIoInit( void );
74 
75 /*!
76  * Initializes FLASH memory operations for EEPROM_Emul package
77  */
78 static void InitFlashMemoryOperations( void );
79 
80 /*!
81  * System Clock Configuration
82  */
83 static void SystemClockConfig( void );
84 
85 /*!
86  * System Clock Re-Configuration when waking up from STOP mode
87  */
88 static void SystemClockReConfig( void );
89 
90 /*!
91  * Flag to indicate if the MCU is Initialized
92  */
93 static bool McuInitialized = false;
94 
95 /*!
96  * Flag used to indicate if board is powered from the USB
97  */
98 static bool UsbIsConnected = false;
99 
100 /*!
101  * UART2 FIFO buffers size
102  */
103 #define UART2_FIFO_TX_SIZE                                1024
104 #define UART2_FIFO_RX_SIZE                                1024
105 
106 uint8_t Uart2TxBuffer[UART2_FIFO_TX_SIZE];
107 uint8_t Uart2RxBuffer[UART2_FIFO_RX_SIZE];
108 
BoardCriticalSectionBegin(uint32_t * mask)109 void BoardCriticalSectionBegin( uint32_t *mask )
110 {
111     *mask = __get_PRIMASK( );
112     __disable_irq( );
113 }
114 
BoardCriticalSectionEnd(uint32_t * mask)115 void BoardCriticalSectionEnd( uint32_t *mask )
116 {
117     __set_PRIMASK( *mask );
118 }
119 
BoardInitPeriph(void)120 void BoardInitPeriph( void )
121 {
122 
123 }
124 
BoardInitMcu(void)125 void BoardInitMcu( void )
126 {
127     if( McuInitialized == false )
128     {
129         HAL_Init( );
130 
131         InitFlashMemoryOperations( );
132 
133         // LEDs
134         GpioInit( &Led1, LED_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
135         GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
136 
137         SystemClockConfig( );
138 
139         UsbIsConnected = true;
140 
141         FifoInit( &Uart2.FifoTx, Uart2TxBuffer, UART2_FIFO_TX_SIZE );
142         FifoInit( &Uart2.FifoRx, Uart2RxBuffer, UART2_FIFO_RX_SIZE );
143         // Configure your terminal for 8 Bits data (7 data bit + 1 parity bit), no parity and no flow ctrl
144         UartInit( &Uart2, UART_2, UART_TX, UART_RX );
145         UartConfig( &Uart2, RX_TX, 921600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
146 
147         RtcInit( );
148 
149         BoardUnusedIoInit( );
150         if( GetBoardPowerSource( ) == BATTERY_POWER )
151         {
152             // Disables OFF mode - Enables lowest power mode (STOP)
153             LpmSetOffMode( LPM_APPLI_ID, LPM_DISABLE );
154         }
155     }
156     else
157     {
158         SystemClockReConfig( );
159     }
160 
161     AdcInit( &Adc, NC );  // Just initialize ADC
162 
163 #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
164     SpiInit( &SX126x.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
165     SX126xIoInit( );
166 #elif defined( LR1110MB1XXS )
167     SpiInit( &LR1110.spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
168     lr1110_board_init_io( &LR1110 );
169 #elif defined( SX1272MB2DAS )
170     SpiInit( &SX1272.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
171     SX1272IoInit( );
172 #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
173     SpiInit( &SX1276.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
174     SX1276IoInit( );
175 #endif
176 
177     if( McuInitialized == false )
178     {
179         McuInitialized = true;
180 #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
181         SX126xIoDbgInit( );
182         // WARNING: If necessary the TCXO control is initialized by SX126xInit function.
183 #elif defined( LR1110MB1XXS )
184         lr1110_board_init_dbg_io( &LR1110 );
185         // WARNING: If necessary the TCXO control is initialized by SX126xInit function.
186 #elif defined( SX1272MB2DAS )
187         SX1272IoDbgInit( );
188         SX1272IoTcxoInit( );
189 #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
190         SX1276IoDbgInit( );
191         SX1276IoTcxoInit( );
192 #endif
193     }
194 }
195 
BoardResetMcu(void)196 void BoardResetMcu( void )
197 {
198     CRITICAL_SECTION_BEGIN( );
199 
200     //Restart system
201     NVIC_SystemReset( );
202 }
203 
BoardDeInitMcu(void)204 void BoardDeInitMcu( void )
205 {
206     AdcDeInit( &Adc );
207 
208 #if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
209     SpiDeInit( &SX126x.Spi );
210     SX126xIoDeInit( );
211 #elif defined( LR1110MB1XXS )
212     SpiDeInit( &LR1110.spi );
213     lr1110_board_deinit_io( &LR1110 );
214 #elif defined( SX1272MB2DAS )
215     SpiDeInit( &SX1272.Spi );
216     SX1272IoDeInit( );
217 #elif defined( SX1276MB1LAS ) || defined( SX1276MB1MAS )
218     SpiDeInit( &SX1276.Spi );
219     SX1276IoDeInit( );
220 #endif
221 }
222 
BoardGetRandomSeed(void)223 uint32_t BoardGetRandomSeed( void )
224 {
225     return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) );
226 }
227 
BoardGetUniqueId(uint8_t * id)228 void BoardGetUniqueId( uint8_t *id )
229 {
230     id[7] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 24;
231     id[6] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 16;
232     id[5] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 8;
233     id[4] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) );
234     id[3] = ( ( *( uint32_t* )ID2 ) ) >> 24;
235     id[2] = ( ( *( uint32_t* )ID2 ) ) >> 16;
236     id[1] = ( ( *( uint32_t* )ID2 ) ) >> 8;
237     id[0] = ( ( *( uint32_t* )ID2 ) );
238 }
239 
240 /*!
241  * Factory power supply
242  */
243 #define VDDA_VREFINT_CAL ( ( uint32_t ) 3000 )  // mV
244 
245 /*!
246  * VREF calibration value
247  */
248 #define VREFINT_CAL ( *( uint16_t* ) ( ( uint32_t ) 0x1FFF75AA ) )
249 
250 /*
251  * Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at
252  * a temperature of 110 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV).
253  */
254 #define TEMP30_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FFF75A8 ) )
255 
256 /* Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at
257  *a temperature of  30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
258 #define TEMP110_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FFF75CA ) )
259 
260 /* Vdda value with which temperature sensor has been calibrated in production
261    (+-10 mV). */
262 #define VDDA_TEMP_CAL ( ( uint32_t ) 3000 )
263 
264 /*!
265  * Battery thresholds
266  */
267 #define BATTERY_MAX_LEVEL 3000       // mV
268 #define BATTERY_MIN_LEVEL 2400       // mV
269 #define BATTERY_SHUTDOWN_LEVEL 2300  // mV
270 
271 #define BATTERY_LORAWAN_UNKNOWN_LEVEL 255
272 #define BATTERY_LORAWAN_MAX_LEVEL 254
273 #define BATTERY_LORAWAN_MIN_LEVEL 1
274 #define BATTERY_LORAWAN_EXT_PWR 0
275 
276 #define COMPUTE_TEMPERATURE( TS_ADC_DATA, VDDA_APPLI )                                                          \
277     ( ( ( ( ( ( ( int32_t )( ( TS_ADC_DATA * VDDA_APPLI ) / VDDA_TEMP_CAL ) - ( int32_t ) TEMP30_CAL_ADDR ) ) * \
278             ( int32_t )( 110 - 30 ) )                                                                           \
279           << 8 ) /                                                                                              \
280         ( int32_t )( TEMP110_CAL_ADDR - TEMP30_CAL_ADDR ) ) +                                                   \
281       ( 30 << 8 ) )
282 
283 static uint16_t BatteryVoltage = BATTERY_MAX_LEVEL;
284 
BoardBatteryMeasureVoltage(void)285 uint16_t BoardBatteryMeasureVoltage( void )
286 {
287     uint16_t vref = 0;
288 
289     // Read the current Voltage
290     vref = AdcReadChannel( &Adc, ADC_CHANNEL_VREFINT );
291 
292     // Compute and return the Voltage in millivolt
293     return ( ( ( uint32_t ) VDDA_VREFINT_CAL * VREFINT_CAL ) / vref );
294 }
295 
BoardGetBatteryVoltage(void)296 uint32_t BoardGetBatteryVoltage( void )
297 {
298     return BatteryVoltage;
299 }
300 
BoardGetBatteryLevel(void)301 uint8_t BoardGetBatteryLevel( void )
302 {
303     uint8_t batteryLevel = 0;
304 
305     BatteryVoltage = BoardBatteryMeasureVoltage( );
306 
307     if( GetBoardPowerSource( ) == USB_POWER )
308     {
309         batteryLevel = BATTERY_LORAWAN_EXT_PWR;
310     }
311     else
312     {
313         if( BatteryVoltage >= BATTERY_MAX_LEVEL )
314         {
315             batteryLevel = BATTERY_LORAWAN_MAX_LEVEL;
316         }
317         else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) )
318         {
319             batteryLevel =
320                 ( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1;
321         }
322         else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) )
323         {
324             batteryLevel = 1;
325         }
326         else  // if( BatteryVoltage <= BATTERY_SHUTDOWN_LEVEL )
327         {
328             batteryLevel = BATTERY_LORAWAN_UNKNOWN_LEVEL;
329         }
330     }
331     return batteryLevel;
332 }
333 
BoardGetTemperature(void)334 int16_t BoardGetTemperature( void )
335 {
336     uint16_t tempRaw = 0;
337 
338     BatteryVoltage = BoardBatteryMeasureVoltage( );
339 
340     tempRaw = AdcReadChannel( &Adc, ADC_CHANNEL_TEMPSENSOR );
341 
342     // Compute and return the temperature in degree celcius * 256
343     return ( int16_t ) COMPUTE_TEMPERATURE( tempRaw, BatteryVoltage );
344 }
345 
BoardUnusedIoInit(void)346 static void BoardUnusedIoInit( void )
347 {
348     HAL_DBGMCU_EnableDBGSleepMode( );
349     HAL_DBGMCU_EnableDBGStopMode( );
350     HAL_DBGMCU_EnableDBGStandbyMode( );
351 }
352 
SystemClockConfig(void)353 void SystemClockConfig( void )
354 {
355     RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
356     RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
357     RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
358 
359     __HAL_RCC_PWR_CLK_ENABLE( );
360 
361     __HAL_PWR_VOLTAGESCALING_CONFIG( PWR_REGULATOR_VOLTAGE_SCALE1 );
362 
363     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI | RCC_OSCILLATORTYPE_LSE;
364     RCC_OscInitStruct.MSIState            = RCC_MSI_ON;
365     RCC_OscInitStruct.LSEState            = RCC_LSE_ON;
366     RCC_OscInitStruct.MSIClockRange       = RCC_MSIRANGE_6;
367     RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
368     RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
369     RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_MSI;
370     RCC_OscInitStruct.PLL.PLLM            = 1;
371     RCC_OscInitStruct.PLL.PLLN            = 40;
372     RCC_OscInitStruct.PLL.PLLP            = RCC_PLLP_DIV7;
373     RCC_OscInitStruct.PLL.PLLQ            = RCC_PLLQ_DIV4;
374     RCC_OscInitStruct.PLL.PLLR            = RCC_PLLR_DIV2;
375     if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
376     {
377         assert_param( LMN_STATUS_ERROR );
378     }
379 
380     RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
381                                   RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
382     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
383     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
384     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
385     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
386     if( HAL_RCC_ClockConfig( &RCC_ClkInitStruct, FLASH_LATENCY_4 ) != HAL_OK )
387     {
388         assert_param( LMN_STATUS_ERROR );
389     }
390 
391     PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
392     PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
393     if( HAL_RCCEx_PeriphCLKConfig( &PeriphClkInit ) != HAL_OK )
394     {
395         assert_param( LMN_STATUS_ERROR );
396     }
397 
398     HAL_SYSTICK_Config( HAL_RCC_GetHCLKFreq( ) / 1000 );
399 
400     HAL_SYSTICK_CLKSourceConfig( SYSTICK_CLKSOURCE_HCLK );
401 
402     // SysTick_IRQn interrupt configuration
403     HAL_NVIC_SetPriority( SysTick_IRQn, 0, 0 );
404 }
405 
406 /*!
407  * \brief  Programmable Voltage Detector (PVD) Configuration
408  *         PVD set to level 6 for a threshold around 2.9V.
409  * \param  None
410  * \retval None
411  */
PVD_Config(void)412 static void PVD_Config( void )
413 {
414     PWR_PVDTypeDef sConfigPVD;
415     sConfigPVD.PVDLevel = PWR_PVDLEVEL_6;
416     sConfigPVD.Mode     = PWR_PVD_MODE_IT_RISING;
417     if( HAL_PWR_ConfigPVD( &sConfigPVD ) != HAL_OK )
418     {
419         assert_param( LMN_STATUS_ERROR );
420     }
421 
422     // Enable PVD
423     HAL_PWR_EnablePVD( );
424 
425     // Enable and set PVD Interrupt priority
426     HAL_NVIC_SetPriority( PVD_PVM_IRQn, 0, 0 );
427     HAL_NVIC_EnableIRQ( PVD_PVM_IRQn );
428 }
429 
430 /*!
431  * \brief Initializes the EEPROM emulation module.
432  *
433  * \remark This function is defined in eeprom-board.c file
434  */
435 void EepromMcuInit( void );
436 
InitFlashMemoryOperations(void)437 static void InitFlashMemoryOperations( void )
438 {
439     // Enable and set FLASH Interrupt priority
440     // FLASH interrupt is used for the purpose of pages clean up under interrupt
441     HAL_NVIC_SetPriority( FLASH_IRQn, 0, 0 );
442     HAL_NVIC_EnableIRQ( FLASH_IRQn );
443 
444     // Unlock the Flash Program Erase controller
445     HAL_FLASH_Unlock( );
446 
447 #if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
448     // Clear OPTVERR bit and PEMPTY flag if set
449     if( __HAL_FLASH_GET_FLAG( FLASH_FLAG_OPTVERR ) != RESET )
450     {
451         __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_OPTVERR );
452     }
453 
454     if( __HAL_FLASH_GET_FLAG( FLASH_FLAG_PEMPTY ) != RESET )
455     {
456         __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_PEMPTY );
457     }
458 #endif /* defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) */
459 
460     // Enable Power Control clock
461     __HAL_RCC_PWR_CLK_ENABLE();
462 #if defined (USE_STM32L4XX_NUCLEO_144)
463     HAL_PWR_DisableWakeUpPin( PWR_WAKEUP_PIN2 );
464 #endif /* defined (USE_STM32L4XX_NUCLEO_144) */
465 
466     // Configure Programmable Voltage Detector (PVD) (optional)
467     // PVD interrupt is used to suspend the current application flow in case
468     // a power-down is detected, allowing the flash interface to finish any
469     // ongoing operation before a reset is triggered.
470     PVD_Config( );
471 
472     // Initialize the EEPROM emulation driver
473     EepromMcuInit( );
474 
475     // Lock the Flash Program Erase controller
476     HAL_FLASH_Lock( );
477 }
478 
SystemClockReConfig(void)479 void SystemClockReConfig( void )
480 {
481       RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
482       RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
483       uint32_t pFLatency = 0;
484 
485     CRITICAL_SECTION_BEGIN( );
486 
487     // In case nvic had a pending IT, the arm doesn't enter stop mode
488     // Hence the pll is not switched off and will cause HAL_RCC_OscConfig return
489     // an error
490     if ( __HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL )
491     {
492         // Enable Power Control clock
493         __HAL_RCC_PWR_CLK_ENABLE( );
494 
495         // Get the Oscillators configuration according to the internal RCC registers */
496         HAL_RCC_GetOscConfig( &RCC_OscInitStruct );
497 
498         // Enable PLL
499         RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_NONE;
500         RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
501         if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
502         {
503             while( 1 );
504         }
505 
506         /* Get the Clocks configuration according to the internal RCC registers */
507         HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
508 
509         /* Select PLL as system clock source and keep HCLK, PCLK1 and PCLK2 clocks dividers as before */
510         RCC_ClkInitStruct.ClockType     = RCC_CLOCKTYPE_SYSCLK;
511         RCC_ClkInitStruct.SYSCLKSource  = RCC_SYSCLKSOURCE_PLLCLK;
512         if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK)
513         {
514             while(1);
515         }
516     }
517     else
518     {
519         // MCU did not enter stop mode beacuse NVIC had a pending IT
520     }
521 
522     CRITICAL_SECTION_END( );
523 }
524 
SysTick_Handler(void)525 void SysTick_Handler( void )
526 {
527     HAL_IncTick( );
528     HAL_SYSTICK_IRQHandler( );
529 }
530 
GetBoardPowerSource(void)531 uint8_t GetBoardPowerSource( void )
532 {
533     if( UsbIsConnected == false )
534     {
535         return BATTERY_POWER;
536     }
537     else
538     {
539         return USB_POWER;
540     }
541 }
542 
543 /**
544   * \brief Enters Low Power Stop Mode
545   *
546   * \note ARM exists the function when waking up
547   */
LpmEnterStopMode(void)548 void LpmEnterStopMode( void)
549 {
550     CRITICAL_SECTION_BEGIN( );
551 
552     BoardDeInitMcu( );
553 
554     CRITICAL_SECTION_END( );
555 
556     // Enter Stop Mode
557     HAL_PWR_EnterSTOPMode( PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI );
558 }
559 
560 /*!
561  * \brief Exists Low Power Stop Mode
562  */
LpmExitStopMode(void)563 void LpmExitStopMode( void )
564 {
565     // Disable IRQ while the MCU is not running on HSI
566     CRITICAL_SECTION_BEGIN( );
567 
568     // Initilizes the peripherals
569     BoardInitMcu( );
570 
571     CRITICAL_SECTION_END( );
572 }
573 
574 /*!
575  * \brief Enters Low Power Sleep Mode
576  *
577  * \note ARM exits the function when waking up
578  */
LpmEnterSleepMode(void)579 void LpmEnterSleepMode( void)
580 {
581     HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
582 }
583 
584 /*!
585  * \brief Indicates if an erasing operation is on going.
586  *
587  * \remark This function is defined in eeprom-board.c file
588  *
589  * \retval isEradingOnGoing Returns true is an erasing operation is on going.
590  */
591 bool EepromMcuIsErasingOnGoing( void );
592 
BoardLowPowerHandler(void)593 void BoardLowPowerHandler( void )
594 {
595     // Wait for any cleanup to complete before entering standby/shutdown mode
596     while( EepromMcuIsErasingOnGoing( ) == true ){ }
597 
598     __disable_irq( );
599     /*!
600      * If an interrupt has occurred after __disable_irq( ), it is kept pending
601      * and cortex will not enter low power anyway
602      */
603 
604     LpmEnterLowPower( );
605 
606     __enable_irq( );
607 }
608 
609 #if !defined ( __CC_ARM )
610 
611 /*
612  * Function to be used by stdout for printf etc
613  */
_write(int fd,const void * buf,size_t count)614 int _write( int fd, const void *buf, size_t count )
615 {
616     while( UartPutBuffer( &Uart2, ( uint8_t* )buf, ( uint16_t )count ) != 0 ){ };
617     return count;
618 }
619 
620 /*
621  * Function to be used by stdin for scanf etc
622  */
_read(int fd,const void * buf,size_t count)623 int _read( int fd, const void *buf, size_t count )
624 {
625     size_t bytesRead = 0;
626     while( UartGetBuffer( &Uart2, ( uint8_t* )buf, count, ( uint16_t* )&bytesRead ) != 0 ){ };
627     // Echo back the character
628     while( UartPutBuffer( &Uart2, ( uint8_t* )buf, ( uint16_t )bytesRead ) != 0 ){ };
629     return bytesRead;
630 }
631 
632 #else
633 
634 #include <stdio.h>
635 
636 // Keil compiler
fputc(int c,FILE * stream)637 int fputc( int c, FILE *stream )
638 {
639     while( UartPutChar( &Uart2, ( uint8_t )c ) != 0 );
640     return c;
641 }
642 
fgetc(FILE * stream)643 int fgetc( FILE *stream )
644 {
645     uint8_t c = 0;
646     while( UartGetChar( &Uart2, &c ) != 0 );
647     // Echo back the character
648     while( UartPutChar( &Uart2, c ) != 0 );
649     return ( int )c;
650 }
651 
652 #endif
653 
654 #ifdef USE_FULL_ASSERT
655 
656 #include <stdio.h>
657 
658 /*
659  * Function Name  : assert_failed
660  * Description    : Reports the name of the source file and the source line number
661  *                  where the assert_param error has occurred.
662  * Input          : - file: pointer to the source file name
663  *                  - line: assert_param error line source number
664  * Output         : None
665  * Return         : None
666  */
assert_failed(uint8_t * file,uint32_t line)667 void assert_failed( uint8_t* file, uint32_t line )
668 {
669     /* User can add his own implementation to report the file name and line number,
670      ex: printf("Wrong parameters value: file %s on line %lu\n", file, line) */
671 
672     printf( "Wrong parameters value: file %s on line %lu\n", ( const char* )file, line );
673     /* Infinite loop */
674     while( 1 )
675     {
676     }
677 }
678 #endif
679