pico添加devmem2读写内存模块

devmem2模块可实现对设备寄存器的读写操作。在RT-Thread的命令行组件Fish中添加devmem2模块,用户可在终端输入devmem2相关命令,FinSH根据输入对指定寄存器进行读写,并将结果显示到控制终端。
关于FinSH详细内容见:Finsh

自定义msh命令devmem2

msh是FinSH的传统命令行模式,因其模式体积小,使用方便,能够解决C-style(C语言解释器模式)的弊端等,被广泛引用。
自定义的 msh 命令,可以在 msh 模式下被运行,将一个命令导出到 msh 模式可以使用如下宏接口:

MSH_CMD_EXPORT(name, desc);
name:要导出的命令,desc:导出命令的描述

在ENV工具中配置MSH:command shell,如下图:
在这里插入图片描述
添加devmem2模块至FinSH组件,需要在工程中的FinSH路径下cmd.c(如:…/bsp/raspberry-pico/dist/project/rt-thread/components/finsh/cmd.c)添加devmem2相关源码。由于pico开发板没有mmp内存映射模块,所以读写寄存器是针对物理地址进行操作。其核心代码:

void devmem2(int argc, char **argv) {
    void *phy_addr;
	unsigned long read_result, writeval;
	off_t target;
	int access_type = 'w';
	
	if(argc < 2) {
		fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
			"\taddress : memory address to act upon\n"
			"\ttype    : access operation type : [b]yte, [h]alfword, [w]ord\n"
			"\tdata    : data to be written\n\n",
			argv[0]);
        return;
	}
	target = strtoul(argv[1], 0, 0);
	if(argc > 2)
		access_type = tolower(argv[2][0]);

    phy_addr = (void*)target;
    printf("phy_addr:%x\n",phy_addr);
    switch(access_type) {
		case 'b':
			read_result = *((unsigned char *) phy_addr);
			break;
		case 'h':
			read_result = *((unsigned short *) phy_addr);
			break;
		case 'w':
			read_result = *((unsigned long *) phy_addr);
			break;
		default:
			fprintf(stderr, "Illegal data type '%c'.\n", access_type);
            return;
	}
    printf("Value at address 0x%X (%p): 0x%X\n", target, phy_addr, read_result); 

	if(argc > 3) {
		writeval = strtoul(argv[3], 0, 0);
		switch(access_type) {
			case 'b':
				*((unsigned char *) phy_addr) = writeval;
				read_result = *((unsigned char *) phy_addr);
				break;
			case 'h':
				*((unsigned short *) phy_addr) = writeval;
				read_result = *((unsigned short *) phy_addr);
				break;
			case 'w':
				*((unsigned long *) phy_addr) = writeval;
				read_result = *((unsigned long *) phy_addr);
				break;
		}
		printf("Written 0x%X; readback 0x%X\n", writeval, read_result); 
	}
}
MSH_CMD_EXPORT(devmem2, devmem2 sample: devmem2 { address } [ type [ data ] ]);

添加devmem会引入新的头文件,在scons构建项目时,会出现因找不到个别头文件或源文件而报错,针对此问题,需要在当前工程的根目录下,查找缺失的头文件,并将头文件所在的路径添加至project/libraries/SConscript中,如:
在这里插入图片描述

验证msh命令devmem2

读CPUID

添加devmem2模块并成功构建工程后,将在msh命令行按下Tab健查看devmem2命令。如图:
在这里插入图片描述在这里插入图片描述
读取设备的CPUID,查看pico rp2040说明文档,获取其ARM寄存器的其实地址为0xe0000000,其CPUID的偏移地址offset为0xed00,故其CPUID的地址为0xe000ed00。通过CPUID寄存器的值为0x410cc601与devmem2查看的一致。如图:
在这里插入图片描述
由于pico中地址范围为0xd0000000-0xefffffff仅支持word size,故halfword及byte的type读操作无效,如图:
在这里插入图片描述
此处,读某一寄存器,验证其type为w、h、b效果,如图:
在这里插入图片描述

读写全局变量

在…/projectt/applications/main.c中添加一全局变量test_value,scons构建项目,通过…/project/rt-thread.map查看test_value变量的地址为0x200012c4,如图:

/*
main.c
*/
#include <rtthread.h>
#include <rtdevice.h>

#define LED_PIN 25

int test_value;
int main(void)
{
    rt_kprintf("Hello, RT-Thread!\n");
    test_value = 0;
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);

    while (1)
    {
        rt_pin_write(LED_PIN, 1);
        rt_thread_mdelay(3000);
        rt_pin_write(LED_PIN, 0);
        rt_thread_mdelay(1000);
    }
}

在这里插入图片描述
通过devmem2命令读写test_value对应寄存器内的值,如图:
在这里插入图片描述
关于逻辑地址(虚拟地址)与物理地址(设备的实际RAM地址/硬盘空间)及映射之间说明可参考如下:
操作系统中逻辑地址和物理地址的区别
linux内存映射mmap原理分析
内存映射原理和内核是如何实现的,完全分析mmap原理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值