lo_os.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. ) {
  35. TaskHandle_t thread = malloc(sizeof(TaskHandle_t));
  36. PthreadTask* task = malloc(sizeof(PthreadTask));
  37. task->func = pxTaskCode;
  38. task->param = pvParameters;
  39. pthread_create(thread, NULL, pthread_wrapper, (void*)task);
  40. return thread;
  41. }
  42. void vTaskDelete(TaskHandle_t xTask) {
  43. if(xTask == NULL) {
  44. // kill itself
  45. pthread_exit(NULL);
  46. }
  47. // maybe thread already join
  48. if (pthread_kill(*xTask, 0) == ESRCH) return;
  49. // send thread_child signal to stop it сигнал, который ее завершает
  50. pthread_cancel(*xTask);
  51. // wait for join and close descriptor
  52. pthread_join(*xTask, 0x00);
  53. // cleanup thread handler
  54. *xTask = 0;
  55. }
  56. TaskHandle_t xTaskGetCurrentTaskHandle(void) {
  57. TaskHandle_t thread = malloc(sizeof(TaskHandle_t));
  58. *thread = pthread_self();
  59. return thread;
  60. }
  61. bool task_equal(TaskHandle_t a, TaskHandle_t b) {
  62. if(a == NULL || b == NULL) return false;
  63. return pthread_equal(*a, *b) != 0;
  64. }
  65. BaseType_t xQueueSend(
  66. QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait
  67. ) {
  68. // TODO: add implementation
  69. return pdTRUE;
  70. }
  71. BaseType_t xQueueReceive(
  72. QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait
  73. ) {
  74. // TODO: add implementation
  75. osDelay(100);
  76. return pdFALSE;
  77. }
  78. static uint32_t queue_global_id = 0;
  79. QueueHandle_t xQueueCreateStatic(
  80. UBaseType_t uxQueueLength,
  81. UBaseType_t uxItemSize,
  82. uint8_t* pucQueueStorageBuffer,
  83. StaticQueue_t *pxQueueBuffer
  84. ) {
  85. // TODO: check this implementation
  86. int* msgid = malloc(sizeof(int));
  87. key_t key = queue_global_id;
  88. queue_global_id++;
  89. *msgid = msgget(key, IPC_CREAT);
  90. return (QueueHandle_t)msgid;
  91. }
  92. SemaphoreHandle_t xSemaphoreCreateCountingStatic(
  93. UBaseType_t uxMaxCount,
  94. UBaseType_t uxInitialCount,
  95. StaticSemaphore_t* pxSemaphoreBuffer
  96. ) {
  97. pxSemaphoreBuffer->type = SemaphoreTypeCounting;
  98. pxSemaphoreBuffer->take_counter = 0;
  99. pxSemaphoreBuffer->give_counter = 0;
  100. return pxSemaphoreBuffer;
  101. }
  102. SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
  103. pxMutexBuffer->type = SemaphoreTypeMutex;
  104. pthread_mutex_init(&pxMutexBuffer->mutex, NULL);
  105. pxMutexBuffer->take_counter = 0;
  106. pxMutexBuffer->give_counter = 0;
  107. return pxMutexBuffer;
  108. }
  109. BaseType_t xSemaphoreTake(volatile SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
  110. if(xSemaphore == NULL) return pdFALSE;
  111. if (xSemaphore->type == SemaphoreTypeMutex) {
  112. if (xTicksToWait == portMAX_DELAY) {
  113. if (pthread_mutex_lock(&xSemaphore->mutex) == 0) {
  114. return pdTRUE;
  115. } else {
  116. return pdFALSE;
  117. }
  118. } else {
  119. TickType_t ticks = xTicksToWait;
  120. while (ticks >= 0) {
  121. if (pthread_mutex_trylock(&xSemaphore->mutex) == 0) {
  122. return pdTRUE;
  123. }
  124. if (ticks > 0) {
  125. osDelay(1);
  126. }
  127. ticks--;
  128. }
  129. return pdFALSE;
  130. }
  131. }
  132. // TODO: need to add inter-process sync or use POSIX primitives
  133. xSemaphore->take_counter++;
  134. TickType_t ticks = xTicksToWait;
  135. while(
  136. xSemaphore->take_counter != xSemaphore->give_counter
  137. && (ticks > 0 || xTicksToWait == portMAX_DELAY)
  138. ) {
  139. osDelay(1);
  140. ticks--;
  141. }
  142. if(xTicksToWait != 0 && ticks == 0) return pdFALSE;
  143. return pdTRUE;
  144. }
  145. BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
  146. if(xSemaphore == NULL) return pdFALSE;
  147. if (xSemaphore->type == SemaphoreTypeMutex) {
  148. if (pthread_mutex_unlock(&xSemaphore->mutex) == 0) {
  149. return pdTRUE;
  150. } else {
  151. return pdFALSE;
  152. }
  153. }
  154. // TODO: need to add inter-process sync or use POSIX primitives
  155. xSemaphore->give_counter++;
  156. return pdTRUE;
  157. }