lo_os.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize) {
  87. return xQueueCreateStatic(uxQueueLength, uxItemSize, 0, NULL);
  88. }
  89. SemaphoreHandle_t xSemaphoreCreateCountingStatic(
  90. UBaseType_t uxMaxCount,
  91. UBaseType_t uxInitialCount,
  92. StaticSemaphore_t* pxSemaphoreBuffer) {
  93. pxSemaphoreBuffer->type = SemaphoreTypeCounting;
  94. pxSemaphoreBuffer->take_counter = 0;
  95. pxSemaphoreBuffer->give_counter = 0;
  96. return pxSemaphoreBuffer;
  97. }
  98. SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
  99. pxMutexBuffer->type = SemaphoreTypeMutex;
  100. pthread_mutex_init(&pxMutexBuffer->mutex, NULL);
  101. pxMutexBuffer->take_counter = 0;
  102. pxMutexBuffer->give_counter = 0;
  103. return pxMutexBuffer;
  104. }
  105. BaseType_t xSemaphoreTake(volatile SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
  106. if(xSemaphore == NULL) return pdFALSE;
  107. if(xSemaphore->type == SemaphoreTypeMutex) {
  108. if(xTicksToWait == portMAX_DELAY) {
  109. if(pthread_mutex_lock(&xSemaphore->mutex) == 0) {
  110. return pdTRUE;
  111. } else {
  112. return pdFALSE;
  113. }
  114. } else {
  115. TickType_t ticks = xTicksToWait;
  116. while(ticks >= 0) {
  117. if(pthread_mutex_trylock(&xSemaphore->mutex) == 0) {
  118. return pdTRUE;
  119. }
  120. if(ticks > 0) {
  121. osDelay(1);
  122. }
  123. ticks--;
  124. }
  125. return pdFALSE;
  126. }
  127. }
  128. // TODO: need to add inter-process sync or use POSIX primitives
  129. xSemaphore->take_counter++;
  130. TickType_t ticks = xTicksToWait;
  131. while(xSemaphore->take_counter != xSemaphore->give_counter &&
  132. (ticks > 0 || xTicksToWait == portMAX_DELAY)) {
  133. osDelay(1);
  134. ticks--;
  135. }
  136. if(xTicksToWait != 0 && ticks == 0) return pdFALSE;
  137. return pdTRUE;
  138. }
  139. BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
  140. if(xSemaphore == NULL) return pdFALSE;
  141. if(xSemaphore->type == SemaphoreTypeMutex) {
  142. if(pthread_mutex_unlock(&xSemaphore->mutex) == 0) {
  143. return pdTRUE;
  144. } else {
  145. return pdFALSE;
  146. }
  147. }
  148. // TODO: need to add inter-process sync or use POSIX primitives
  149. xSemaphore->give_counter++;
  150. return pdTRUE;
  151. }
  152. #define TLS_ITEM_COUNT 1
  153. static pthread_key_t tls_keys[TLS_ITEM_COUNT];
  154. static pthread_once_t tls_keys_once = PTHREAD_ONCE_INIT;
  155. static void create_tls_keys() {
  156. for(size_t i = 0; i < TLS_ITEM_COUNT; i++) {
  157. pthread_key_create(&tls_keys[i], NULL);
  158. }
  159. }
  160. void* pvTaskGetThreadLocalStoragePointer(TaskHandle_t xTaskToQuery, BaseType_t xIndex) {
  161. // Non-current task TLS access is not allowed
  162. if(xTaskToQuery != NULL) {
  163. return NULL;
  164. }
  165. if(xIndex >= TLS_ITEM_COUNT) {
  166. return NULL;
  167. }
  168. pthread_once(&tls_keys_once, create_tls_keys);
  169. return pthread_getspecific(tls_keys[xIndex]);
  170. }
  171. void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void* pvValue) {
  172. // Non-current task TLS access is not allowed
  173. if(xTaskToSet != NULL) {
  174. return;
  175. }
  176. if(xIndex >= TLS_ITEM_COUNT) {
  177. return;
  178. }
  179. pthread_once(&tls_keys_once, create_tls_keys);
  180. pthread_setspecific(tls_keys[xIndex], pvValue);
  181. }
  182. osMutexId_t osMutexNew(const osMutexAttr_t *attr) {
  183. StaticSemaphore_t* pxMutexBuffer = malloc(sizeof(StaticSemaphore_t));
  184. xSemaphoreCreateMutexStatic(pxMutexBuffer);
  185. return (osMutexId_t)pxMutexBuffer;
  186. }
  187. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) {
  188. if(xSemaphoreTake((SemaphoreHandle_t)mutex_id, (TickType_t)timeout) == pdTRUE) {
  189. return osOK;
  190. } else {
  191. return osErrorTimeout;
  192. }
  193. }
  194. osStatus_t osMutexRelease (osMutexId_t mutex_id) {
  195. if(xSemaphoreGive((SemaphoreHandle_t)mutex_id) == pdTRUE) {
  196. return osOK;
  197. } else {
  198. return osError;
  199. }
  200. }
  201. osStatus_t osMutexDelete (osMutexId_t mutex_id) {
  202. osMutexRelease(mutex_id);
  203. int res = 0;
  204. if((res = pthread_mutex_destroy(&mutex_id->mutex)) == 0) {
  205. return osOK;
  206. } else {
  207. printf("res = %d\n", res);
  208. return osError;
  209. }
  210. }