Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

572 lines
14 KiB

  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. * \author Andreas Pella ( IMST GmbH )
  24. */
  25. #include "stm32l1xx.h"
  26. #include "utilities.h"
  27. #include "gpio.h"
  28. #include "adc.h"
  29. #include "spi.h"
  30. #include "i2c.h"
  31. #include "uart.h"
  32. #include "timer.h"
  33. #include "sysIrqHandlers.h"
  34. #include "board-config.h"
  35. #include "lpm-board.h"
  36. #include "rtc-board.h"
  37. #include "sx1272-board.h"
  38. #include "board.h"
  39. /*!
  40. * Unique Devices IDs register set ( STM32L1xxx )
  41. */
  42. #define ID1 ( 0x1FF80050 )
  43. #define ID2 ( 0x1FF80054 )
  44. #define ID3 ( 0x1FF80064 )
  45. /*!
  46. * LED GPIO pins objects
  47. */
  48. #if ( USE_POTENTIOMETER == 0 )
  49. Gpio_t Led1;
  50. #endif
  51. Gpio_t Led2;
  52. Gpio_t Led3;
  53. Gpio_t Led4;
  54. /*
  55. * MCU objects
  56. */
  57. Adc_t Adc;
  58. I2c_t I2c;
  59. Uart_t Uart1;
  60. /*!
  61. * Initializes the unused GPIO to a know status
  62. */
  63. static void BoardUnusedIoInit( void );
  64. /*!
  65. * System Clock Configuration
  66. */
  67. static void SystemClockConfig( void );
  68. /*!
  69. * System Clock Re-Configuration when waking up from STOP mode
  70. */
  71. static void SystemClockReConfig( void );
  72. /*!
  73. * Flag to indicate if the MCU is Initialized
  74. */
  75. static bool McuInitialized = false;
  76. /*!
  77. * UART2 FIFO buffers size
  78. */
  79. #define UART1_FIFO_TX_SIZE 1024
  80. #define UART1_FIFO_RX_SIZE 1024
  81. uint8_t Uart1TxBuffer[UART1_FIFO_TX_SIZE];
  82. uint8_t Uart1RxBuffer[UART1_FIFO_RX_SIZE];
  83. void BoardCriticalSectionBegin( uint32_t *mask )
  84. {
  85. *mask = __get_PRIMASK( );
  86. __disable_irq( );
  87. }
  88. void BoardCriticalSectionEnd( uint32_t *mask )
  89. {
  90. __set_PRIMASK( *mask );
  91. }
  92. void BoardInitPeriph( void )
  93. {
  94. }
  95. void BoardInitMcu( void )
  96. {
  97. if( McuInitialized == false )
  98. {
  99. HAL_Init( );
  100. // LEDs
  101. #if ( USE_POTENTIOMETER == 0 )
  102. GpioInit( &Led1, LED_1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  103. #endif
  104. GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  105. GpioInit( &Led3, LED_3, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  106. GpioInit( &Led4, LED_4, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  107. SystemClockConfig( );
  108. FifoInit( &Uart1.FifoTx, Uart1TxBuffer, UART1_FIFO_TX_SIZE );
  109. FifoInit( &Uart1.FifoRx, Uart1RxBuffer, UART1_FIFO_RX_SIZE );
  110. // Configure your terminal for 8 Bits data (7 data bit + 1 parity bit), no parity and no flow ctrl
  111. UartInit( &Uart1, UART_1, UART_TX, UART_RX );
  112. UartConfig( &Uart1, RX_TX, 921600, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL );
  113. RtcInit( );
  114. // Switch LED 1, 2, 3, 4 OFF
  115. #if ( USE_POTENTIOMETER == 0 )
  116. GpioWrite( &Led1, 0 );
  117. #endif
  118. GpioWrite( &Led2, 0 );
  119. GpioWrite( &Led3, 0 );
  120. GpioWrite( &Led4, 0 );
  121. BoardUnusedIoInit( );
  122. if( GetBoardPowerSource( ) == BATTERY_POWER )
  123. {
  124. // Disables OFF mode - Enables lowest power mode (STOP)
  125. LpmSetOffMode( LPM_APPLI_ID, LPM_DISABLE );
  126. }
  127. }
  128. else
  129. {
  130. SystemClockReConfig( );
  131. }
  132. AdcInit( &Adc, POTI );
  133. SpiInit( &SX1272.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
  134. SX1272IoInit( );
  135. if( McuInitialized == false )
  136. {
  137. McuInitialized = true;
  138. SX1272IoDbgInit( );
  139. SX1272IoTcxoInit( );
  140. }
  141. }
  142. void BoardResetMcu( void )
  143. {
  144. CRITICAL_SECTION_BEGIN( );
  145. //Restart system
  146. NVIC_SystemReset( );
  147. }
  148. void BoardDeInitMcu( void )
  149. {
  150. Gpio_t ioPin;
  151. AdcDeInit( &Adc );
  152. SpiDeInit( &SX1272.Spi );
  153. SX1272IoDeInit( );
  154. GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  155. GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
  156. GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 );
  157. GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 );
  158. }
  159. uint32_t BoardGetRandomSeed( void )
  160. {
  161. return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) );
  162. }
  163. void BoardGetUniqueId( uint8_t *id )
  164. {
  165. id[7] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 24;
  166. id[6] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 16;
  167. id[5] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) ) >> 8;
  168. id[4] = ( ( *( uint32_t* )ID1 )+ ( *( uint32_t* )ID3 ) );
  169. id[3] = ( ( *( uint32_t* )ID2 ) ) >> 24;
  170. id[2] = ( ( *( uint32_t* )ID2 ) ) >> 16;
  171. id[1] = ( ( *( uint32_t* )ID2 ) ) >> 8;
  172. id[0] = ( ( *( uint32_t* )ID2 ) );
  173. }
  174. /*!
  175. * Potentiometer max and min levels definition
  176. */
  177. #define POTI_MAX_LEVEL 900
  178. #define POTI_MIN_LEVEL 10
  179. uint8_t BoardGetPotiLevel( void )
  180. {
  181. uint8_t potiLevel = 0;
  182. uint16_t vpoti = 0;
  183. // Read the current potentiometer setting
  184. vpoti = AdcReadChannel( &Adc , ADC_CHANNEL_3 );
  185. // check the limits
  186. if( vpoti >= POTI_MAX_LEVEL )
  187. {
  188. potiLevel = 100;
  189. }
  190. else if( vpoti <= POTI_MIN_LEVEL )
  191. {
  192. potiLevel = 0;
  193. }
  194. else
  195. {
  196. // if the value is in the area, calculate the percentage value
  197. potiLevel = ( ( vpoti - POTI_MIN_LEVEL ) * 100 ) / POTI_MAX_LEVEL;
  198. }
  199. return potiLevel;
  200. }
  201. /*!
  202. * Factory power supply
  203. */
  204. #define FACTORY_POWER_SUPPLY 3300 // mV
  205. /*!
  206. * VREF calibration value
  207. */
  208. #define VREFINT_CAL ( *( uint16_t* )0x1FF800F8U )
  209. /*!
  210. * ADC maximum value
  211. */
  212. #define ADC_MAX_VALUE 4095
  213. /*!
  214. * VREF bandgap value
  215. */
  216. #define ADC_VREF_BANDGAP 1224 // mV
  217. /*!
  218. * Battery thresholds
  219. */
  220. #define BATTERY_MAX_LEVEL 3000 // mV
  221. #define BATTERY_MIN_LEVEL 2400 // mV
  222. #define BATTERY_SHUTDOWN_LEVEL 2300 // mV
  223. static uint16_t BatteryVoltage = BATTERY_MAX_LEVEL;
  224. uint16_t BoardBatteryMeasureVoltage( void )
  225. {
  226. uint16_t vref = 0;
  227. uint32_t batteryVoltage = 0;
  228. // Read the current Voltage
  229. vref = AdcReadChannel( &Adc , ADC_CHANNEL_17 );
  230. // We don't use the VREF from calibValues here.
  231. // calculate the Voltage in millivolt
  232. batteryVoltage = ( uint32_t )ADC_VREF_BANDGAP * ( uint32_t )ADC_MAX_VALUE;
  233. batteryVoltage = batteryVoltage / ( uint32_t )vref;
  234. return batteryVoltage;
  235. }
  236. uint32_t BoardGetBatteryVoltage( void )
  237. {
  238. return BatteryVoltage;
  239. }
  240. uint8_t BoardGetBatteryLevel( void )
  241. {
  242. uint8_t batteryLevel = 0;
  243. BatteryVoltage = BoardBatteryMeasureVoltage( );
  244. if( GetBoardPowerSource( ) == USB_POWER )
  245. {
  246. batteryLevel = 0;
  247. }
  248. else
  249. {
  250. if( BatteryVoltage >= BATTERY_MAX_LEVEL )
  251. {
  252. batteryLevel = 254;
  253. }
  254. else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) )
  255. {
  256. batteryLevel = ( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1;
  257. }
  258. else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) )
  259. {
  260. batteryLevel = 1;
  261. }
  262. else //if( BatteryVoltage <= BATTERY_SHUTDOWN_LEVEL )
  263. {
  264. batteryLevel = 255;
  265. }
  266. }
  267. return batteryLevel;
  268. }
  269. static void BoardUnusedIoInit( void )
  270. {
  271. Gpio_t ioPin;
  272. if( GetBoardPowerSource( ) == BATTERY_POWER )
  273. {
  274. GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  275. GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  276. }
  277. #if defined( USE_DEBUGGER )
  278. HAL_DBGMCU_EnableDBGSleepMode( );
  279. HAL_DBGMCU_EnableDBGStopMode( );
  280. HAL_DBGMCU_EnableDBGStandbyMode( );
  281. #else
  282. HAL_DBGMCU_DisableDBGSleepMode( );
  283. HAL_DBGMCU_DisableDBGStopMode( );
  284. HAL_DBGMCU_DisableDBGStandbyMode( );
  285. GpioInit( &ioPin, JTAG_TMS, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  286. GpioInit( &ioPin, JTAG_TCK, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  287. GpioInit( &ioPin, JTAG_TDI, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  288. GpioInit( &ioPin, JTAG_TDO, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  289. GpioInit( &ioPin, JTAG_NRST, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
  290. #endif
  291. }
  292. void SystemClockConfig( void )
  293. {
  294. RCC_OscInitTypeDef RCC_OscInitStruct;
  295. RCC_ClkInitTypeDef RCC_ClkInitStruct;
  296. RCC_PeriphCLKInitTypeDef PeriphClkInit;
  297. __HAL_RCC_PWR_CLK_ENABLE( );
  298. __HAL_PWR_VOLTAGESCALING_CONFIG( PWR_REGULATOR_VOLTAGE_SCALE1 );
  299. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSE;
  300. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  301. RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  302. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  303. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  304. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
  305. RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3;
  306. if( HAL_RCC_OscConfig( &RCC_OscInitStruct ) != HAL_OK )
  307. {
  308. assert_param( LMN_STATUS_ERROR );
  309. }
  310. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
  311. RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  312. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  313. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  314. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  315. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  316. if( HAL_RCC_ClockConfig( &RCC_ClkInitStruct, FLASH_LATENCY_1 ) != HAL_OK )
  317. {
  318. assert_param( LMN_STATUS_ERROR );
  319. }
  320. PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  321. PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
  322. if( HAL_RCCEx_PeriphCLKConfig( &PeriphClkInit ) != HAL_OK )
  323. {
  324. assert_param( LMN_STATUS_ERROR );
  325. }
  326. HAL_SYSTICK_Config( HAL_RCC_GetHCLKFreq( ) / 1000 );
  327. HAL_SYSTICK_CLKSourceConfig( SYSTICK_CLKSOURCE_HCLK );
  328. // SysTick_IRQn interrupt configuration
  329. HAL_NVIC_SetPriority( SysTick_IRQn, 0, 0 );
  330. }
  331. void SystemClockReConfig( void )
  332. {
  333. __HAL_RCC_PWR_CLK_ENABLE( );
  334. __HAL_PWR_VOLTAGESCALING_CONFIG( PWR_REGULATOR_VOLTAGE_SCALE1 );
  335. // Enable HSE
  336. __HAL_RCC_HSE_CONFIG( RCC_HSE_ON );
  337. // Wait till HSE is ready
  338. while( __HAL_RCC_GET_FLAG( RCC_FLAG_HSERDY ) == RESET )
  339. {
  340. }
  341. // Enable PLL
  342. __HAL_RCC_PLL_ENABLE( );
  343. // Wait till PLL is ready
  344. while( __HAL_RCC_GET_FLAG( RCC_FLAG_PLLRDY ) == RESET )
  345. {
  346. }
  347. // Select PLL as system clock source
  348. __HAL_RCC_SYSCLK_CONFIG ( RCC_SYSCLKSOURCE_PLLCLK );
  349. // Wait till PLL is used as system clock source
  350. while( __HAL_RCC_GET_SYSCLK_SOURCE( ) != RCC_SYSCLKSOURCE_STATUS_PLLCLK )
  351. {
  352. }
  353. }
  354. void SysTick_Handler( void )
  355. {
  356. HAL_IncTick( );
  357. HAL_SYSTICK_IRQHandler( );
  358. }
  359. uint8_t GetBoardPowerSource( void )
  360. {
  361. return USB_POWER;
  362. }
  363. /**
  364. * \brief Enters Low Power Stop Mode
  365. *
  366. * \note ARM exists the function when waking up
  367. */
  368. void LpmEnterStopMode( void)
  369. {
  370. CRITICAL_SECTION_BEGIN( );
  371. BoardDeInitMcu( );
  372. // Disable the Power Voltage Detector
  373. HAL_PWR_DisablePVD( );
  374. // Clear wake up flag
  375. SET_BIT( PWR->CR, PWR_CR_CWUF );
  376. // Enable Ultra low power mode
  377. HAL_PWREx_EnableUltraLowPower( );
  378. // Enable the fast wake up from Ultra low power mode
  379. HAL_PWREx_EnableFastWakeUp( );
  380. CRITICAL_SECTION_END( );
  381. // Enter Stop Mode
  382. HAL_PWR_EnterSTOPMode( PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI );
  383. }
  384. /*!
  385. * \brief Exists Low Power Stop Mode
  386. */
  387. void LpmExitStopMode( void )
  388. {
  389. // Disable IRQ while the MCU is not running on HSI
  390. CRITICAL_SECTION_BEGIN( );
  391. // Initilizes the peripherals
  392. BoardInitMcu( );
  393. CRITICAL_SECTION_END( );
  394. }
  395. /*!
  396. * \brief Enters Low Power Sleep Mode
  397. *
  398. * \note ARM exits the function when waking up
  399. */
  400. void LpmEnterSleepMode( void)
  401. {
  402. HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
  403. }
  404. void BoardLowPowerHandler( void )
  405. {
  406. __disable_irq( );
  407. /*!
  408. * If an interrupt has occurred after __disable_irq( ), it is kept pending
  409. * and cortex will not enter low power anyway
  410. */
  411. LpmEnterLowPower( );
  412. __enable_irq( );
  413. }
  414. #if !defined ( __CC_ARM )
  415. /*
  416. * Function to be used by stdout for printf etc
  417. */
  418. int _write( int fd, const void *buf, size_t count )
  419. {
  420. while( UartPutBuffer( &Uart1, ( uint8_t* )buf, ( uint16_t )count ) != 0 ){ };
  421. return count;
  422. }
  423. /*
  424. * Function to be used by stdin for scanf etc
  425. */
  426. int _read( int fd, const void *buf, size_t count )
  427. {
  428. size_t bytesRead = 0;
  429. while( UartGetBuffer( &Uart1, ( uint8_t* )buf, count, ( uint16_t* )&bytesRead ) != 0 ){ };
  430. // Echo back the character
  431. while( UartPutBuffer( &Uart1, ( uint8_t* )buf, ( uint16_t )bytesRead ) != 0 ){ };
  432. return bytesRead;
  433. }
  434. #else
  435. #include <stdio.h>
  436. // Keil compiler
  437. int fputc( int c, FILE *stream )
  438. {
  439. while( UartPutChar( &Uart1, ( uint8_t )c ) != 0 );
  440. return c;
  441. }
  442. int fgetc( FILE *stream )
  443. {
  444. uint8_t c = 0;
  445. while( UartGetChar( &Uart1, &c ) != 0 );
  446. // Echo back the character
  447. while( UartPutChar( &Uart1, c ) != 0 );
  448. return ( int )c;
  449. }
  450. #endif
  451. #ifdef USE_FULL_ASSERT
  452. #include <stdio.h>
  453. /*
  454. * Function Name : assert_failed
  455. * Description : Reports the name of the source file and the source line number
  456. * where the assert_param error has occurred.
  457. * Input : - file: pointer to the source file name
  458. * - line: assert_param error line source number
  459. * Output : None
  460. * Return : None
  461. */
  462. void assert_failed( uint8_t* file, uint32_t line )
  463. {
  464. /* User can add his own implementation to report the file name and line number,
  465. ex: printf("Wrong parameters value: file %s on line %lu\n", file, line) */
  466. printf( "Wrong parameters value: file %s on line %lu\n", ( const char* )file, line );
  467. /* Infinite loop */
  468. while( 1 )
  469. {
  470. }
  471. }
  472. #endif