Difference between revisions of "Zephyr rtos threads"
m |
m (→^ Example Zephyr Thread Creation: - rename section, remove some older content) |
||
(21 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | Keywords: Zephyr thread analyzer module :: thread resource use :: thread stack monitoring | ||
+ | |||
+ | |||
+ | |||
+ | == [[#top|^]] OVERVIEW == | ||
+ | |||
+ | Kinda limited tutorials on Zephyr RTOS threads, but seemingly solid documentation on zephyrproject.org site. A specific example starting point may be among Zephyr source tree's [https://github.com/zephyrproject-rtos/zephyr/tree/main/drivers samples directory] . . . `$ grep -nr k_thread_create ./*` shows thread creation in a SPI Bluetooth driver sample. Path from root Zephyr RTOS source tree is <code>zephyr/drivers/bluetooth/hci</code>. | ||
+ | |||
+ | Also worth noting Zephyr provides a [https://docs.zephyrproject.org/2.6.0/guides/flash_debug/thread-analyzer.html thread analyzer module] for Zephyr based apps. | ||
+ | |||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] Latest == | ||
+ | |||
+ | 0311 | ||
+ | * https://docs.zephyrproject.org/2.6.0/reference/kernel/threads/system_threads.html | ||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] New Zephyr Project Documentation Pages to Learn == | ||
+ | |||
+ | * https://docs.zephyrproject.org/apidoc/latest/group__thread__stack__api.html | ||
+ | |||
+ | * https://docs.zephyrproject.org/apidoc/latest/group__task__wdt__api.html | ||
+ | |||
+ | * https://docs.zephyrproject.org/apidoc/latest/group__thread__analyzer.html | ||
+ | <ul> | ||
+ | * https://docs.zephyrproject.org/apidoc/latest/group__thread__analyzer.html#ga9ff07e2eff100f4b8c79440483c89836 | ||
+ | </ul> | ||
+ | |||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | <b>Passing data between Zephyr threads:</b><br /> | ||
+ | On this top level page there is mention of passing data between threads: | ||
+ | * https://docs.zephyrproject.org/2.6.0/reference/kernel/index.html | ||
+ | |||
+ | * https://docs.zephyrproject.org/1.9.0/kernel/data_passing/data_passing.html | ||
+ | |||
+ | * https://docs.zephyrproject.org/latest/reference/kernel/index.html?highlight=pass%20data | ||
+ | |||
+ | * https://docs.zephyrproject.org/2.6.0/reference/kernel/index.html?highlight=pass%20data | ||
+ | |||
+ | Zephyr queues: | ||
+ | * https://docs.zephyrproject.org/2.6.0/reference/kernel/data_passing/queues.html | ||
+ | |||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] Zephyr RTOS Thread API == | ||
Some Zephyr RTOS API functions to learn: | Some Zephyr RTOS API functions to learn: | ||
Line 5: | Line 56: | ||
* k_sem_take(<e_connected, K_FOREVER); | * k_sem_take(<e_connected, K_FOREVER); | ||
* k_work_schedule(&connect_work, K_NO_WAIT); | * k_work_schedule(&connect_work, K_NO_WAIT); | ||
+ | </ul> | ||
+ | |||
+ | Additionally some further Zephyr thread entities and mostly API functions include: | ||
+ | <ul> | ||
+ | * k_thread | ||
+ | * K_THREAD_STACK versus K_KERNEL_STACK | ||
+ | * k_thread_create() | ||
+ | * k_thread_ | ||
+ | * k_thread_join() | ||
+ | * k_thread_abort() | ||
+ | * k_thread_suspend() | ||
+ | * k_thread_resume() | ||
+ | Thread options K_ESSENTIAL, K_SSE_REGS and more . . . | ||
+ | * | ||
</ul> | </ul> | ||
Line 21: | Line 86: | ||
== [[#top|^]] Specific Zephyr documentation pages == | == [[#top|^]] Specific Zephyr documentation pages == | ||
+ | * https://docs.zephyrproject.org/latest/reference/kernel/threads/index.html#lifecycle | ||
* https://docs.zephyrproject.org/latest/reference/kernel/threads/workqueue.html?highlight=k_work_reschedule#c.k_work_reschedule | * https://docs.zephyrproject.org/latest/reference/kernel/threads/workqueue.html?highlight=k_work_reschedule#c.k_work_reschedule | ||
+ | |||
+ | Following example code block matches k_thread_create() code in zephyr/drivers/bluetooth/hci/spi.c:519: | ||
+ | * https://docs.zephyrproject.org/latest/reference/kernel/threads/index.html#spawning-a-thread | ||
+ | |||
<!-- comment --> | <!-- comment --> | ||
− | == [[#top|^]] | + | == [[#top|^]] Zephyr Thread Creation == |
− | + | ||
+ | 2023-08-11 note - Threads in Zephyr may be created a couple of ways. One involves an API call, and the other way involves a macro which expands to the thread creation code at compile time. There are some constraints on creating threads via the API, that is at run time rather than compile time, which also generally implies that a user side or application. These constraints detailed at: | ||
+ | |||
+ | * https://docs.zephyrproject.org/3.4.0/kernel/services/threads/index.html#user-mode-constraints | ||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] Specific Function Associated With Zephyr Thread == | ||
+ | |||
+ | <pre> | ||
+ | 150 static void connect_work_fn(struct k_work *work) | ||
+ | 151 { | ||
+ | 152 int err; | ||
+ | 153 | ||
+ | 154 if (cloud_connected) { | ||
+ | 155 return; | ||
+ | 156 } | ||
+ | 157 | ||
+ | 158 err = aws_iot_connect(NULL); | ||
+ | 159 if (err) { | ||
+ | 160 printk("aws_iot_connect, error: %d\n", err); | ||
+ | 161 } | ||
+ | 162 | ||
+ | 163 printk("Next connection retry in %d seconds\n", | ||
+ | 164 CONFIG_CONNECTION_RETRY_TIMEOUT_SECONDS); | ||
+ | 165 | ||
+ | 166 k_work_schedule(&connect_work, | ||
+ | 167 K_SECONDS(CONFIG_CONNECTION_RETRY_TIMEOUT_SECONDS)); | ||
+ | 168 } | ||
+ | </pre> | ||
+ | |||
<pre> | <pre> | ||
− | |||
− | |||
− | |||
− | |||
150:static void connect_work_fn(struct k_work *work) | 150:static void connect_work_fn(struct k_work *work) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
338: k_work_init_delayable(&connect_work, connect_work_fn); | 338: k_work_init_delayable(&connect_work, connect_work_fn); | ||
− | + | </pre> | |
− | + | ||
− | + | ||
− | + | <!-- comment --> | |
− | + | ||
+ | == [[#top|^]] Issue with Counter Timer in Zephyr Thread - dwt.h == | ||
+ | |||
+ | <pre> | ||
+ | 5���_�_yϗ���Uߗ���5�_]����������Օ���}����ߧ�߿��ϯ���U�����u�����u�����U����u����������������땥����]��w����w����w�����u�7�w�U���u���W� * | ||
+ | The AWS IoT sample started, version: v1.0.0 | ||
+ | Zephyr thread create routine returns 536955992 for LED blink thread, | ||
+ | - SUCCESS - found Kionix accelerometer and device is ready | ||
+ | uart task at loop iteration 0x00000000 | ||
+ | LTE cell changed: Cell ID: -1, Tracking area: -1 | ||
+ | uart task at loop iteration 0x00000001 | ||
+ | uart task at loop iteration 0x00000002 | ||
+ | thread_kionix_accel - Kionix sensor reports manufacturer ID string: " K i o n " | ||
+ | ( spaces added around characters, ID four bytes long. ) | ||
+ | |||
+ | *** | ||
+ | *** TEST 2p1 | ||
+ | *** X accel 184, Y accel 65341, Z accel 16409 | ||
+ | *** | ||
+ | ASSERTION FAIL @ WEST_TOPDIR/zephyr/arch/arm/include/aarch32/cortex_m/dwt.h:103 | ||
+ | E: r0/a1: 0x00000004 r1/a2: 0x00000067 r2/a3: 0x00000001 | ||
+ | E: r3/a4: 0x00000000 r12/ip: 0xa0000000 r14/lr: 0x00027439 | ||
+ | E: xpsr: 0x41000000 | ||
+ | E: Faulting instruction address (r15/pc): 0x00039590 | ||
+ | E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0 | ||
+ | E: Current thread: 0x20014d88 (unknown) | ||
+ | </pre> | ||
− | + | Looking at `dwt.h`: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | <pre> | ||
+ | 88 | ||
+ | 89 /** | ||
+ | 90 * @brief Initialize and Enable the DWT cycle counter | ||
+ | 91 * | ||
+ | 92 * This routine enables the cycle counter and initializes its value to zero. | ||
+ | 93 * | ||
+ | 94 * @return 0 | ||
+ | 95 */ | ||
+ | 96 static inline int z_arm_dwt_init_cycle_counter(void) | ||
+ | 97 { | ||
+ | 98 /* Clear and enable the cycle counter */ | ||
+ | 99 DWT->CYCCNT = 0; | ||
+ | 100 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; | ||
+ | 101 | ||
+ | 102 /* Assert that the cycle counter is indeed implemented. */ | ||
+ | 103 __ASSERT((DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk) != 0, | ||
+ | 104 "DWT implements no cycle counter. " | ||
+ | 105 "Cannot be used for cycle counting\n"); | ||
+ | 106 | ||
+ | 107 return 0; | ||
+ | 108 } | ||
+ | 109 | ||
</pre> | </pre> | ||
+ | |||
+ | What does this mean? Hello, a Nordic Devzone post and reply from Sigurd of Nordic provides an answer to this specific problem: | ||
+ | |||
+ | * https://devzone.nordicsemi.com/f/nordic-q-a/75041/error-dwt-implements-no-cycle-counter-cannot-be-used-for-cycle-counting | ||
+ | |||
+ | <!-- comment --> | ||
+ | |||
+ | == [[#top|^]] Project Files Which Change With Addition Of A Thread == | ||
+ | |||
+ | Added a header and a source file to implement given new thread. Updated `CMakeLists.txt` to include new dot c source file. Updated main.c to include new dot h file and to call the new thread's initialization routine: | ||
+ | |||
+ | <pre> | ||
+ | Memory region Used Size Region Size %age Used | ||
+ | FLASH: 34988 B 1 MB 3.34% | ||
+ | SRAM: 9744 B 64 KB 14.87% | ||
+ | IDT_LIST: 0 GB 2 KB 0.00% | ||
+ | ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo$ git status | ||
+ | On branch cli-dev-work-002 | ||
+ | Changes to be committed: | ||
+ | (use "git restore --staged <file>..." to unstage) | ||
+ | new file: src/thread_simple_cli.c | ||
+ | new file: src/thread_simple_cli.h | ||
+ | |||
+ | Changes not staged for commit: | ||
+ | (use "git add <file>..." to update what will be committed) | ||
+ | (use "git restore <file>..." to discard changes in working directory) | ||
+ | modified: CMakeLists.txt | ||
+ | modified: src/main.c | ||
+ | modified: src/thread_simple_cli.c | ||
+ | modified: src/thread_simple_cli.h | ||
+ | <pre> | ||
+ | |||
+ | |||
+ | <!-- comment --> |
Latest revision as of 19:32, 11 August 2023
Keywords: Zephyr thread analyzer module :: thread resource use :: thread stack monitoring
Contents
- 1 ^ OVERVIEW
- 2 ^ Latest
- 3 ^ New Zephyr Project Documentation Pages to Learn
- 4 ^ Zephyr RTOS Thread API
- 5 ^ Specific Zephyr documentation pages
- 6 ^ Zephyr Thread Creation
- 7 ^ Specific Function Associated With Zephyr Thread
- 8 ^ Issue with Counter Timer in Zephyr Thread - dwt.h
- 9 ^ Project Files Which Change With Addition Of A Thread
^ OVERVIEW
Kinda limited tutorials on Zephyr RTOS threads, but seemingly solid documentation on zephyrproject.org site. A specific example starting point may be among Zephyr source tree's samples directory . . . `$ grep -nr k_thread_create ./*` shows thread creation in a SPI Bluetooth driver sample. Path from root Zephyr RTOS source tree is zephyr/drivers/bluetooth/hci
.
Also worth noting Zephyr provides a thread analyzer module for Zephyr based apps.
^ Latest
0311
^ New Zephyr Project Documentation Pages to Learn
Passing data between Zephyr threads:
On this top level page there is mention of passing data between threads:
Zephyr queues:
^ Zephyr RTOS Thread API
Some Zephyr RTOS API functions to learn:
- k_sem_take(<e_connected, K_FOREVER);
- k_work_schedule(&connect_work, K_NO_WAIT);
Additionally some further Zephyr thread entities and mostly API functions include:
- k_thread
- K_THREAD_STACK versus K_KERNEL_STACK
- k_thread_create()
- k_thread_
- k_thread_join()
- k_thread_abort()
- k_thread_suspend()
- k_thread_resume()
Unsure whether this routine a Zephyr one:
work_init();
Following non-function entities from aws_iot main.c appear important:
77 static struct k_work_delayable shadow_update_work; 78 static struct k_work_delayable connect_work; 79 static struct k_work shadow_update_version_work;
^ Specific Zephyr documentation pages
- https://docs.zephyrproject.org/latest/reference/kernel/threads/index.html#lifecycle
- https://docs.zephyrproject.org/latest/reference/kernel/threads/workqueue.html?highlight=k_work_reschedule#c.k_work_reschedule
Following example code block matches k_thread_create() code in zephyr/drivers/bluetooth/hci/spi.c:519:
^ Zephyr Thread Creation
2023-08-11 note - Threads in Zephyr may be created a couple of ways. One involves an API call, and the other way involves a macro which expands to the thread creation code at compile time. There are some constraints on creating threads via the API, that is at run time rather than compile time, which also generally implies that a user side or application. These constraints detailed at:
^ Specific Function Associated With Zephyr Thread
150 static void connect_work_fn(struct k_work *work) 151 { 152 int err; 153 154 if (cloud_connected) { 155 return; 156 } 157 158 err = aws_iot_connect(NULL); 159 if (err) { 160 printk("aws_iot_connect, error: %d\n", err); 161 } 162 163 printk("Next connection retry in %d seconds\n", 164 CONFIG_CONNECTION_RETRY_TIMEOUT_SECONDS); 165 166 k_work_schedule(&connect_work, 167 K_SECONDS(CONFIG_CONNECTION_RETRY_TIMEOUT_SECONDS)); 168 }
150:static void connect_work_fn(struct k_work *work) 338: k_work_init_delayable(&connect_work, connect_work_fn);
^ Issue with Counter Timer in Zephyr Thread - dwt.h
5���_�_yϗ���Uߗ���5�_]����������Օ���}����ߧ�߿��ϯ���U�����u�����u�����U����u����������������땥����]��w����w����w�����u�7�w�U���u���W� * The AWS IoT sample started, version: v1.0.0 Zephyr thread create routine returns 536955992 for LED blink thread, - SUCCESS - found Kionix accelerometer and device is ready uart task at loop iteration 0x00000000 LTE cell changed: Cell ID: -1, Tracking area: -1 uart task at loop iteration 0x00000001 uart task at loop iteration 0x00000002 thread_kionix_accel - Kionix sensor reports manufacturer ID string: " K i o n " ( spaces added around characters, ID four bytes long. ) *** *** TEST 2p1 *** X accel 184, Y accel 65341, Z accel 16409 *** ASSERTION FAIL @ WEST_TOPDIR/zephyr/arch/arm/include/aarch32/cortex_m/dwt.h:103 E: r0/a1: 0x00000004 r1/a2: 0x00000067 r2/a3: 0x00000001 E: r3/a4: 0x00000000 r12/ip: 0xa0000000 r14/lr: 0x00027439 E: xpsr: 0x41000000 E: Faulting instruction address (r15/pc): 0x00039590 E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0 E: Current thread: 0x20014d88 (unknown)
Looking at `dwt.h`:
88 89 /** 90 * @brief Initialize and Enable the DWT cycle counter 91 * 92 * This routine enables the cycle counter and initializes its value to zero. 93 * 94 * @return 0 95 */ 96 static inline int z_arm_dwt_init_cycle_counter(void) 97 { 98 /* Clear and enable the cycle counter */ 99 DWT->CYCCNT = 0; 100 DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; 101 102 /* Assert that the cycle counter is indeed implemented. */ 103 __ASSERT((DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk) != 0, 104 "DWT implements no cycle counter. " 105 "Cannot be used for cycle counting\n"); 106 107 return 0; 108 } 109
What does this mean? Hello, a Nordic Devzone post and reply from Sigurd of Nordic provides an answer to this specific problem:
^ Project Files Which Change With Addition Of A Thread
Added a header and a source file to implement given new thread. Updated `CMakeLists.txt` to include new dot c source file. Updated main.c to include new dot h file and to call the new thread's initialization routine:
Memory region Used Size Region Size %age Used FLASH: 34988 B 1 MB 3.34% SRAM: 9744 B 64 KB 14.87% IDT_LIST: 0 GB 2 KB 0.00% ted@localhost:~/projects/zephyr-based/z4-sandbox-kionix-work/kionix-driver-demo$ git status On branch cli-dev-work-002 Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: src/thread_simple_cli.c new file: src/thread_simple_cli.h Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: CMakeLists.txt modified: src/main.c modified: src/thread_simple_cli.c modified: src/thread_simple_cli.h <pre>