Difference between revisions of "Zephyr rtos threads"

From Wiki at Neela Nurseries
Jump to: navigation, search
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(&lte_connected, K_FOREVER);
 
*  k_sem_take(&lte_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|^]] Example Zephyr Thread Creation ==
+
== [[#top|^]] Zephyr Thread Creation ==
Rough search narrowing in on specific thread creation and use in aws_iot sample project from nRF Connect SDK:
+
 
 +
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>
cpguest@ubuntu-vm-0p2:/mnt/host-os-dev-area/pulse-pro/firmware-stage1/aws-iot-stand-alone/src$ grep -nr k_ ./*.c
 
30:static struct k_work_delayable shadow_update_work;
 
31:static struct k_work_delayable connect_work;
 
32:static struct k_work shadow_update_version_work;
 
 
150:static void connect_work_fn(struct k_work *work)
 
150:static void connect_work_fn(struct k_work *work)
166:    k_work_schedule(&connect_work,
 
170:static void shadow_update_work_fn(struct k_work *work)
 
186:    k_work_schedule(&shadow_update_work,
 
190:static void shadow_update_version_work_fn(struct k_work *work)
 
242:            (void)k_work_cancel_delayable(&connect_work);
 
258:            k_work_submit(&shadow_update_version_work);
 
262:            k_work_schedule(&shadow_update_work,
 
283:            (void)k_work_cancel_delayable(&shadow_update_work);
 
284:            k_work_schedule(&connect_work, K_NO_WAIT);
 
335:static void work_init(void)
 
337:    k_work_init_delayable(&shadow_update_work, shadow_update_work_fn);
 
 
338:    k_work_init_delayable(&connect_work, connect_work_fn);
 
338:    k_work_init_delayable(&connect_work, connect_work_fn);
339:   k_work_init(&shadow_update_version_work, shadow_update_version_work_fn);
+
</pre>
356:           k_sem_give(&lte_connected);
+
 
513:   work_init();
+
 
523:   k_sem_take(&lte_connected, K_FOREVER);
+
<!-- comment -->
528:   k_work_schedule(&connect_work, K_NO_WAIT);
+
 
 +
== [[#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>
  
cpguest@ubuntu-vm-0p2:/mnt/host-os-dev-area/pulse-pro/firmware-stage1/aws-iot-stand-alone/src$ grep -n connect_work ./*.c
+
Looking at `dwt.h`:
31:static struct k_work_delayable connect_work;
 
150:static void connect_work_fn(struct k_work *work)
 
166:    k_work_schedule(&connect_work,
 
242:            (void)k_work_cancel_delayable(&connect_work);
 
284:            k_work_schedule(&connect_work, K_NO_WAIT);
 
338:    k_work_init_delayable(&connect_work, connect_work_fn);
 
528:    k_work_schedule(&connect_work, K_NO_WAIT);
 
cpguest@ubuntu-vm-0p2:/mnt/host-os-dev-area/pulse-pro/firmware-stage1/aws-iot-stand-alone/src$
 
  
 +
<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


^ 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(&lte_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()
    Thread options K_ESSENTIAL, K_SSE_REGS and more . . .

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

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>