Solaris Software
Loading...
Searching...
No Matches
halEsp32.c
Go to the documentation of this file.
1/**
2 * @file halEsp32.c
3 * @brief ESP32 HAL port for SPP — polling SPI, no FreeRTOS dependency.
4 *
5 * Register @ref g_esp32HalPort before calling @ref SPP_CORE_init().
6 */
7
8#include "spp/hal/hal.h"
9#include "spp/hal/gpio/gpio.h"
10#include "spp/hal/uart/uart.h"
12#include "spp/core/types.h"
13#include "macrosEsp32.h"
14#include "halEsp32.h"
15
16#include "driver/spi_common.h"
17#include "driver/spi_master.h"
18#include "driver/gpio.h"
19#include "driver/sdspi_host.h"
20#include "sdmmc_cmd.h"
21#include "esp_log.h"
22#include "esp_timer.h"
23#include "driver/uart.h"
24
25#include <string.h>
26
27/* ----------------------------------------------------------------
28 * STATIC FUNCTIONS DEFINITIONS
29 * ---------------------------------------------------------------- */
30
32static void *SPP_PORTS_HAL_ESP32_spiGetHandle(spp_uint8_t deviceIdx);
33
35static SPP_RetVal_t SPP_PORTS_HAL_ESP32_spiTransmit(void *p_handle, spp_uint8_t *p_data, spp_uint8_t length);
37
40
42static SPP_RetVal_t SPP_PORTS_HAL_ESP32_storageWrite(const void *p_buffer, spp_uint32_t first_block,
43 spp_uint16_t count);
44
48
50static SPP_RetVal_t SPP_PORTS_HAL_ESP32_uartTransmit(const void *p_data, spp_uint32_t len);
51static SPP_RetVal_t SPP_PORTS_HAL_ESP32_uartRead(void *p_data, spp_uint32_t len, spp_uint32_t *p_readBytes);
52
53
54/* ----------------------------------------------------------------
55 * STATIC VARIABLES
56 * ---------------------------------------------------------------- */
57
61 .spiDeviceInit = SPP_PORTS_HAL_ESP32_spiDeviceInit,
63 .spiDeviceSetSpeed = SPP_PORTS_HAL_ESP32_spiDeviceSetSpeed,
64};
65
67 .gpioConfigInterrupt = SPP_PORTS_HAL_ESP32_gpioConfigInterrupt,
68 .gpioRegisterIsr = SPP_PORTS_HAL_ESP32_gpioRegisterIsr,
69};
70
75
81
86};
87
88
90 .spi = s_esp32HalSpi,
91 .gpio = s_esp32HalGpio,
92 .storage = s_esp32HalStorage,
93 .time = s_esp32HalTime,
94 .uart = s_esp32HalUart,
95};
96
97/* ----------------------------------------------------------------
98 * PUBLIC FUNCTIONS
99 * ---------------------------------------------------------------- */
100
101/**
102 * @brief Returns a pointer to the ESP32-S3 HAL port descriptor.
103 * @return Pointer to the static @ref SPP_HalPort_t.
104 */
109
110/* ----------------------------------------------------------------
111 * PRIVATE VARIABLES
112 * ---------------------------------------------------------------- */
113
114static const char *const k_tag = "SPP_HAL";
115
116static spi_device_handle_t s_spiHandles[K_ESP32_MAX_SPI_DEVICES];
119
120static sdspi_dev_handle_t sdHandle;
121static sdmmc_card_t sdCard;
123
124/* ----------------------------------------------------------------
125 * SPI
126 * ---------------------------------------------------------------- */
127
129{
131 {
132 return K_SPP_OK;
133 }
134
135 /* Diagnostic: test MISO pin level before SPI takes control of it */
136 gpio_config_t misoCfg = {
137 .pin_bit_mask = (1ULL << K_ESP32_PIN_MISO),
138 .mode = GPIO_MODE_INPUT,
139 .pull_up_en = GPIO_PULLUP_ENABLE,
140 .pull_down_en = GPIO_PULLDOWN_DISABLE,
141 .intr_type = GPIO_INTR_DISABLE,
142 };
143 gpio_config(&misoCfg);
144 int misoLevel = gpio_get_level((gpio_num_t)K_ESP32_PIN_MISO);
145
146 spi_bus_config_t busCfg = {
147 .miso_io_num = K_ESP32_PIN_MISO,
148 .mosi_io_num = K_ESP32_PIN_MOSI,
149 .sclk_io_num = K_ESP32_PIN_CLK,
150 .quadwp_io_num = -1,
151 .quadhd_io_num = -1,
152 .max_transfer_sz = 0,
153 };
154
155 esp_err_t ret = spi_bus_initialize(K_ESP32_SPI_HOST, &busCfg, SPI_DMA_CH_AUTO);
156 if (ret != ESP_OK)
157 {
158 ESP_LOGE(k_tag, "SPI bus init failed: %s", esp_err_to_name(ret));
159 return K_SPP_ERROR;
160 }
161
162 s_busInitialized = true;
163 return K_SPP_OK;
164}
165
167{
168 if (deviceIdx >= K_ESP32_MAX_SPI_DEVICES)
169 {
170 return NULL;
171 }
172 return (void *)&s_spiHandles[deviceIdx];
173}
174
176{
177 if (p_handle == NULL)
178 {
180 }
182 {
183 return K_SPP_ERROR;
184 }
185
186 spi_device_handle_t *p_h = (spi_device_handle_t *)p_handle;
187 spi_device_interface_config_t devCfg = {0};
188
190 {
191 devCfg.clock_speed_hz = 1 * 1000 * 1000;
192 devCfg.mode = 0;
193 devCfg.spics_io_num = K_ESP32_PIN_CS_ICM;
194 devCfg.queue_size = 1;
195 }
197 {
198 devCfg.clock_speed_hz = 500 * 1000;
199 devCfg.mode = 0;
200 devCfg.spics_io_num = K_ESP32_PIN_CS_BMP;
201 devCfg.queue_size = 1;
202 }
203 else
204 {
205 ESP_LOGE(k_tag, "Unexpected device index %u", s_spiDevCount);
206 return K_SPP_ERROR;
207 }
208
209 esp_err_t ret = spi_bus_add_device(K_ESP32_SPI_HOST, &devCfg, p_h);
210 if (ret != ESP_OK)
211 {
212 ESP_LOGE(k_tag, "spi_bus_add_device failed: %s", esp_err_to_name(ret));
213 return K_SPP_ERROR;
214 }
215
217 return K_SPP_OK;
218}
219
221{
222 if ((p_handle == NULL) || (p_data == NULL) || (length == 0U))
223 {
225 }
226
227 spi_device_handle_t hDev = *(spi_device_handle_t *)p_handle;
228
229 if (hDev == NULL)
230 {
232 }
233
234 spp_uint8_t i = 0U;
235
236 while (i < length)
237 {
238 spi_transaction_t trans = {0};
239
240 if ((p_data[i] & 0x80U) != 0U)
241 {
242 trans.length = 8U * 3U;
243 trans.tx_buffer = &p_data[i];
244 trans.rx_buffer = &p_data[i];
245
246 i += 3U;
247 }
248 else
249 {
250 trans.length = 8U * 2U;
251 trans.tx_buffer = &p_data[i];
252
253 i += 2U;
254 }
255
256 esp_err_t ret = spi_device_polling_transmit(hDev, &trans);
257
258 if (ret != ESP_OK)
259 {
261 }
262 }
263
264 return K_SPP_OK;
265}
266
268{
269 if (p_handle == NULL)
270 {
272 }
273
274 spi_device_handle_t *p_h = (spi_device_handle_t *)p_handle;
275
276 spi_bus_remove_device(*p_h);
277
278 spi_device_interface_config_t devCfg = {0};
279 devCfg.clock_speed_hz = (int)speedHz;
280 devCfg.mode = 0;
281 devCfg.spics_io_num = K_ESP32_PIN_CS_SDC;
282 devCfg.queue_size = 1;
283
284 esp_err_t ret = spi_bus_add_device(K_ESP32_SPI_HOST, &devCfg, p_h);
285 if (ret != ESP_OK)
286 {
287 ESP_LOGE(k_tag, "spiDeviceSetSpeed failed: %s", esp_err_to_name(ret));
288 return K_SPP_ERROR;
289 }
290
291 return K_SPP_OK;
292}
293
294/* ----------------------------------------------------------------
295 * GPIO
296 * ---------------------------------------------------------------- */
297
298static void IRAM_ATTR SPP_PORTS_HAL_ESP32_gpioIsr(void *p_arg)
299{
300 SPP_GpioIsrCtx_t *p_ctx = (SPP_GpioIsrCtx_t *)p_arg;
301 *p_ctx->p_flag = true;
302}
303
305{
306 gpio_config_t ioCfg = {
307 .pin_bit_mask = (1ULL << pin),
308 .mode = GPIO_MODE_INPUT,
309 .intr_type = (gpio_int_type_t)intrType,
310 .pull_up_en = GPIO_PULLUP_DISABLE,
311 .pull_down_en = GPIO_PULLDOWN_DISABLE,
312 };
313
314 if (pull == 1U)
315 {
316 ioCfg.pull_up_en = GPIO_PULLUP_ENABLE;
317 }
318 if (pull == 2U)
319 {
320 ioCfg.pull_down_en = GPIO_PULLDOWN_ENABLE;
321 }
322
323 gpio_config(&ioCfg);
324 return K_SPP_OK;
325}
326
328{
329 static spp_bool_t s_serviceInstalled = false;
330 if (!s_serviceInstalled)
331 {
332 gpio_install_isr_service(0);
333 s_serviceInstalled = true;
334 }
335 gpio_isr_handler_add((gpio_num_t)pin, SPP_PORTS_HAL_ESP32_gpioIsr, p_isrCtx);
336 return K_SPP_OK;
337}
338
339/* ----------------------------------------------------------------
340 * Storage
341 * ---------------------------------------------------------------- */
342
344{
345 esp_err_t ret;
346
347 if (s_busInitialized == false)
348 {
349 return K_SPP_ERROR;
350 }
351
352 sdspi_device_config_t sdCfg = SDSPI_DEVICE_CONFIG_DEFAULT();
353 sdCfg.host_id = K_ESP32_SPI_HOST;
354 sdCfg.gpio_cs = K_ESP32_PIN_CS_SDC;
355
356 (void)sdspi_host_deinit();
357
358 gpio_set_direction(K_ESP32_PIN_CS_BMP, GPIO_MODE_OUTPUT);
359 gpio_set_direction(K_ESP32_PIN_CS_ICM, GPIO_MODE_OUTPUT);
360 gpio_set_level(K_ESP32_PIN_CS_BMP, 1);
361 gpio_set_level(K_ESP32_PIN_CS_ICM, 1);
362
363 for (int attempt = 0; attempt < 5; attempt++)
364 {
365 ret = sdspi_host_init();
366 if (ret != ESP_OK)
367 {
368 continue;
369 }
370
371 ret = sdspi_host_init_device(&sdCfg, &sdHandle);
372 if (ret != ESP_OK)
373 {
374 (void)sdspi_host_deinit();
375 continue;
376 }
377
378 sdmmc_host_t host = SDSPI_HOST_DEFAULT();
379 host.slot = sdHandle;
380
381 vTaskDelay(pdMS_TO_TICKS(10));
382
383 ret = sdmmc_card_init(&host, &sdCard);
384 if (ret == ESP_OK)
385 {
387 return K_SPP_OK;
388 }
389
390 (void)sdspi_host_remove_device(sdHandle);
391 (void)sdspi_host_deinit();
392 vTaskDelay(pdMS_TO_TICKS(50));
393 }
394
395 return K_SPP_ERROR;
396}
397
398static SPP_RetVal_t SPP_PORTS_HAL_ESP32_storageWrite(const void *p_buffer, spp_uint32_t first_block, spp_uint16_t count)
399{
400 esp_err_t ret;
401
402 if (s_storageInitialized == false || count == 0)
403 {
404 return K_SPP_ERROR;
405 }
406
407 if (p_buffer == NULL)
408 {
410 }
411
412 if (sdCard.csd.capacity <= first_block || (sdCard.csd.capacity - first_block) < count)
413 {
414 return K_SPP_ERROR;
415 }
416
417 ret = sdmmc_write_sectors(&sdCard, p_buffer, first_block, count);
418 if (ret != ESP_OK)
419 {
420 return K_SPP_ERROR;
421 }
422
423 return K_SPP_OK;
424}
425
426/* ----------------------------------------------------------------
427 * Time
428 * ---------------------------------------------------------------- */
429
431{
432 return (spp_uint32_t)(esp_timer_get_time() / 1000LL);
433}
434
436{
437 return (spp_uint32_t)(esp_timer_get_time());
438}
439
441{
443 while ((SPP_PORTS_HAL_ESP32_getTimeMs() - start) < ms)
444 { /* busy-wait */
445 }
446}
447
448/* ----------------------------------------------------------------
449 * UART
450 * ---------------------------------------------------------------- */
452{
453 esp_err_t ret = ESP_OK;
454 static spp_bool_t s_uartPortInitialized = false;
455
456 if (s_uartPortInitialized == true)
457 {
458 return K_SPP_OK;
459 }
460
461 const uart_port_t uart_num = K_ESP32_UART_PORT_ID;
462
463 uart_config_t espUartPortCfg = {
464 .baud_rate = K_ESP32_UART_BAUD_RATE,
465 .data_bits = UART_DATA_8_BITS,
466 .parity = UART_PARITY_DISABLE,
467 .stop_bits = UART_STOP_BITS_1,
468 .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
469 .rx_flow_ctrl_thresh = 0,
470 };
471
472 ret = uart_param_config(uart_num, &espUartPortCfg);
473 if (ret != ESP_OK)
474 {
475 return K_SPP_ERROR;
476 }
477
479
480 if (ret != ESP_OK)
481 {
482 return K_SPP_ERROR;
483 }
484
485 ret = uart_driver_install(uart_num, K_ESP32_UART_RX_BUFFER_SIZE, K_ESP32_UART_TX_BUFFER_SIZE, 0, NULL, 0);
486
487 if (ret != ESP_OK)
488 {
489 return K_SPP_ERROR;
490 }
491
492 s_uartPortInitialized = true;
493
494 return K_SPP_OK;
495}
496
498{
499 if ((p_data == NULL) || (len == 0U))
500 {
502 }
503
504 const spp_uint8_t *p_dataToTransmit = (spp_uint8_t *)p_data;
505
506 const int written = uart_write_bytes(K_ESP32_UART_PORT_ID, (void *)p_dataToTransmit, (size_t)len);
507
508 if (written != (int)len)
509 {
510 return K_SPP_ERROR;
511 }
512
513 return K_SPP_OK;
514}
515
516/**
517 * @brief Reads data from the ESP32 UART.
518 *
519 * @param[out] p_data Pointer to the buffer where received data will be stored.
520 * @param[in] len Number of bytes to read.
521 * @param[out] p_readBytes Pointer to the variable where the number of bytes read will be stored.
522 */
524{
525 if ((p_data == NULL) || (len == 0U))
526 {
528 }
529
530 spp_uint8_t *p_dataToRead = (spp_uint8_t *)p_data;
531
532 const int read = uart_read_bytes(K_ESP32_UART_PORT_ID, p_dataToRead, (size_t)len, K_ESP32_UART_MAX_DELAY);
533
534 if (read < 0)
535 {
536 return K_SPP_ERROR;
537 }
538
539 *p_readBytes = (spp_uint32_t)read;
540 return K_SPP_OK;
541}
SPP GPIO HAL API — dispatches through the registered HAL port.
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_spiDeviceSetSpeed(void *p_handle, spp_uint32_t speedHz)
Definition halEsp32.c:267
static const SPP_HALTime_t s_esp32HalTime
Definition halEsp32.c:76
static const SPP_HALStorage_t s_esp32HalStorage
Definition halEsp32.c:71
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_uartRead(void *p_data, spp_uint32_t len, spp_uint32_t *p_readBytes)
Reads data from the ESP32 UART.
Definition halEsp32.c:523
static const char *const k_tag
Definition halEsp32.c:114
static const SPP_HALGpio_t s_esp32HalGpio
Definition halEsp32.c:66
static void * SPP_PORTS_HAL_ESP32_spiGetHandle(spp_uint8_t deviceIdx)
Definition halEsp32.c:166
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_spiBusInit(void)
Definition halEsp32.c:128
static sdmmc_card_t sdCard
Definition halEsp32.c:121
static spp_uint32_t SPP_PORTS_HAL_ESP32_getTimeUs(void)
Definition halEsp32.c:435
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_uartPortInit(void)
Definition halEsp32.c:451
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_gpioRegisterIsr(spp_uint32_t pin, void *p_isrCtx)
Definition halEsp32.c:327
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_spiTransmit(void *p_handle, spp_uint8_t *p_data, spp_uint8_t length)
Definition halEsp32.c:220
static const SPP_HALSpi_t s_esp32HalSpi
Definition halEsp32.c:58
static spp_bool_t s_busInitialized
Definition halEsp32.c:118
static spi_device_handle_t s_spiHandles[K_ESP32_MAX_SPI_DEVICES]
Definition halEsp32.c:116
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_spiDeviceInit(void *p_handle)
Definition halEsp32.c:175
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_uartTransmit(const void *p_data, spp_uint32_t len)
Definition halEsp32.c:497
static spp_uint32_t SPP_PORTS_HAL_ESP32_getTimeMs(void)
Definition halEsp32.c:430
static const SPP_HALUart_t s_esp32HalUart
Definition halEsp32.c:82
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_storageInit(void)
Definition halEsp32.c:343
static const SPP_HalPort_t s_esp32HalPorts
Definition halEsp32.c:89
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_storageWrite(const void *p_buffer, spp_uint32_t first_block, spp_uint16_t count)
Definition halEsp32.c:398
const SPP_HalPort_t * SPP_PORTS_ESP32S3_getHalPorts(void)
Returns a pointer to the ESP32-S3 HAL port descriptor.
Definition halEsp32.c:105
static spp_uint8_t s_spiDevCount
Definition halEsp32.c:117
static spp_bool_t s_storageInitialized
Definition halEsp32.c:122
static SPP_RetVal_t SPP_PORTS_HAL_ESP32_gpioConfigInterrupt(spp_uint32_t pin, spp_uint32_t intrType, spp_uint32_t pull)
Definition halEsp32.c:304
static void IRAM_ATTR SPP_PORTS_HAL_ESP32_gpioIsr(void *p_arg)
Definition halEsp32.c:298
static sdspi_dev_handle_t sdHandle
Definition halEsp32.c:120
static void SPP_PORTS_HAL_ESP32_delayMs(spp_uint32_t ms)
Definition halEsp32.c:440
ESP32-S3 HAL port descriptor for SPP.
This file contains the structs that contain all the pointers to the functions that are used by the SP...
ESP32 hardware pin definitions and SPI constants.
#define K_ESP32_UART_TX_BUFFER_SIZE
Definition macrosEsp32.h:75
#define K_ESP32_SPI_IDX_BMP
SPI device index for the BMP390.
Definition macrosEsp32.h:55
#define K_ESP32_SPI_HOST
SPI peripheral to use.
Definition macrosEsp32.h:28
#define K_ESP32_UART_RX_PIN
Definition macrosEsp32.h:70
#define K_ESP32_UART_BAUD_RATE
Definition macrosEsp32.h:67
#define K_ESP32_PIN_MISO
MISO (CIPO) GPIO pin.
Definition macrosEsp32.h:19
#define K_ESP32_UART_RX_BUFFER_SIZE
Definition macrosEsp32.h:74
#define K_ESP32_MAX_SPI_DEVICES
Maximum number of SPI device slots.
Definition macrosEsp32.h:48
#define K_ESP32_SPI_IDX_ICM
SPI device index for the ICM20948.
Definition macrosEsp32.h:58
#define K_ESP32_UART_CTS_PIN
Definition macrosEsp32.h:72
#define K_ESP32_UART_PORT_ID
Definition macrosEsp32.h:66
#define K_ESP32_PIN_CLK
SPI clock GPIO pin.
Definition macrosEsp32.h:25
#define K_ESP32_PIN_CS_BMP
BMP390 barometer chip-select GPIO.
Definition macrosEsp32.h:35
#define K_ESP32_PIN_MOSI
MOSI (COPI) GPIO pin.
Definition macrosEsp32.h:22
#define K_ESP32_PIN_CS_ICM
ICM20948 IMU chip-select GPIO.
Definition macrosEsp32.h:38
#define K_ESP32_UART_MAX_DELAY
Definition macrosEsp32.h:77
#define K_ESP32_UART_TX_PIN
Definition macrosEsp32.h:69
#define K_ESP32_PIN_CS_SDC
SD card chip-select GPIO.
Definition macrosEsp32.h:41
#define K_ESP32_UART_RTS_PIN
Definition macrosEsp32.h:71
Standard return-value type used across all SPP modules.
SPP_RetVal_t
Unified return type for all SPP API functions.
Definition returnTypes.h:24
@ K_SPP_OK
Definition returnTypes.h:25
@ K_SPP_ERROR
Definition returnTypes.h:26
@ K_SPP_ERROR_ON_SPI_TRANSACTION
Definition returnTypes.h:33
@ K_SPP_ERROR_NULL_POINTER
Definition returnTypes.h:30
Context passed to the GPIO ISR handler.
Definition gpio.h:27
volatile spp_bool_t * p_flag
Definition gpio.h:28
GPIO struct that contains all the pointers to the GPIO functions.
Definition hal.h:123
SPI bus struct that contains all the pointers to the SPI functions.
Definition hal.h:22
Storage struct that contains all the pointers to the storage functions.
Definition hal.h:151
Time struct that contains all the pointers to the Time functions.
Definition hal.h:180
UART port struct that contains all the pointers to the UART functions.
Definition hal.h:86
Ports struct that contains all the pointers to the Ports functions.
Definition hal.h:215
Portable integer types and SPI/storage configuration types for SPP.
uint16_t spp_uint16_t
Definition types.h:29
uint32_t spp_uint32_t
Definition types.h:31
uint8_t spp_uint8_t
Definition types.h:27
bool spp_bool_t
Definition types.h:36
SPP UART HAL API — dispatches through the registered HAL port.