1+ #ifdef defined (PLATFORM_STM32F4 )
2+ /*************
3+ I hope this software works LOL
4+ ***************/
5+
6+ #include "lf_STM32f4_support.h"
7+ #include "platform.h"
8+ #include "utils/util.h"
9+ #include "tag.h"
10+
11+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
12+ // | Important defines and global variables
13+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
14+
15+ static volatile bool _lf_sleep_interrupted = false;
16+ static volatile bool _lf_async_event = false;
17+
18+ #define LF_MAX_SLEEP_NS USEC(UINT32_MAX)
19+ #define LF_MIN_SLEEP_NS USEC(5)
20+
21+ // nested critical section counter
22+ static uint32_t _lf_num_nested_crit_sec = 0 ;
23+
24+ // Timer upper half (for overflow)
25+ static uint32_t _lf_time_us_high = 0 ;
26+
27+ // Combine 2 32bit works to a 64 bit word (Takes from nrf52 support)
28+ #define COMBINE_HI_LO (hi , lo ) ((((uint64_t)hi) << 32) | ((uint64_t)lo))
29+
30+
31+
32+
33+
34+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
35+ // | Code for timer functions
36+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
37+
38+ // We use timer 5 for our clock (probably better than fucking with sysTick)
39+ void _lf_initialize_clock (void ) {
40+ // Standard initializations from generated code
41+ // HAL_Init();
42+ // SystemClock_Config();
43+
44+ // Configure TIM5 as our 32-bit clock timer
45+ __HAL_RCC_TIM5_CLK_ENABLE (); // initialize counter
46+ TIM5 -> CR1 = TIM_CR1_CEN ; // enable counter
47+
48+ // set prescaler to (16 - 1) = 15
49+ // CPU runs a 16MHz so timer ticks at 1MHz
50+ // Which means period of 1 microsecond
51+ TIM5 -> PSC = 15 ;
52+
53+ // Setup ISR to increment upper bits
54+ TIM5 -> DIER |= TIM_DIER_CC1IE ;
55+ NVIC_EnableIRQ (TIM5_IRQn );
56+
57+ /* This is to make the Prescaler actually work
58+ * For some reason, the Prescaler only kicks in once the timer has reset once.
59+ * Thus, the current solution is to manually ret the value to a really large
60+ * and force it to reset once. Its really jank but its the only way I could
61+ * find to make it work
62+ */
63+ TIM5 -> CNT = 0xFFFFFFFE ;
64+ }
65+
66+ /**
67+ * ISR for handling timer overflow -> We increment the upper timer
68+ */
69+ void TIM5_IRQHandler (void ){
70+ if (TIM5 -> SR & (1 << 1 )) {
71+ TIM5 -> SR &= ~(1 << 1 );
72+ _lf_time_us_high += 1 ;
73+ }
74+ }
75+
76+ /**
77+ * Write the time since boot into time variable
78+ */
79+ int _lf_clock_now (instant_t * t ){
80+ // Timer is cooked
81+ if (!t ) {
82+ return -1 ;
83+ }
84+ // Get the current microseconds from TIM5
85+ uint32_t _lf_time_us_low = TIM5 -> CNT ;
86+
87+ // Combine upper and lower timers (Yoinked from lf_nrf52 support)
88+ uint64_t now_us = COMBINE_HI_LO ((_lf_time_us_high - 1 ), _lf_time_us_low );
89+ * t = ((instant_t )now_us ) * 1000 ;
90+ return 0 ;
91+ }
92+
93+ /**
94+ * Make the STM32 go honk shoo mimimi for set nanoseconds
95+ * I essentially stole this from the lf_nrf52 support
96+ */
97+ int lf_sleep (interval_t sleep_duration ){
98+ instant_t target_time ;
99+ instant_t current_time ;
100+
101+ _lf_clock_now (& current_time );
102+ target_time = current_time + sleep_duration ;
103+ while (current_time <= target_time )
104+ _lf_clock_now (& current_time );
105+
106+ return 0 ;
107+ }
108+
109+ /**
110+ * Make the STM32 go honk shoo honk shoo for set nanoseconds
111+ * This one uses a do-while loop. :)
112+ * I essentially stole this from the lf_nrf52 support
113+ */
114+ static void lf_busy_wait_until (instant_t wakeup_time ) {
115+ instant_t now ;
116+ do {
117+ _lf_clock_now (& now );
118+ } while (now < wakeup_time );
119+ }
120+
121+ // I am pretty sure this function doesnt work
122+ // Ill try to fix it once i know what the fuck its supposed to do, LOL
123+ int _lf_interruptable_sleep_until_locked (environment_t * env , instant_t wakeup_time ) {
124+ // // Get the current time and sleep time
125+ // instant_t now;
126+ // _lf_clock_now(&now);
127+ // interval_t duration = wakeup_time - now;
128+
129+ // // Edge case handling for super small duration
130+ // if (duration <= 0) {
131+ // return 0;
132+ // } else if (duration < 10) {
133+ // lf_busy_wait_until(wakeup_time);
134+ // return 0;
135+ // }
136+
137+ // // Enable interrupts and prepare to wait
138+ // _lf_async_event = false;
139+ // instant_t curr;
140+ // lf_enable_interrupts_nested();
141+
142+ // do {
143+ // _lf_clock_now(&curr);
144+
145+ // // Exit wither when the timer is up or there is an exception
146+ // } while (!_lf_async_event && (now < wakeup_time));
147+
148+ // // Disable interrupts again on exit
149+ // lf_disable_interrupts_nested();
150+
151+ // if (!_lf_async_event) {
152+ // return 0;
153+ // } else {
154+ // LF_PRINT_DEBUG(" *The STM32 rises from sleep* \n");
155+ // return -1;
156+ // }
157+
158+ instant_t now ;
159+ do {
160+ _lf_clock_now (& now );
161+ } while (now < wakeup_time );
162+ return 0 ;
163+ }
164+
165+
166+
167+
168+
169+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
170+ // | Code for enabling and disabling Interrupts
171+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
172+
173+ // disables the IRQ (checks if its already disabled)
174+ int lf_disable_interrupts_nested () {
175+ // Disable interrupts if they are currently enabled
176+ if (_lf_num_nested_crit_sec == 0 ) {
177+ __disable_irq ();
178+ }
179+
180+ // update the depth of disabling interrupts
181+ _lf_num_nested_crit_sec ++ ;
182+ return 0 ;
183+ }
184+
185+ // enables the IRQ (checks if other programs still want it disabled first)
186+ int lf_enable_interrupts_nested () {
187+ // Somebody fucked up, LOL
188+ if (_lf_num_nested_crit_sec <= 0 ) {
189+ return 1 ;
190+ }
191+
192+ // update the depth of disabling interrupts
193+ _lf_num_nested_crit_sec -- ;
194+
195+ // If we have exited all important programs, we can enable them again
196+ if (_lf_num_nested_crit_sec == 0 ) {
197+ __enable_irq ();
198+ }
199+ return 0 ;
200+ }
201+
202+ int _lf_unthreaded_notify_of_event () {
203+ _lf_async_event = true;
204+ return 0 ;
205+ }
206+
207+ int test_func (void ){
208+ return 5 ;
209+ }
210+
211+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
212+ // | Other functions I found -> taken from the generated main.c
213+ // + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +
214+
215+ // void SystemClock_Config(void) {
216+ // RCC_OscInitTypeDef RCC_OscInitStruct = {0};
217+ // RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
218+
219+ // /** Configure the main internal regulator output voltage
220+ // */
221+ // __HAL_RCC_PWR_CLK_ENABLE();
222+ // __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
223+
224+ // /** Initializes the RCC Oscillators according to the specified parameters
225+ // * in the RCC_OscInitTypeDef structure.
226+ // */
227+ // RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
228+ // RCC_OscInitStruct.HSIState = RCC_HSI_ON;
229+ // RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
230+ // RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
231+ // if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
232+ // {
233+ // Error_Handler();
234+ // }
235+
236+ // /** Initializes the CPU, AHB and APB buses clocks
237+ // */
238+ // RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
239+ // RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
240+ // RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
241+ // RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
242+ // RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
243+
244+ // if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
245+ // {
246+ // Error_Handler();
247+ // }
248+ // }
249+
250+
251+ // void Error_Handler(void)
252+ // {
253+ // /* USER CODE BEGIN Error_Handler_Debug */
254+ // /* User can add his own implementation to report the HAL error return state */
255+ // __disable_irq();
256+ // while (1)
257+ // {
258+ // }
259+ // /* USER CODE END Error_Handler_Debug */
260+ // }
261+
262+ #endif
0 commit comments