acc_exploration_server_stm32.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2021-2025
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #include <stdarg.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "main.h"
14
15 #include "acc_exploration_server_base.h"
16 #include "acc_exploration_server_stm32.h"
17 #include "acc_integration.h"
18 #include "acc_integration_log.h"
19
20 #define MODULE "exploration_server_stm32"
21
22 #define LOG_BUFFER_MAX_SIZE 150
23
24 #define STM32_EXPLORATION_SERVER_MAX_BAUDRATE 2000000
25
26 extern UART_HandleTypeDef EXPLORATION_SERVER_UART_HANDLE;
27
28 static char *command_buffer = NULL;
29 static size_t command_buffer_size = 0;
30
31 #define UART_DMA_BUFFER_SIZE (8192)
32
33 static volatile bool uart_tx_active = false;
34 static uint8_t uart_dma_buffer[UART_DMA_BUFFER_SIZE];
35
36 static char exploration_server_command_buffer[4096];
37
38 static void uart_wait_for_tx_done(void)
39 {
40 while (true)
41 {
42 __disable_irq();
43 bool active = uart_tx_active;
44 __enable_irq();
45 if (active)
46 {
47 __WFI();
48 }
49 else
50 {
51 break;
52 }
53 }
54 }
55
56 /**
57 * @brief Write data to client (UART)
58 *
59 * @param[in] data pointer to data
60 * @param[in] size data size in bytes
61 */
62 static void write_to_client_uart(const void *data, uint32_t size)
63 {
64 const uint8_t *data8 = (const uint8_t *)data;
65
66 size_t pos = 0;
67
68 while (pos < size)
69 {
70 /* Wait for previous transmit to be done */
71 uart_wait_for_tx_done();
72
73 size_t this_size = ((size - pos) < UART_DMA_BUFFER_SIZE) ? (size - pos) : UART_DMA_BUFFER_SIZE;
74 memcpy(uart_dma_buffer, &data8[pos], this_size);
75
76 uart_tx_active = true;
77 HAL_UART_Transmit_DMA(&EXPLORATION_SERVER_UART_HANDLE, uart_dma_buffer, this_size);
78 pos += this_size;
79 }
80 }
81
82 /**
83 * @brief Restart input of new command
84 */
85 static void restart_input(void)
86 {
87 memset(command_buffer, 0, command_buffer_size);
88
89 /**
90 * Stop previous reception
91 * Clear buffer
92 * Re-start receive after a line has been received.
93 */
94 HAL_UART_AbortReceive(&EXPLORATION_SERVER_UART_HANDLE);
95 HAL_UART_Receive_DMA(&EXPLORATION_SERVER_UART_HANDLE, (uint8_t *)command_buffer, command_buffer_size);
96 }
97
98 static void set_baudrate(uint32_t baudrate)
99 {
100
101 /* Wait for previous transmit to be done before changing baudrate */
102 uart_wait_for_tx_done();
103
104 HAL_UART_AbortReceive(&EXPLORATION_SERVER_UART_HANDLE);
105 HAL_UART_DeInit(&EXPLORATION_SERVER_UART_HANDLE);
106 EXPLORATION_SERVER_UART_HANDLE.Init.BaudRate = baudrate;
107 if (HAL_UART_Init(&EXPLORATION_SERVER_UART_HANDLE) != HAL_OK)
108 {
109 Error_Handler();
110 }
111
112 HAL_UART_Receive_DMA(&EXPLORATION_SERVER_UART_HANDLE, (uint8_t *)command_buffer, command_buffer_size);
113 }
114
115 static uint32_t get_tick(void)
116 {
117 return acc_integration_get_time();
118 }
119
120 /**
121 * @brief Server interface functions
122 */
123 static const exploration_server_interface_t server_if = {
124 .write = write_to_client_uart,
125 .restart_input = restart_input,
126 .set_baudrate = set_baudrate,
127 .max_baudrate = STM32_EXPLORATION_SERVER_MAX_BAUDRATE,
128 .get_tick = get_tick,
129 .ticks_per_second = 1000,
130 };
131
132 void acc_exploration_server_stm32_init(const char *hw, char *buffer, size_t buffer_size)
133 {
134
135 command_buffer = buffer;
136 command_buffer_size = buffer_size;
137 acc_exploration_server_init(command_buffer, command_buffer_size, hw, ACC_LOG_LEVEL_INFO);
138 }
139
140 void acc_exploration_server_stm32_main(void)
141 {
142 /**
143 * The embedded exploration server for STM32 can stream UART input data
144 * directly into the input buffer.
145 *
146 * Setup DMA into buffer with buffer_size.
147 */
148 HAL_UART_Receive_DMA(&EXPLORATION_SERVER_UART_HANDLE, (uint8_t *)command_buffer, command_buffer_size);
149
150 while (true)
151 {
152 /* Default values */
153 acc_exploration_server_state_t state = ACC_EXPLORATION_SERVER_WAITING;
154 int32_t ticks_until_next = 0;
155
156 if (acc_exploration_server_process(&server_if, &state, &ticks_until_next))
157 {
158 switch (state)
159 {
160 case ACC_EXPLORATION_SERVER_STOPPED:
161 /* Stop exploration server, not implemented for this target */
162 ACC_LOG_ERROR("Exploration server command 'stop_application' not supported.");
163 __WFI();
164 break;
165 case ACC_EXPLORATION_SERVER_WAITING:
166 /* Idle time, just wait for next interrupt */
167 __WFI();
168 break;
169 case ACC_EXPLORATION_SERVER_STREAMING:
170 if (ticks_until_next > 1)
171 {
172 /* More than 1 tick to sleep, wait for next interrupt (at the most 1ms away) */
173 __WFI();
174 }
175
176 break;
177 }
178 }
179 else
180 {
181 /* Error */
182 Error_Handler();
183 }
184 }
185 }
186
187 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
188 {
189 if (huart == &EXPLORATION_SERVER_UART_HANDLE)
190 {
191 /* Check framing error bit to detect break condition */
192 if ((huart->ErrorCode & HAL_UART_ERROR_FE) == HAL_UART_ERROR_FE)
193 {
194 HAL_NVIC_SystemReset();
195 }
196 }
197 }
198
199 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *h_uart)
200 {
201 if (h_uart == &EXPLORATION_SERVER_UART_HANDLE)
202 {
203 uart_tx_active = false;
204 }
205 }
206
207 void acc_integration_log(acc_log_level_t level, const char *module, const char *format, ...)
208 {
209 char log_buffer[LOG_BUFFER_MAX_SIZE];
210 va_list ap;
211
212 va_start(ap, format);
213 int ret = vsnprintf(log_buffer, LOG_BUFFER_MAX_SIZE, format, ap);
214
215 va_end(ap);
216
217 if (ret >= LOG_BUFFER_MAX_SIZE)
218 {
219 log_buffer[LOG_BUFFER_MAX_SIZE - 4] = '.';
220 log_buffer[LOG_BUFFER_MAX_SIZE - 3] = '.';
221 log_buffer[LOG_BUFFER_MAX_SIZE - 2] = '.';
222 log_buffer[LOG_BUFFER_MAX_SIZE - 1] = 0;
223 }
224
225 acc_exploration_server_send_log(server_if.write, level, module, log_buffer);
226 }
227
228 int acconeer_main(int argc, char *argv[]);
229
230 int acconeer_main(int argc, char *argv[])
231 {
232 (void)argc;
233 (void)argv;
234
235 printf("Acconeer Exploration Server\n");
236
237 // Wait for host line break to end before starting exploration server
238 while (HAL_GPIO_ReadPin(UART_RX_GPIO_Port, UART_RX_Pin) == GPIO_PIN_RESET)
239 {
240 printf("Waiting for host line break to end...\n");
241 HAL_Delay(10);
242 }
243
244 // Clear out any pending garbage and errors on the UART line by deinit/init
245 // it again. This avoids that the HAL_UART_ErrorCallback() is called (leading
246 // to an additional reset cycle) if the RX line was previously low.
247 HAL_UART_DeInit(&EXPLORATION_SERVER_UART_HANDLE);
248 if (HAL_UART_Init(&EXPLORATION_SERVER_UART_HANDLE) != HAL_OK)
249 {
250 Error_Handler();
251 }
252
253 acc_exploration_server_stm32_init("xm125", exploration_server_command_buffer, sizeof(exploration_server_command_buffer));
254 acc_exploration_server_stm32_main();
255
256 return 0;
257 }
ACC_EXPLORATION_SERVER_STOPPED
@ ACC_EXPLORATION_SERVER_STOPPED
Definition: acc_exploration_server_base.h:17
exploration_server_command_buffer
static char exploration_server_command_buffer[4096]
Definition: acc_exploration_server_stm32.c:36
acc_exploration_server_stm32_main
void acc_exploration_server_stm32_main(void)
Start the stm32 exploration server.
Definition: acc_exploration_server_stm32.c:140
acc_exploration_server_stm32.h
LOG_BUFFER_MAX_SIZE
#define LOG_BUFFER_MAX_SIZE
Definition: acc_exploration_server_stm32.c:22
acc_integration_get_time
uint32_t acc_integration_get_time(void)
Get current time.
Definition: acc_integration_stm32.c:587
acc_exploration_server_base.h
set_baudrate
static void set_baudrate(uint32_t baudrate)
Definition: acc_exploration_server_stm32.c:98
buffer
void * buffer
Definition: i2c_example_cargo.c:40
vsnprintf
#define vsnprintf
Definition: printf.h:85
write_to_client_uart
static void write_to_client_uart(const void *data, uint32_t size)
Write data to client (UART)
Definition: acc_exploration_server_stm32.c:62
ACC_LOG_LEVEL_INFO
@ ACC_LOG_LEVEL_INFO
Definition: acc_definitions_common.h:30
STM32_EXPLORATION_SERVER_MAX_BAUDRATE
#define STM32_EXPLORATION_SERVER_MAX_BAUDRATE
Definition: acc_exploration_server_stm32.c:24
UART_RX_GPIO_Port
#define UART_RX_GPIO_Port
Definition: main.h:81
exploration_server_interface_t
Struct to handle input for acc_exploration_server_process_cmds.
Definition: acc_exploration_server_base.h:46
HAL_UART_TxCpltCallback
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *h_uart)
Definition: acc_exploration_server_stm32.c:199
acc_integration.h
ACC_LOG_ERROR
#define ACC_LOG_ERROR(...)
Definition: acc_integration_log.h:16
acc_exploration_server_stm32_init
void acc_exploration_server_stm32_init(const char *hw, char *buffer, size_t buffer_size)
Init the stm32 exploration server.
Definition: acc_exploration_server_stm32.c:132
acc_log_level_t
acc_log_level_t
This enum represents the different log levels for RSS.
Definition: acc_definitions_common.h:23
buffer_size
uint32_t buffer_size
Definition: i2c_example_cargo.c:41
acc_exploration_server_init
bool acc_exploration_server_init(char *buffer, size_t buffer_size, const char *hw, acc_log_level_t log_level)
Initialize the exploration server.
server_if
static const exploration_server_interface_t server_if
Server interface functions.
Definition: acc_exploration_server_stm32.c:123
uart_dma_buffer
static uint8_t uart_dma_buffer[(8192)]
Definition: acc_exploration_server_stm32.c:34
ACC_EXPLORATION_SERVER_STREAMING
@ ACC_EXPLORATION_SERVER_STREAMING
Definition: acc_exploration_server_base.h:16
acc_exploration_server_state_t
acc_exploration_server_state_t
Definition: acc_exploration_server_base.h:13
get_tick
static uint32_t get_tick(void)
Definition: acc_exploration_server_stm32.c:115
printf
#define printf
Definition: printf.h:60
uart_tx_active
static volatile bool uart_tx_active
Definition: acc_exploration_server_stm32.c:33
ACC_EXPLORATION_SERVER_WAITING
@ ACC_EXPLORATION_SERVER_WAITING
Definition: acc_exploration_server_base.h:15
uart_wait_for_tx_done
static void uart_wait_for_tx_done(void)
Definition: acc_exploration_server_stm32.c:38
EXPLORATION_SERVER_UART_HANDLE
UART_HandleTypeDef EXPLORATION_SERVER_UART_HANDLE
UART_DMA_BUFFER_SIZE
#define UART_DMA_BUFFER_SIZE
Definition: acc_exploration_server_stm32.c:31
acconeer_main
int acconeer_main(int argc, char *argv[])
Assembly test example.
Definition: acc_exploration_server_stm32.c:230
acc_exploration_server_send_log
bool acc_exploration_server_send_log(write_data_function_t write_func, acc_log_level_t level, const char *module, const char *buffer)
Sends a log as a json package.
acc_integration_log.h
HAL_UART_ErrorCallback
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
Definition: acc_exploration_server_stm32.c:187
main.h
: Header for main.c file. This file contains the common defines of the application.
Error_Handler
void Error_Handler(void)
command_buffer_size
static size_t command_buffer_size
Definition: acc_exploration_server_stm32.c:29
exploration_server_interface_t::write
write_data_function_t * write
Definition: acc_exploration_server_base.h:48
command_buffer
static char * command_buffer
Definition: acc_exploration_server_stm32.c:28
acc_exploration_server_process
bool acc_exploration_server_process(const exploration_server_interface_t *server_if, acc_exploration_server_state_t *state, int32_t *ticks_until_next)
The exploration server process function.
restart_input
static void restart_input(void)
Restart input of new command.
Definition: acc_exploration_server_stm32.c:85
acc_integration_log
void acc_integration_log(acc_log_level_t level, const char *module, const char *format,...)
Log function.
Definition: acc_exploration_server_stm32.c:207
UART_RX_Pin
#define UART_RX_Pin
Definition: main.h:80