lo_os.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "cmsis_os.h"
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <pthread.h>
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <sys/types.h>
  8. #include <sys/ipc.h>
  9. #include <sys/msg.h>
  10. void osDelay(uint32_t ms) {
  11. // printf("[DELAY] %d ms\n", ms);
  12. usleep(ms * 1000);
  13. }
  14. // temporary struct to pass function ptr and param to wrapper
  15. typedef struct {
  16. TaskFunction_t func;
  17. void* param;
  18. } PthreadTask;
  19. void* pthread_wrapper(void* p) {
  20. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0x00);
  21. pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0x00);
  22. PthreadTask* task = (PthreadTask*)p;
  23. task->func(task->param);
  24. return NULL;
  25. }
  26. TaskHandle_t xTaskCreateStatic(
  27. TaskFunction_t pxTaskCode,
  28. const char* const pcName,
  29. const uint32_t ulStackDepth,
  30. void* const pvParameters,
  31. UBaseType_t uxPriority,
  32. StackType_t* const puxStackBuffer,
  33. StaticTask_t* const pxTaskBuffer) {
  34. TaskHandle_t thread = malloc(sizeof(TaskHandle_t));
  35. PthreadTask* task = malloc(sizeof(PthreadTask));
  36. task->func = pxTaskCode;
  37. task->param = pvParameters;
  38. pthread_create(thread, NULL, pthread_wrapper, (void*)task);
  39. return thread;
  40. }
  41. void vTaskDelete(TaskHandle_t xTask) {
  42. if(xTask == NULL) {
  43. // kill itself
  44. pthread_exit(NULL);
  45. }
  46. // maybe thread already join
  47. if(pthread_kill(*xTask, 0) == ESRCH) return;
  48. // send thread_child signal to stop it сигнал, который ее завершает
  49. pthread_cancel(*xTask);
  50. // wait for join and close descriptor
  51. pthread_join(*xTask, 0x00);
  52. // cleanup thread handler
  53. *xTask = 0;
  54. }
  55. TaskHandle_t xTaskGetCurrentTaskHandle(void) {
  56. TaskHandle_t thread = malloc(sizeof(TaskHandle_t));
  57. *thread = pthread_self();
  58. return thread;
  59. }
  60. bool task_equal(TaskHandle_t a, TaskHandle_t b) {
  61. if(a == NULL || b == NULL) return false;
  62. return pthread_equal(*a, *b) != 0;
  63. }
  64. BaseType_t xQueueSend(QueueHandle_t xQueue, const void* pvItemToQueue, TickType_t xTicksToWait) {
  65. // TODO: add implementation
  66. return pdTRUE;
  67. }
  68. BaseType_t xQueueReceive(QueueHandle_t xQueue, void* pvBuffer, TickType_t xTicksToWait) {
  69. // TODO: add implementation
  70. osDelay(100);
  71. return pdFALSE;
  72. }
  73. static uint32_t queue_global_id = 0;
  74. QueueHandle_t xQueueCreateStatic(
  75. UBaseType_t uxQueueLength,
  76. UBaseType_t uxItemSize,
  77. uint8_t* pucQueueStorageBuffer,
  78. StaticQueue_t* pxQueueBuffer) {
  79. // TODO: check this implementation
  80. int* msgid = malloc(sizeof(int));
  81. key_t key = queue_global_id;
  82. queue_global_id++;
  83. *msgid = msgget(key, IPC_CREAT);
  84. return (QueueHandle_t)msgid;
  85. }
  86. SemaphoreHandle_t xSemaphoreCreateCountingStatic(
  87. UBaseType_t uxMaxCount,
  88. UBaseType_t uxInitialCount,
  89. StaticSemaphore_t* pxSemaphoreBuffer) {
  90. pxSemaphoreBuffer->type = SemaphoreTypeCounting;
  91. pxSemaphoreBuffer->take_counter = 0;
  92. pxSemaphoreBuffer->give_counter = 0;
  93. return pxSemaphoreBuffer;
  94. }
  95. SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
  96. pxMutexBuffer->type = SemaphoreTypeMutex;
  97. pthread_mutex_init(&pxMutexBuffer->mutex, NULL);
  98. pxMutexBuffer->take_counter = 0;
  99. pxMutexBuffer->give_counter = 0;
  100. return pxMutexBuffer;
  101. }
  102. BaseType_t xSemaphoreTake(volatile SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
  103. if(xSemaphore == NULL) return pdFALSE;
  104. if(xSemaphore->type == SemaphoreTypeMutex) {
  105. if(xTicksToWait == portMAX_DELAY) {
  106. if(pthread_mutex_lock(&xSemaphore->mutex) == 0) {
  107. return pdTRUE;
  108. } else {
  109. return pdFALSE;
  110. }
  111. } else {
  112. TickType_t ticks = xTicksToWait;
  113. while(ticks >= 0) {
  114. if(pthread_mutex_trylock(&xSemaphore->mutex) == 0) {
  115. return pdTRUE;
  116. }
  117. if(ticks > 0) {
  118. osDelay(1);
  119. }
  120. ticks--;
  121. }
  122. return pdFALSE;
  123. }
  124. }
  125. // TODO: need to add inter-process sync or use POSIX primitives
  126. xSemaphore->take_counter++;
  127. TickType_t ticks = xTicksToWait;
  128. while(xSemaphore->take_counter != xSemaphore->give_counter &&
  129. (ticks > 0 || xTicksToWait == portMAX_DELAY)) {
  130. osDelay(1);
  131. ticks--;
  132. }
  133. if(xTicksToWait != 0 && ticks == 0) return pdFALSE;
  134. return pdTRUE;
  135. }
  136. BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
  137. if(xSemaphore == NULL) return pdFALSE;
  138. if(xSemaphore->type == SemaphoreTypeMutex) {
  139. if(pthread_mutex_unlock(&xSemaphore->mutex) == 0) {
  140. return pdTRUE;
  141. } else {
  142. return pdFALSE;
  143. }
  144. }
  145. // TODO: need to add inter-process sync or use POSIX primitives
  146. xSemaphore->give_counter++;
  147. return pdTRUE;
  148. }
  149. #define TLS_ITEM_COUNT 1
  150. static pthread_key_t tls_keys[TLS_ITEM_COUNT];
  151. static pthread_once_t tls_keys_once = PTHREAD_ONCE_INIT;
  152. static void create_tls_keys() {
  153. for(size_t i = 0; i < TLS_ITEM_COUNT; i++) {
  154. pthread_key_create(&tls_keys[i], NULL);
  155. }
  156. }
  157. void* pvTaskGetThreadLocalStoragePointer(TaskHandle_t xTaskToQuery, BaseType_t xIndex) {
  158. // Non-current task TLS access is not allowed
  159. if(xTaskToQuery != NULL) {
  160. return NULL;
  161. }
  162. if(xIndex >= TLS_ITEM_COUNT) {
  163. return NULL;
  164. }
  165. pthread_once(&tls_keys_once, create_tls_keys);
  166. return pthread_getspecific(tls_keys[xIndex]);
  167. }
  168. void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void* pvValue) {
  169. // Non-current task TLS access is not allowed
  170. if(xTaskToSet != NULL) {
  171. return;
  172. }
  173. if(xIndex >= TLS_ITEM_COUNT) {
  174. return;
  175. }
  176. pthread_once(&tls_keys_once, create_tls_keys);
  177. pthread_setspecific(tls_keys[xIndex], pvValue);
  178. }