安装
编译和运行
参考west使用指南:
Building, Flashing and Debugging
- 嵌入CMAKE:Permanent CMake Arguments
- Built-in commands
- Signing Binaries
- Using Zephyr without west
以qemu an521为例
west update
west build -p auto -b mps2_an521_ns -t run samples/hello_world
选项run
表示编译后自动运行,参考west usage,输出
[INF] Beginning TF-M provisioning
[WRN] TFM_DUMMY_PROVISIONING is not suitable for production! This device is NOT SECURE
[Sec Thread] Secure image initializing!
Booting TF-M a8313be08
Creating an empty ITS flash layout.
Creating an empty PS flash layout.
[INF][Crypto] Provisioning entropy seed... complete.
*** Booting Zephyr OS build zephyr-v3.3.0-1195-g9a759025d912 ***
Hello World! mps2_an521_ns
显然,这里打开了默认的trusted firmware-M
使用Kconfig关闭编译选项
参考:Configuration System (Kconfig)
命令:
west build -p auto -b mps2_an521_ns samples/hello_world -t menuconfig
为了编译不含TF-M的版本,选择打开boards/arm/mps2_an521/Kconfig.defconfig
看到:
config BOARD
default "mps2_an521_ns" if TRUSTED_EXECUTION_NONSECURE
default "mps2_an521_remote" if BOARD_MPS2_AN521_CPU1
default "mps2_an521"
# By default, if we build for a Non-Secure version of the board,
# force building with TF-M as the Secure Execution Environment.
config BUILD_WITH_TFM
default y if TRUSTED_EXECUTION_NONSECURE
运行
west build -p auto -b mps2_an521 samples/hello_world -t run
打开menuconfig看到
此时输出为:
*** Booting Zephyr OS build zephyr-v3.3.0-1195-g9a759025d912 ***
Hello World! mps2_an521
musca_s1开发板
板载资源可以在boards/arm/v2m_musca_s1/doc/index.rst找到,下载镜像,直接拷贝到存储区
west build -p auto -b v2m_musca_s1 samples/hello_world
cp build/zephyr/zephyr.hex /Volumes/MUSCA_S
minicom -D /dev/tty.usbmodem11302
output:
Musca-S1 Dual Firmware Version 1.9
*** Booting Zephyr OS build zephyr-v3.3.0-1195-g9a759025d912 ***
Hello World! musca_s1
应用开发
概述
应用既可以在zephyrproject/zephyr里面创建编译,也可以在外部建立prj文件夹,项目文件中应当包含:
<app>
├── CMakeLists.txt
├── app.overlay
├── prj.conf
└── src
└── main.c
以samples/hello_world
为例:
- cmake文件,环境中一定要设置
ZEPHYR_BASE
- 设备树文件
- Kconfig配置文件,defconfig
- C/C++源文件
调试
Zephyr运行qemu的命令是:
qemu-system-arm -cpu cortex-m33 \
-machine mps2-an521 \
-nographic -m 16 -vga none -net none \
-pidfile qemu.pid \
-chardev stdio,id=con,mux=on \
-serial chardev:con \
-mon chardev=con,mode=readline \
-icount shift=6,align=off,sleep=off \
-rtc clock=vm -chardev pty,id=hostS0 \
-serial chardev:hostS0 \
-kernel build/zephyr/zephyr.elf
加上-s
,(-gdb tcp::1234
的缩写)打开gdbserver,默认端口为:1234。也可以运行
west build -p auto -b mps2_an521 . -t debugserver_qemu
运行gdb命令:
arm-zephyr-eabi-gdb build/zephyr/zephyr.elf
(gdb) target remote localhost:1234
(gdb) dir ZEPHYR_BASE
使用工具连接调试硬件板
API
汇总:API Overview
使用说明:API Guildlines
内核系统开发
点灯
以musca-s1为例,在其设备树文件boards/arm/v2m_musca_s1/v2m_musca_s1.dts中:
aliases {
led0 = &red_led;
led1 = &green_led;
};
leds {
compatible = "gpio-leds";
red_led: led_0 {
gpios = <&gpio 2 0>;
label = "User LED1";
};
green_led: led_1 {
gpios = <&gpio 3 0>;
label = "User LED2";
};
};
使用led0和led1,用两个线程进行闪烁,调用的是toggle接口,使用fifo和输出线程通信,打印log,配置如下:
CONFIG_PRINTK=y
CONFIG_HEAP_MEM_POOL_SIZE=256
CONFIG_ASSERT=y
CONFIG_GPIO=y
代码如下:
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/__assert.h>
#include <string.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
/* size of stack area used by each thread */
#define STACKSIZE 1024
/* scheduling priority used by each thread */
#define PRIORITY 7
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
struct printk_data_t
{
void *fifo_reserved; /* 1st word reserved for use by fifo */
uint32_t led;
uint32_t cnt;
};
K_FIFO_DEFINE(printk_fifo);
void blink(const struct gpio_dt_spec *led, uint32_t sleep_ms, uint32_t id)
{
int ret, cnt = 0;
if (!gpio_is_ready_dt(led))
{
return;
}
ret = gpio_pin_configure_dt(led, GPIO_OUTPUT_ACTIVE);
if (ret < 0)
{
return;
}
while (1)
{
ret = gpio_pin_toggle_dt(led);
struct printk_data_t tx_data = {.led = id, .cnt = cnt};
size_t size = sizeof(struct printk_data_t);
char *mem_ptr = k_malloc(size);
__ASSERT_NO_MSG(mem_ptr != 0);
memcpy(mem_ptr, &tx_data, size);
k_fifo_put(&printk_fifo, mem_ptr);
k_msleep(sleep_ms);
cnt++;
}
}
void blink0(void)
{
blink(&led0, SLEEP_TIME_MS, 0);
}
void blink1(void)
{
blink(&led1, SLEEP_TIME_MS, 1);
}
void uart_out(void)
{
while (1)
{
struct printk_data_t *rx_data = k_fifo_get(&printk_fifo,
K_FOREVER);
printk("Toggled led%d; counter=%d\n",
rx_data->led, rx_data->cnt);
k_free(rx_data);
}
}
K_THREAD_DEFINE(blink0_id, STACKSIZE, blink0, NULL, NULL, NULL, PRIORITY, 0, 0);
K_THREAD_DEFINE(blink1_id, STACKSIZE, blink1, NULL, NULL, NULL, PRIORITY, 0, SLEEP_TIME_MS);
K_THREAD_DEFINE(uart_out_id, STACKSIZE, uart_out, NULL, NULL, NULL, PRIORITY, 0, 0);
线程开发
生命周期
- 线程创建
线程终止,termination,入口函数执行返回,线程终止
- 通过k_thread_join()睡眠当前线程,等待其他线程执行结束
- 线程中止,aborting,调用k_thread_abort()
- 线程挂起,suspension,调用k_thread_suspend()
线程状态
zephyr的线程状态:
线程特性
线程有以下重要特性:
堆栈区域
- 内核堆栈
- 线程堆栈
- 线程控制块
- 线程入口函数,及三个参数
- 越小优先级越高,可以为负数
线程配置选项
- 启动延时
- 执行模式
其他特性