{"id":46232706,"url":"https://github.com/sufst/rtcan","last_synced_at":"2026-03-03T18:10:56.550Z","repository":{"id":116125500,"uuid":"595835028","full_name":"sufst/rtcan","owner":"sufst","description":"ThreadX RTOS service for managing concurrent access to CAN peripherals on STM32 microcontrollers","archived":false,"fork":false,"pushed_at":"2025-04-04T18:34:50.000Z","size":50,"stargazers_count":3,"open_issues_count":16,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T19:44:41.190Z","etag":null,"topics":["can","rtos","stm32","threadx"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sufst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-31T22:45:08.000Z","updated_at":"2025-04-04T18:34:53.000Z","dependencies_parsed_at":"2025-04-04T19:42:30.050Z","dependency_job_id":"29475c4d-cd14-47ef-b168-4338db8e9026","html_url":"https://github.com/sufst/rtcan","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sufst/rtcan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufst%2Frtcan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufst%2Frtcan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufst%2Frtcan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufst%2Frtcan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sufst","download_url":"https://codeload.github.com/sufst/rtcan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sufst%2Frtcan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30054110,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T17:46:22.538Z","status":"ssl_error","status_checked_at":"2026-03-03T17:46:22.036Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["can","rtos","stm32","threadx"],"created_at":"2026-03-03T18:10:56.126Z","updated_at":"2026-03-03T18:10:56.542Z","avatar_url":"https://github.com/sufst.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RTCAN\n\n\u003e :warning: This system is in early development. It is functional at a basic level, but expect bugs!\n\n## About\n\nRTCAN (Real-Time CAN) is a [ThreadX RTOS](https://learn.microsoft.com/en-us/azure/rtos/threadx/overview-threadx) \nservice for managing concurrent access to CAN peripherals on [STM32 microcontrollers](https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html).\n\nFeatures:\n- Background thread based ThreadX service.\n- FIFO transmit queuing.\n- \"Subscription\" style receiving functionality.\n\nPlanned features:\n- Automatic CAN filter configuration management.\n- Priority queueing for transmissions.\n\nNot currently supported:\n- STM32 FDCAN HAL.\n- Extended CAN identifiers.\n\n## Dependencies\n\n- C11 compiler.\n- 32 bit STM32 microcontroller.\n- ThreadX memory pool, thread, semaphore and queue services.\n- STM32 Hardware Abstraction Layer (HAL) CAN drivers.\n\n## Adding to a Project\n\n### Submodule\n\nAdd this repository as a submodule using:\n\n```sh\ngit submodule add https://github.com/sufst/rtcan\n```\n\nMake sure to change directories to the location you want the submodule to exist\nin the project source tree. Note that the use of submodules will require the \nfollowing commands to be run when cloning a project for the first time:\n\n```sh\ngit submodule init\ngit submodule update\n```\n\nFor more information on submodules, see the [Git submodule documentation](https://git-scm.com/book/en/v2/Git-Tools-Submodules).\n\n### Build System\n\nRTCAN consists of one header file (`inc/rtcan.h`) which should be added to the\ninclude path for a project (or just to specific files requiring RTCAN), \nand one source file (`src/rtcan.c`) which should be compiled by the build system\nin question. Make sure the [RTCAN dependencies](#dependencies) are satisfied.\n\n## Usage\n\n### Initialisation\n\nRTCAN is provided for a CAN peripheral by an instance of `rtcan_handle_t` which\nis initialised with the function `rtcan_init()`. Each RTCAN instance manages\none CAN peripheral and has two background service threads: one for transmitting\nand one for receiving.\n\n### Transmitting\n\nThe `rtcan_transmit()` function uses a simple FIFO queueing system to transmit\nmessages with the CAN peripheral. This provides a way of ensuring that there is \nnot contention for the CAN peripheral by multiple threads. \n\nTo use the transmit service, CAN Tx interrupts must be enabled and the \n`HAL_CAN_TxMailbox\u003cN\u003eCompleteCallback` must be implemented to call \n`rtcan_handle_tx_mailbox_callback` (for all `N`). For example, for the\nHAL callback for Tx mailbox 1:\n\n```c\nstatic rtcan_handle_t rtcan;\n\nvoid HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_tx_mailbox_callback(\u0026rtcan, can_h);\n}\n```\n\n### Receiving and Subscriptions\n\nReceiving functionality in RTCAN is based around a \"publisher\" / \"subscriber\"\nmodel in which application threads can register their interest in receiving\nCAN messages with a particular ID through the `rtcan_subscribe()` function.\nThreads must provide a queue as an endpoint for messages where queue items have\nsize `TX_1_ULONG`. Incoming CAN messages are published to the queue by the RTCAN\nservice, where each queue item is a pointer to the received message represented \nas an `rtcan_msg_t` struct. Once a subscriber has finished with a message, it \n**must** call the `rtcan_msg_consumed()` function to indicate this to the service.\nInternally `rtcan_msg_t` is a reference counted, dynamically allocated data\nstructure which is distributed to all the subscribers of a given CAN ID. \nAs such, subscribers must treat this message as **read only** and should\nnot modify the `reference_count` field.\n\nTo use the receive service, CAN Rx interrupts must be enabled and the \n`HAL_CAN_RxFifo\u003cN\u003eMsgPendingCallback` must be implemented to call \n`rtcan_handle_rx_it` (for all `N`). For example, for the\nHAL callback for Rx FIFO 1:\n\n```c\nstatic rtcan_handle_t rtcan;\n\nvoid HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_rx_it(\u0026rtcan, can_h, 1);\n}\n```\n\n### CAN Errors\n\nIf CAN transmit errors occur, RTCAN must be notified through the `rtcan_handle_hal_error()`\nfunction when `HAL_CAN_ErrorCallback()` is called.\n\n```c\nstatic rtcan_handle_t rtcan;\n\nvoid HAL_CAN_ErrorCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_hal_error(\u0026rtcan, can_h);\n}\n```\n\nFailure to do so will mean the RTCAN transmit service is no longer able to\ntransmit messages. Note that it is not necessary to check that the CAN handle\nmatches that of the RTCAN instance, this is done automatically by RTCAN.\n\n### Error Codes\n\nAll functions in the RTCAN API return a status code (`rtcan_status_t`) \nindicating the RTCAN error state. `RTCAN_OK` indicates no error and \n`RTCAN_ERROR` indicates an error. The specific error can be checked with the\nreturn value of `rtcan_get_error()`. This design is based around the conventions\nof the STM32 HAL.\n\n### Example\n\nThe following example uses RTCAN to subscribe to CAN messages with ID `0x100`\nand re-transmit the data as a CAN message with ID `0x101`.\n\n```c\n#include \"tx_api.h\"\n#include \"rtcan.h\"\n#include \"can.h\"\n#include \"string.h\" // for memcpy()\n\n#define RTCAN_THREAD_PRIORITY   3\n#define MY_THREAD_PRIORITY      4\n#define MY_THREAD_STACK_SIZE    1024\n\nstatic rtcan_handle_t rtcan;\nstatic TX_THREAD my_thread;\nstatic TX_QUEUE rx_queue;\nstatic ULONG rx_queue_mem[10];\n\nstatic void my_thread_entry(ULONG thread_input);\n\n/**\n * initialise a thread which will use RTCAN services\n */\nvoid init_my_thread(TX_BYTE_POOL* app_mem_pool)\n{\n    // initialise RTCAN instance\n    rtcan_init(\u0026rtcan, \n               \u0026hcan1, \n               RTCAN_THREAD_PRIORITY, \n               app_mem_pool);\n\n    // allocate memory for thread\n    void* stack_ptr;\n    tx_byte_allocate(app_mem_pool,\n                     \u0026stack_ptr,\n                     MY_THREAD_STACK_SIZE,\n                     TX_NO_WAIT);\n\n    // create thread\n    tx_thread_create(\u0026my_thread,\n                     my_thread_entry,\n                     NULL,\n                     stack_ptr,\n                     MY_THREAD_STACK_SIZE,\n                     MY_THREAD_PRIORITY,\n                     MY_THREAD_PRIORITY,\n                     TX_NO_TIME_SLICE,\n                     TX_AUTO_START);\n\n    // subscribe to a message\n    tx_queue_create(\u0026rx_queue,\n                    \"My Rx Queue\",\n                    TX_1_ULONG,\n                    rx_queue_mem,\n                    sizeof(rx_queue));\n\n    rtcan_subscribe(\u0026rtcan, 0x100, \u0026rx_queue);\n\n    // start the RTCAN service\n    rtcan_start(\u0026rtcan);\n}\n\n/**\n * thread which uses RTCAN services\n */\nvoid my_thread_entry(ULONG thread_input)\n{\n    (void) thread_input; // unused\n\n    while (1)\n    {\n        // wait for an item to enter the rx queue\n        rtcan_msg_t* msg_ptr;\n\n        tx_queue_receive(\u0026rx_queue, \n                         (void*) \u0026msg_ptr, \n                         TX_WAIT_FOREVER);\n\n        // make a copy of the message but change the ID to 0x101\n        rtcan_msg_t new_message;\n        new_message.identifier = 0x101;\n        new_message.length = message_ptr-\u003elength;\n        memcpy((void*) new_message.data, (void*) message_ptr-\u003edata, msg_ptr-\u003elength);\n\n        // transmit the copied message\n        rtcan_transmit(\u0026rtcan, \u0026new_message);\n\n        // mark the original received message as consumed\n        rtcan_msg_consumed(\u0026rtcan, msg_ptr);\n    }\n}\n\n/**\n * implement HAL CAN callbacks to call RTCAN handler functions\n * \n * note: specific callbacks depend on CAN capabilities of target STM32\n */\nvoid HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_tx_mailbox_callback(\u0026rtcan, can_h);\n}\n\nvoid HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_tx_mailbox_callback(\u0026rtcan, can_h);\n}\n\nvoid HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_tx_mailbox_callback(\u0026rtcan, can_h);\n}\n\nvoid HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_rx_it(\u0026rtcan, can_h, 0);\n}\n\nvoid HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* can_h)\n{\n    rtcan_handle_rx_it(\u0026rtcan, can_h, 1);\n}\n\n```\n\n\u003e Checking of return codes has been omitted here for brevity. In practice,\n  you should always check the return codes of both ThreadX and RTCAN \n  functions.\n\n## Other Platforms\n\nThis implementation was developed for the STM32 platform, however it should be\nrelatively simple to port to another platform with a different HAL. A similar\nsystem could also be implemented with another RTOS so long as it provides \nequivalent services to ThreadX.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsufst%2Frtcan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsufst%2Frtcan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsufst%2Frtcan/lists"}