lo_os.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. BaseType_t xQueueSend(QueueHandle_t xQueue, const void* pvItemToQueue, TickType_t xTicksToWait) {
  61. // TODO: add implementation
  62. return pdTRUE;
  63. }
  64. BaseType_t xQueueReceive(QueueHandle_t xQueue, void* pvBuffer, TickType_t xTicksToWait) {
  65. // TODO: add implementation
  66. osDelay(100);
  67. return pdFALSE;
  68. }
  69. static uint32_t queue_global_id = 0;
  70. QueueHandle_t xQueueCreateStatic(
  71. UBaseType_t uxQueueLength,
  72. UBaseType_t uxItemSize,
  73. uint8_t* pucQueueStorageBuffer,
  74. StaticQueue_t* pxQueueBuffer) {
  75. // TODO: check this implementation
  76. int* msgid = malloc(sizeof(int));
  77. key_t key = queue_global_id;
  78. queue_global_id++;
  79. *msgid = msgget(key, IPC_CREAT);
  80. return (QueueHandle_t)msgid;
  81. }
  82. QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize) {
  83. return xQueueCreateStatic(uxQueueLength, uxItemSize, 0, NULL);
  84. }
  85. SemaphoreHandle_t xSemaphoreCreateCountingStatic(
  86. UBaseType_t uxMaxCount,
  87. UBaseType_t uxInitialCount,
  88. StaticSemaphore_t* pxSemaphoreBuffer) {
  89. pxSemaphoreBuffer->type = SemaphoreTypeCounting;
  90. pxSemaphoreBuffer->take_counter = 0;
  91. pxSemaphoreBuffer->give_counter = 0;
  92. return pxSemaphoreBuffer;
  93. }
  94. SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t* pxMutexBuffer) {
  95. pxMutexBuffer->type = SemaphoreTypeMutex;
  96. pthread_mutex_init(&pxMutexBuffer->mutex, NULL);
  97. pxMutexBuffer->take_counter = 0;
  98. pxMutexBuffer->give_counter = 0;
  99. return pxMutexBuffer;
  100. }
  101. BaseType_t xSemaphoreTake(volatile SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait) {
  102. if(xSemaphore == NULL) return pdFALSE;
  103. if(xSemaphore->type == SemaphoreTypeMutex) {
  104. if(xTicksToWait == portMAX_DELAY) {
  105. if(pthread_mutex_lock(&xSemaphore->mutex) == 0) {
  106. return pdTRUE;
  107. } else {
  108. return pdFALSE;
  109. }
  110. } else {
  111. TickType_t ticks = xTicksToWait;
  112. while(ticks >= 0) {
  113. if(pthread_mutex_trylock(&xSemaphore->mutex) == 0) {
  114. return pdTRUE;
  115. }
  116. if(ticks > 0) {
  117. osDelay(1);
  118. }
  119. ticks--;
  120. }
  121. return pdFALSE;
  122. }
  123. }
  124. // TODO: need to add inter-process sync or use POSIX primitives
  125. xSemaphore->take_counter++;
  126. TickType_t ticks = xTicksToWait;
  127. while(xSemaphore->take_counter != xSemaphore->give_counter &&
  128. (ticks > 0 || xTicksToWait == portMAX_DELAY)) {
  129. osDelay(1);
  130. ticks--;
  131. }
  132. if(xTicksToWait != 0 && ticks == 0) return pdFALSE;
  133. return pdTRUE;
  134. }
  135. BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore) {
  136. if(xSemaphore == NULL) return pdFALSE;
  137. if(xSemaphore->type == SemaphoreTypeMutex) {
  138. if(pthread_mutex_unlock(&xSemaphore->mutex) == 0) {
  139. return pdTRUE;
  140. } else {
  141. return pdFALSE;
  142. }
  143. }
  144. // TODO: need to add inter-process sync or use POSIX primitives
  145. xSemaphore->give_counter++;
  146. return pdTRUE;
  147. }
  148. #define TLS_ITEM_COUNT 1
  149. static pthread_key_t tls_keys[TLS_ITEM_COUNT];
  150. static pthread_once_t tls_keys_once = PTHREAD_ONCE_INIT;
  151. static void create_tls_keys() {
  152. for(size_t i = 0; i < TLS_ITEM_COUNT; i++) {
  153. pthread_key_create(&tls_keys[i], NULL);
  154. }
  155. }
  156. void* pvTaskGetThreadLocalStoragePointer(TaskHandle_t xTaskToQuery, BaseType_t xIndex) {
  157. // Non-current task TLS access is not allowed
  158. if(xTaskToQuery != NULL) {
  159. return NULL;
  160. }
  161. if(xIndex >= TLS_ITEM_COUNT) {
  162. return NULL;
  163. }
  164. pthread_once(&tls_keys_once, create_tls_keys);
  165. return pthread_getspecific(tls_keys[xIndex]);
  166. }
  167. void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void* pvValue) {
  168. // Non-current task TLS access is not allowed
  169. if(xTaskToSet != NULL) {
  170. return;
  171. }
  172. if(xIndex >= TLS_ITEM_COUNT) {
  173. return;
  174. }
  175. pthread_once(&tls_keys_once, create_tls_keys);
  176. pthread_setspecific(tls_keys[xIndex], pvValue);
  177. }
  178. osMutexId_t osMutexNew(const osMutexAttr_t *attr) {
  179. StaticSemaphore_t* pxMutexBuffer = malloc(sizeof(StaticSemaphore_t));
  180. xSemaphoreCreateMutexStatic(pxMutexBuffer);
  181. return (osMutexId_t)pxMutexBuffer;
  182. }
  183. osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) {
  184. if(xSemaphoreTake((SemaphoreHandle_t)mutex_id, (TickType_t)timeout) == pdTRUE) {
  185. return osOK;
  186. } else {
  187. return osErrorTimeout;
  188. }
  189. }
  190. osStatus_t osMutexRelease (osMutexId_t mutex_id) {
  191. if(xSemaphoreGive((SemaphoreHandle_t)mutex_id) == pdTRUE) {
  192. return osOK;
  193. } else {
  194. return osError;
  195. }
  196. }
  197. osStatus_t osMutexDelete (osMutexId_t mutex_id) {
  198. osMutexRelease(mutex_id);
  199. int res = 0;
  200. if((res = pthread_mutex_destroy(&mutex_id->mutex)) == 0) {
  201. return osOK;
  202. } else {
  203. printf("res = %d\n", res);
  204. return osError;
  205. }
  206. }
  207. osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) {
  208. if(max_count != 1) {
  209. // Non-binary semaphors are not supported at the moment
  210. return NULL;
  211. }
  212. if(attr != NULL) {
  213. // Attributes are not supported at the moment
  214. return NULL;
  215. }
  216. SemaphoreHandle_t handle = osMutexNew(NULL);
  217. if(handle == NULL) return NULL;
  218. if(initial_count == 0) {
  219. xSemaphoreTake(handle, 0);
  220. }
  221. return handle;
  222. }
  223. osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) {
  224. if(semaphore_id == NULL) {
  225. return osErrorParameter;
  226. }
  227. if(xSemaphoreTake(semaphore_id, timeout) == pdTRUE) {
  228. return osOK;
  229. } else {
  230. return osErrorTimeout;
  231. }
  232. }
  233. osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) {
  234. if(semaphore_id == NULL) {
  235. return osErrorParameter;
  236. }
  237. if(xSemaphoreGive(semaphore_id) == pdTRUE) {
  238. return osOK;
  239. } else {
  240. return osErrorTimeout;
  241. }
  242. }
  243. osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) {
  244. if(semaphore_id == NULL) {
  245. return osErrorParameter;
  246. }
  247. return osMutexDelete(semaphore_id);
  248. }