Skip to content

Commit 84035d8

Browse files
authored
Merge pull request #265 from david-cermak/feat/linux_port_component
examples: Add simple mqtt client demo running on linux
2 parents 68392f0 + e620eb5 commit 84035d8

33 files changed

+820
-288
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ repos:
6262
hooks:
6363
- id: commit message scopes
6464
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, common"
65-
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|websocket|asio|mqtt_cxx)\)\:)'
65+
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|websocket|asio|mqtt_cxx|examples)\)\:)'
6666
language: pygrep
6767
args: [--multiline]
6868
stages: [commit-msg]

ci/check_copyright_config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ DEFAULT:
2929
# this section sets the default license for examples and unit tests of components
3030
examples_and_unit_tests:
3131
include:
32+
- 'examples/**'
3233
- 'components/**/examples/**'
3334
- 'components/**/test/**'
3435
- 'components/**/tests/**'

components/mdns/tests/host_test/components/esp_timer_linux/esp_timer_linux.c renamed to common_components/linux_compat/esp_timer/esp_timer_linux.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "esp_timer.h"
88
#include "freertos/FreeRTOS.h"
99
#include "freertos/task.h"
10+
#include <pthread.h>
1011

1112
void *create_tt(esp_timer_cb_t cb);
1213

@@ -37,3 +38,10 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer)
3738
destroy_tt(timer);
3839
return ESP_OK;
3940
}
41+
42+
int64_t esp_timer_get_time(void)
43+
{
44+
struct timespec spec;
45+
clock_gettime(CLOCK_REALTIME, &spec);
46+
return spec.tv_nsec / 1000 + spec.tv_sec * 1000000;
47+
}

components/mdns/tests/host_test/components/esp_timer_linux/include/esp_timer.h renamed to common_components/linux_compat/esp_timer/include/esp_timer.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#include <stdint.h>
1010
#include "bsd/string.h"
1111

12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
1217
typedef struct esp_timer *esp_timer_handle_t;
1318

1419
typedef void (*esp_timer_cb_t)(void *arg);
@@ -32,3 +37,9 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period);
3237
esp_err_t esp_timer_stop(esp_timer_handle_t timer);
3338

3439
esp_err_t esp_timer_delete(esp_timer_handle_t timer);
40+
41+
int64_t esp_timer_get_time(void);
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif

components/mdns/tests/host_test/components/freertos/CMakeLists.txt renamed to common_components/linux_compat/freertos/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp
1+
idf_component_register(SRCS freertos_linux.c
2+
osal/queue.cpp osal/event_group.cpp osal/mutex.cpp
23
INCLUDE_DIRS include)
34

45
set(THREADS_PREFER_PTHREAD_FLAG ON)
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <unistd.h>
8+
#include "freertos/FreeRTOS.h"
9+
#include "freertos/task.h"
10+
#include <pthread.h>
11+
#include <assert.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
#include "osal/osal_api.h"
15+
16+
static uint64_t s_semaphore_data = 0;
17+
18+
typedef enum queue_type_tag {
19+
MUTEX_REC,
20+
MUTEX,
21+
SEMA,
22+
QUEUE,
23+
} queue_type_t;
24+
25+
struct generic_queue_handle {
26+
queue_type_t type;
27+
size_t item_size;
28+
void *q;
29+
};
30+
31+
static struct generic_queue_handle *create_generic_queue(queue_type_t type, uint32_t len, uint32_t item_size)
32+
{
33+
struct generic_queue_handle *h = calloc(1, sizeof(struct generic_queue_handle));
34+
h->item_size = len;
35+
h->type = type;
36+
switch (type) {
37+
default:
38+
case QUEUE:
39+
case SEMA:
40+
h->q = osal_queue_create();
41+
break;
42+
43+
case MUTEX:
44+
case MUTEX_REC:
45+
h->q = osal_mutex_create();
46+
break;
47+
}
48+
return h;
49+
}
50+
51+
QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize )
52+
{
53+
return (QueueHandle_t)create_generic_queue(QUEUE, uxQueueLength, uxItemSize);
54+
}
55+
56+
uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait)
57+
{
58+
struct generic_queue_handle *h = xQueue;
59+
return osal_queue_send(h->q, (uint8_t *)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL;
60+
}
61+
62+
uint32_t xQueueSendToBack(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )
63+
{
64+
return xQueueSend(xQueue, pvItemToQueue, xTicksToWait);
65+
}
66+
67+
uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait)
68+
{
69+
struct generic_queue_handle *h = xQueue;
70+
return osal_queue_recv(h->q, (uint8_t *)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL;
71+
}
72+
73+
BaseType_t xSemaphoreGive( QueueHandle_t xQueue)
74+
{
75+
struct generic_queue_handle *h = xQueue;
76+
if (h->type == MUTEX) {
77+
osal_mutex_give(h->q);
78+
return pdTRUE;
79+
}
80+
return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY);
81+
}
82+
83+
BaseType_t xSemaphoreGiveRecursive( QueueHandle_t xQueue)
84+
{
85+
struct generic_queue_handle *h = xQueue;
86+
if (h->type == MUTEX_REC) {
87+
osal_mutex_give(h->q);
88+
return pdTRUE;
89+
}
90+
return pdFALSE;
91+
}
92+
BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask )
93+
{
94+
struct generic_queue_handle *h = xQueue;
95+
if (h->type == MUTEX) {
96+
osal_mutex_take(h->q);
97+
return pdTRUE;
98+
}
99+
return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY);
100+
}
101+
102+
103+
BaseType_t xSemaphoreTakeRecursive( QueueHandle_t xQueue, TickType_t pvTask )
104+
{
105+
struct generic_queue_handle *h = xQueue;
106+
if (h->type == MUTEX_REC) {
107+
osal_mutex_take(h->q);
108+
return pdTRUE;
109+
}
110+
return pdFALSE;
111+
}
112+
113+
114+
115+
116+
void vQueueDelete( QueueHandle_t xQueue )
117+
{
118+
struct generic_queue_handle *h = xQueue;
119+
if (h->q) {
120+
if (h->type == MUTEX || h->type == MUTEX_REC) {
121+
osal_mutex_delete(h->q);
122+
} else {
123+
osal_queue_delete(h->q);
124+
}
125+
}
126+
free(xQueue);
127+
}
128+
129+
QueueHandle_t xSemaphoreCreateBinary(void)
130+
{
131+
QueueHandle_t sempaphore = xQueueCreate(1, 1);
132+
return sempaphore;
133+
}
134+
135+
QueueHandle_t xSemaphoreCreateMutex(void)
136+
{
137+
return (QueueHandle_t)create_generic_queue(MUTEX, 1, 1);
138+
}
139+
140+
QueueHandle_t xSemaphoreCreateRecursiveMutex(void)
141+
{
142+
return (QueueHandle_t)create_generic_queue(MUTEX_REC, 1, 1);
143+
}
144+
145+
146+
void vTaskDelete(TaskHandle_t *task)
147+
{
148+
if (task == NULL) {
149+
pthread_exit(0);
150+
}
151+
void *thread_rval = NULL;
152+
pthread_join((pthread_t)task, &thread_rval);
153+
}
154+
155+
void vTaskSuspend(void *task)
156+
{
157+
vTaskDelete(task);
158+
}
159+
160+
TickType_t xTaskGetTickCount( void )
161+
{
162+
struct timespec spec;
163+
clock_gettime(CLOCK_REALTIME, &spec);
164+
return spec.tv_nsec / 1000000 + spec.tv_sec * 1000;
165+
}
166+
167+
void vTaskDelay( const TickType_t xTicksToDelay )
168+
{
169+
usleep(xTicksToDelay * 1000);
170+
}
171+
172+
void *pthread_task(void *params)
173+
{
174+
struct {
175+
void *const param;
176+
TaskFunction_t task;
177+
bool started;
178+
} *pthread_params = params;
179+
180+
void *const param = pthread_params->param;
181+
TaskFunction_t task = pthread_params->task;
182+
pthread_params->started = true;
183+
184+
task(param);
185+
186+
return NULL;
187+
}
188+
189+
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode,
190+
const char *const pcName,
191+
const uint32_t usStackDepth,
192+
void *const pvParameters,
193+
UBaseType_t uxPriority,
194+
TaskHandle_t *const pvCreatedTask,
195+
const BaseType_t xCoreID)
196+
{
197+
xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask);
198+
return pdTRUE;
199+
}
200+
201+
202+
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *const pcName, const uint32_t usStackDepth, void *const pvParameters, UBaseType_t uxPriority, TaskHandle_t *const pvCreatedTask)
203+
{
204+
pthread_t new_thread = (pthread_t)NULL;
205+
pthread_attr_t attr;
206+
struct {
207+
void *const param;
208+
TaskFunction_t task;
209+
bool started;
210+
} pthread_params = { .param = pvParameters, .task = pvTaskCode};
211+
int res = pthread_attr_init(&attr);
212+
assert(res == 0);
213+
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
214+
assert(res == 0);
215+
res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params);
216+
assert(res == 0);
217+
218+
if (pvCreatedTask) {
219+
*pvCreatedTask = (void *)new_thread;
220+
}
221+
222+
// just wait till the task started so we can unwind params from the stack
223+
while (pthread_params.started == false) {
224+
usleep(1000);
225+
}
226+
return pdTRUE;
227+
}
228+
229+
void xTaskNotifyGive(TaskHandle_t task)
230+
{
231+
232+
}
233+
234+
BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time )
235+
{
236+
return true;
237+
}
238+
239+
TaskHandle_t xTaskGetCurrentTaskHandle(void)
240+
{
241+
return NULL;
242+
}
243+
244+
EventGroupHandle_t xEventGroupCreate( void )
245+
{
246+
return osal_signal_create();
247+
}
248+
249+
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
250+
{
251+
osal_signal_delete(xEventGroup);
252+
}
253+
254+
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
255+
{
256+
return osal_signal_clear(xEventGroup, uxBitsToClear);
257+
}
258+
259+
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup)
260+
{
261+
return osal_signal_get(xEventGroup);
262+
}
263+
264+
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
265+
{
266+
return osal_signal_set(xEventGroup, uxBitsToSet);
267+
}
268+
269+
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
270+
{
271+
return osal_signal_wait(xEventGroup, uxBitsToWaitFor, xWaitForAllBits, xTicksToWait);
272+
}

0 commit comments

Comments
 (0)