Skip to content

Commit c11bed5

Browse files
committed
initial test for support for STM32
1 parent a0ad33d commit c11bed5

File tree

5 files changed

+296
-0
lines changed

5 files changed

+296
-0
lines changed

core/platform/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(LF_PLATFORM_FILES
1212
lf_zephyr_clock_counter.c
1313
lf_zephyr_clock_kernel.c
1414
lf_rp2040_support.c
15+
lf_STM32f4_support.c
1516
)
1617

1718
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
@@ -22,6 +23,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Nrf52")
2223
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr")
2324
list(APPEND REACTORC_COMPILE_DEFS PLATFORM_ZEPHYR)
2425
set(PLATFORM_ZEPHYR true)
26+
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "STM32f4")
27+
target_compile_definitions(core PUBLIC PLATFORM_STM32F4)
2528
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040")
2629
list(APPEND REACTORC_COMPILE_DEFS PLATFORM_RP2040)
2730
endif()

core/platform/Platform.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
1010
message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
1111
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr")
1212
set(LF_PLATFORM_FILE lf_zephyr_support.c)
13+
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "STM32f4")
14+
set(LF_PLATFORM_FILE lf_STM32f4_support.c)
1315
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040")
1416
message("Using pico-sdk for RP2040 target")
1517
set(LF_PLATFORM_FILE lf_rp2040_support.c)

core/platform/lf_STM32f4_support.c

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
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

include/core/platform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ int lf_critical_section_exit(environment_t* env);
7070
#include "platform/lf_zephyr_support.h"
7171
#elif defined(PLATFORM_NRF52)
7272
#include "platform/lf_nrf52_support.h"
73+
#elif defined(PLATFORM_STM32F4)
74+
#include "platform/lf_STM32f4_support.h"
7375
#elif defined(PLATFORM_RP2040)
7476
#include "platform/lf_rp2040_support.h"
7577
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* STM32 API support for the C target of Lingua Franca. */
2+
3+
#ifndef LF_STM32F4_SUPPORT_H
4+
#define LF_STM32F4_SUPPORT_H
5+
6+
// I have no idea what the fuck TTY is so i guess we dont support it
7+
#define NO_TTY
8+
9+
// #include <../../../STM_Core/Inc/main.h>
10+
// #include <../../../Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h>
11+
#include <stm32f4xx_hal.h>
12+
13+
// src-gen/Main/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h
14+
15+
// Defines for formatting time in printf for pico
16+
#define PRINTF_TAG "(" PRINTF_TIME ", " PRINTF_MICROSTEP ")"
17+
#define PRINTF_TIME "%lld"
18+
#define PRINTF_MICROSTEP "%d"
19+
20+
#define LF_TIME_BUFFER_LENGTH 80
21+
#define _LF_TIMEOUT 1
22+
23+
#ifdef LF_THREADED
24+
#error "I have no idea how to support threading"
25+
#endif // LF_THREADED
26+
27+
#endif

0 commit comments

Comments
 (0)