这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 软件与操作系统 » 【Zephyr】MCXN947 Zephyr 开发入门适配shell

共2条 1/1 1 跳转至

【Zephyr】MCXN947 Zephyr 开发入门适配shell

高工
2025-03-24 23:15:30   被打赏 20 分(兑奖)     打赏

        在上一篇配置Zephyr开发环境的基础上(【Zephyr】MCXN947 Zephyr开发环境搭建),我们开始上手第一个Zephyr  应用来学习Zephyr的使用。Zephyr 的源码的Demo 目录下有很多示例程序,我们可以使用这些示例程序进入Zephyr开发,在FreeRtos的基础环境开发中,习惯适配个shell 方便用于和cpu 交互使用,我们将之前适配的shell移植到Zephyr,Shell 的移植过程可以查看此贴(基础环境搭建之裸机环境添加shell),本次不做重点介绍。

开始之前我们先看下Zephyr 的软件结构图,从中可以看到我们本次shell 依赖的uart 的驱动在软件结构中的层次

image.png

因为要适配shell,主要依赖uart 的驱动,我们选取 zephyr\samples\drivers\uart\echo_bot 作为base,在此基础上进行修改适配shell,首先复制echo_bot 命名为shell,方便我门修改添加shell。

image.png

zephyr 的编译使用CMAKE来编译,我们修改shell/CMakeLists.txt 文件加入shell 源代码及依赖的ringbuffer 代码并将对应.h 路径加入到include path.

image.png

添加完源代码后在main函数入口添加uart 的配置操作,并注册uart 的中断回调函数,在回调内更新ringbuffer.

/*
 * Copyright (c) 2022 Libre Solar Technologies GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <littleshell.h>
#include <ringbuffer.h>

#include <string.h>

/* change this to any other UART peripheral if desired */
#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)

#define MSG_SIZE 32

/* queue to store up to 10 messages (aligned to 4-byte boundary) */
//K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 10, 4);

static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);

static RingBuffer ringbuff;

/* receive buffer used in UART ISR callback */
//static char rx_buf[MSG_SIZE];
//static int rx_buf_pos;

uint8_t shell_uart_getchar(uint8_t  * ch)
{
	return RingBuffer_Read(&ringbuff,ch,1);
}

/*
 * Read characters from UART until line end is detected. Afterwards push the
 * data to the message queue.
 */
void serial_cb(const struct device *dev, void *user_data)
{
	uint8_t c;

	if (!uart_irq_update(uart_dev)) {
		return;
	}

	if (!uart_irq_rx_ready(uart_dev)) {
		return;
	}

	/* read until FIFO empty */
	while (uart_fifo_read(uart_dev, &c, 1) == 1) {
		/* else: characters beyond buffer size are dropped */
		/* Get date and write to ringbuffer */
        RingBuffer_Write(&ringbuff,&c,1);
	}
}

/*
 * Print a null-terminated string character by character to the UART interface
 */
void print_uart(char *buf)
{
	int msg_len = strlen(buf);

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(uart_dev, buf[i]);
	}
}

int main(void)
{
	//char tx_buf[MSG_SIZE];
    /* Init Ringbuffer */
    static uint8_t uart_rx_buff[128] = {0};
    RingBuffer_Init(&ringbuff,uart_rx_buff,128);
	
	if (!device_is_ready(uart_dev)) {
		printk("UART device not found!");
		return 0;
	}

	/* configure interrupt and callback to receive data */
	int ret = uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);

	if (ret < 0) {
		if (ret == -ENOTSUP) {
			printk("Interrupt-driven UART API support not enabled\n");
		} else if (ret == -ENOSYS) {
			printk("UART device does not support interrupt-driven API\n");
		} else {
			printk("Error setting UART callback: %d\n", ret);
		}
		return 0;
	}
	uart_irq_rx_enable(uart_dev);

	littleshell_main_entry(NULL);

	/* indefinitely wait for input from the user */
	return 0;
}


因为shell 中用大到了了"FSymTab" 来保存命令,需要在link 文件中添加对应的定义,我们使用的MCXN947板子使用了zephyr\include\zephyr\arch\arm\cortex_m\scripts\link.ld的链接文件,修改文件添加对应的section 定义。

image.png

这里分享一个小技巧,因为zephyr 仓库内的文件比较多,我们如何快速找到对应的link 文件,我们可以在west 编译时加上-v 选项,这样在终端上会输出详细的编译信息

image.png

从这些编译信息中我们可以快速找到编译使用的link file 文件。

image.png


上述修改完成后,我们使用west build -p auto  -b frdm_mcxn947/mcxn947/cpu0   samples\drivers\uart\shell 命令来编译应用程序。


image.png


将生成的可执行程序下载到板子中运行发现shell 已经按照预取的运行

image.png

至此我们就将之前的裸机的shell 适配到zephyr 。



高工
2025-03-25 19:19:17     打赏
2楼

zephyr 看起来还是蛮难的


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]