xref: /btstack/port/stm32-wb55xx-nucleo-freertos/Src/main.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
1 /*
2  * Copyright (C) 2019 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 /*
39  *  Made for BlueKitchen by OneWave with <3
40  *      Author: [email protected]
41  */
42 
43 #define BTSTACK_FILE__ "main.c"
44 
45 #include <stdio.h>
46 
47 #include "main.h"
48 #include "otp.h"
49 #include "app_conf.h"
50 
51 #include "FreeRTOS.h"
52 #include "task.h"
53 
54 UART_HandleTypeDef hTuart     = { 0 };
55 static RTC_HandleTypeDef hrtc = { 0 };
56 
57 TaskHandle_t hbtstack_task;
58 
59 static void SystemClock_Config(void);
60 static void PeriphClock_Config(void);
61 static void Tune_HSE( void );
62 static void Init_Exti( void );
63 static void Init_UART( void );
64 static void Init_RTC( void );
65 
66 
Error_Handler(void)67 static void Error_Handler(void)
68 {
69     for(;;);
70 }
71 
Reset_BackupDomain(void)72 static void Reset_BackupDomain( void )
73 {
74     if ((LL_RCC_IsActiveFlag_PINRST() != 0) && (LL_RCC_IsActiveFlag_SFTRST() == 0))
75     {
76         HAL_PWR_EnableBkUpAccess(); /**< Enable access to the RTC registers */
77 
78         /**
79          *  Write twice the value to flush the APB-AHB bridge
80          *  This bit shall be written in the register before writing the next one
81          */
82         HAL_PWR_EnableBkUpAccess();
83 
84         __HAL_RCC_BACKUPRESET_FORCE();
85         __HAL_RCC_BACKUPRESET_RELEASE();
86     }
87 
88     return;
89 }
90 
91 
92 /**
93   * @brief  The application entry point.
94   * @retval int
95   */
96 void port_thread(void* args);
main(void)97 int main(void)
98 {
99 	/* Reset of all peripherals, initializes the Systick. */
100     HAL_Init();
101 
102     Reset_BackupDomain();
103 
104     Tune_HSE();
105 
106     SystemClock_Config();
107     PeriphClock_Config();
108 
109     /* Init debug */
110     Init_UART();
111 
112     Init_Exti();
113 
114     Init_RTC();
115 
116     xTaskCreate(port_thread, "btstack_thread", 2048, NULL, 1, &hbtstack_task);
117 
118     vTaskStartScheduler();
119 
120     /* We should never get here as control is now taken by the scheduler */
121     for(;;);
122 }
123 
124 /**
125   * @brief System Clock Configuration
126   * @retval None
127   */
SystemClock_Config(void)128 void SystemClock_Config(void)
129 {
130   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
131   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
132   RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
133 
134   /** Configure LSE Drive Capability
135   */
136   __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
137 
138   /** Configure the main internal regulator output voltage
139   */
140   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
141   /** Initializes the CPU, AHB and APB busses clocks
142   */
143   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI1
144                               |RCC_OSCILLATORTYPE_HSE;
145   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
146   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
147   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
148   RCC_OscInitStruct.LSIState = RCC_LSI_ON;
149   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
150   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
151   {
152     Error_Handler();
153   }
154   /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
155   */
156   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
157                               |RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
158                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
159   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
160   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
161   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
162   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
163   RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
164   RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
165 
166   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
167   {
168     Error_Handler();
169   }
170   /** Initializes the peripherals clocks
171   */
172   PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP
173                               |RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
174                               |RCC_PERIPHCLK_LPUART1;
175   PeriphClkInitStruct.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
176   PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
177   PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
178   PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSI;
179   PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSE;
180   PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE0;
181 
182   if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
183   {
184     Error_Handler();
185   }
186 }
187 
188 /**
189   * @brief Peripheral Clock Configuration
190   * @retval None
191   */
PeriphClock_Config(void)192 void PeriphClock_Config(void)
193 {
194     /**
195      * Select LSE clock
196      * on wb series LSI is not enough accurate to maintain connection
197      */
198     LL_RCC_LSE_Enable();
199     while(!LL_RCC_LSE_IsReady());
200 
201     /**
202      * Select wakeup source of BLE RF
203      */
204     LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
205 
206     /**
207      * Switch OFF LSI
208      */
209     LL_RCC_LSI1_Disable();
210 
211 
212     /**
213      * Set RNG on HSI48
214      */
215     LL_RCC_HSI48_Enable();
216     while(!LL_RCC_HSI48_IsReady());
217     LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_HSI48);
218 
219     return;
220 }
221 
Tune_HSE(void)222 void Tune_HSE( void )
223 {
224   OTP_ID0_t * p_otp;
225 
226   /**
227     * Read HSE_Tuning from OTP
228     */
229   p_otp = (OTP_ID0_t *) OTP_Read(0);
230   if (p_otp)
231   {
232     LL_RCC_HSE_SetCapacitorTuning(p_otp->hse_tuning);
233   }
234 }
235 
Init_UART(void)236 static void Init_UART( void )
237 {
238     GPIO_InitTypeDef GPIO_InitStruct;
239 
240     /* Peripheral clock enable */
241     DEBUG_USART_CLK_ENABLE();
242     DEBUG_USART_PORT_CLK_ENABLE();
243 
244     /**USART GPIO Configuration */
245     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
246     GPIO_InitStruct.Pull = GPIO_NOPULL;
247     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
248     GPIO_InitStruct.Alternate = DEBUG_GPIO_AF;
249     /* DEBUG_USART_TX */
250     GPIO_InitStruct.Pin = DEBUG_USART_TX_Pin;
251     HAL_GPIO_Init(DEBUG_USART_TX_GPIO_Port, &GPIO_InitStruct);
252     /* DEBUG_USART_RX */
253     GPIO_InitStruct.Pin = DEBUG_USART_RX_Pin;
254     HAL_GPIO_Init(DEBUG_USART_RX_GPIO_Port, &GPIO_InitStruct);
255 
256     /* USART Configuration */
257     hTuart.Instance = DEBUG_USART;
258     hTuart.Init.BaudRate = 115200;
259     hTuart.Init.WordLength = UART_WORDLENGTH_8B;
260     hTuart.Init.StopBits = UART_STOPBITS_1;
261     hTuart.Init.Parity = UART_PARITY_NONE;
262     hTuart.Init.Mode = UART_MODE_TX_RX;
263     hTuart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
264     hTuart.Init.OverSampling = UART_OVERSAMPLING_16;
265     hTuart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
266     hTuart.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
267     if (HAL_UART_Init(&hTuart) != HAL_OK){
268         Error_Handler();
269     }
270     return;
271 }
272 
Init_Exti(void)273 static void Init_Exti( void )
274 {
275   /**< Disable all wakeup interrupt on CPU1  except IPCC(36), HSEM(38) */
276   LL_EXTI_DisableIT_0_31(~0);
277   LL_EXTI_DisableIT_32_63( (~0) & (~(LL_EXTI_LINE_36 | LL_EXTI_LINE_38)) );
278 
279   HAL_NVIC_SetPriority(IPCC_C1_RX_IRQn,5,0);
280   HAL_NVIC_SetPriority(IPCC_C1_TX_IRQn,5,0);
281 
282   return;
283 }
284 
Init_RTC(void)285 static void Init_RTC( void )
286 {
287   HAL_PWR_EnableBkUpAccess(); /**< Enable access to the RTC registers */
288 
289   /**
290    *  Write twice the value to flush the APB-AHB bridge
291    *  This bit shall be written in the register before writing the next one
292    */
293   HAL_PWR_EnableBkUpAccess();
294 
295   __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); /**< Select LSI as RTC Input */
296 
297   __HAL_RCC_RTC_ENABLE(); /**< Enable RTC */
298 
299   hrtc.Instance = RTC; /**< Define instance */
300 
301   /**
302    * Set the Asynchronous prescaler
303    */
304   hrtc.Init.AsynchPrediv = CFG_RTC_ASYNCH_PRESCALER;
305   hrtc.Init.SynchPrediv = CFG_RTC_SYNCH_PRESCALER;
306   HAL_RTC_Init(&hrtc);
307 
308   MODIFY_REG(RTC->CR, RTC_CR_WUCKSEL, CFG_RTC_WUCKSEL_DIVIDER);
309 
310     /* RTC interrupt Init */
311     HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0, 0);
312     HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
313 
314   return;
315 }
316 
PreSleepProcessing(uint32_t ulExpectedIdleTime)317 void PreSleepProcessing(uint32_t ulExpectedIdleTime)
318 {
319   /* Called by the kernel before it places the MCU into a sleep mode because
320   configPRE_SLEEP_PROCESSING() is #defined to PreSleepProcessing().
321 
322   NOTE:  Additional actions can be taken here to get the power consumption
323   even lower.  For example, peripherals can be turned off here, and then back
324   on again in the post sleep processing function.  For maximum power saving
325   ensure all unused pins are in their lowest power state. */
326 
327   /*
328     (*ulExpectedIdleTime) is set to 0 to indicate that PreSleepProcessing contains
329     its own wait for interrupt or wait for event instruction and so the kernel vPortSuppressTicksAndSleep
330     function does not need to execute the wfi instruction
331   */
332   ulExpectedIdleTime = 0;
333 
334   /*Enter to sleep Mode using the HAL function HAL_PWR_EnterSLEEPMode with WFI instruction*/
335   HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
336 }
337 
338 
PostSleepProcessing(uint32_t ulExpectedIdleTime)339 void PostSleepProcessing(uint32_t ulExpectedIdleTime)
340 {
341   /* Called by the kernel when the MCU exits a sleep mode because
342   configPOST_SLEEP_PROCESSING is #defined to PostSleepProcessing(). */
343 
344   /* Avoid compiler warnings about the unused parameter. */
345   (void) ulExpectedIdleTime;
346 }
347 
vApplicationStackOverflowHook(TaskHandle_t xTask,signed char * pcTaskName)348 void vApplicationStackOverflowHook(TaskHandle_t xTask,
349         signed char *pcTaskName)
350 {
351     printf("stack overflow in task %s!\r\n", pcTaskName);
352     while (1);
353 }