烧写
先说烧写,胖友们好多反应烧写失败的,这里特此贴出我参考的地址:
快速启动 - 東山Pi (dongshanpi.com)
咱当初玩过全志的d1哪吒开发板,所以知道需要安装驱动,
百问网的d1s教程中,缺了这一步,在上边东山哪吒派里面有介绍。
注意事项
1、新的程序编译完了,要pack一下,否则烧写的还是之前的固件。
2、在make menuconfig阶段,可以配置log的等级,默认是2
但是咱们调试程序,总想多看到一些信息啊,于是配置成了5,配置路径是:
Environment Setup → (2) Default log level 进入改成5即可。
但是改成5之后,编译之后的固件就开始疯狂打印了,
改成5疯狂打印:
[INF]: [riscv_cpu_handle_exception:0271]: ecall SYSCALL_FROM_S
[INF]: [riscv_cpu_handle_exception:0271]: ecall SYSCALL_FROM_S
[INF]: [riscv_cpu_handle_exception:0271]: ecall SYSCALL_FROM_S
改成4疯狂打印:
thread:initprocess stack overflow
thread pri status sp stack size max used left tick error
于是我又改回了2,自己调试的时候,所有xxx_info(“brararala”);的info都改成err
就是使用err级别的打印,这样就可以规避这个问题了。
3、melis的学习资料很少,除了这里下载的SDK目录有manual和doc目录之外,全志的github仓库里面,v853芯片也有关于melis的资料,可以学习一下,虽然,,,也没啥深入的说明。
地址:
v83x-melis/document at master · Tina-Linux/v83x-melis (github.com)
把测试程序加上
melis的驱动都在ekernel/drivers目录下
hal目录是操作寄存器的
drv目录是使用hal层,结合rtthread的框架,让用户写应用程序的时候,直接open、read、write就行。
在hal和drv的目录下,
都有source目录,是驱动程序。
也都有test目录,是驱动测试程序(一个测试驱动程序是否好用的应用程序)。
但是,
在ekernel/drivers目录下,还有一个test目录,这里的测试程序会把hal层和drv目录的测试程序弄到一起,写成了一个文件,,,就是说,在这个目录的测试程序,它即测试hal层驱动,又测试drv层驱动。
配置方法:
Kernel Setup → Drivers Test Sample —>
[*] Twi Test 这是I2C的测试程序
配置上这些之后,开机help敲下去,就可以看到多了2个命令:
cmd_hal_twi - hal twi test code 测试hal层驱动的测试程序
cmd_drv_twi - rtthread twi test code 测试drv层驱动的测试程序
会把文件ekernel/drivers/test/test_twi.c编译到固件中,他就是测试程序。
twi的hal层驱动里的一个bug
cmd_hal_twi 的使用方法是:
msh />cmd_hal_twi
Usage:
cmd_hal_twi [port] [slave_addr] [reg] -r
cmd_hal_twi [port] [slave_addr] [reg] -w [val]
但是使用这个命令,会导致卡死,修改方法:
ekernel/drivers/hal/source/twi/hal_twi.c
解决cmd_hal_twi卡死的方法:
1870 static twi_status_t hal_twi_regulator_exit(hal_twi_t *twi)
1871 {
1872 int ret;
1873
1874 enum REGULATOR_ID_ENUM regulator_id = twi_regulator_id[twi->port];
1875 /* 我加的
1876 if (regulator_id == AXP2101_ID_MAX)
1877 {
1878 TWI_INFO("[twi%d] needn't to exit regulator", twi->port);
1879 return TWI_STATUS_OK;
1880 }
1881
1882 ret = hal_regulator_disable(&twi->regulator);
1883
1884 if (ret)
1885 {
1886 TWI_ERR("twi%d disable regulator failed\n", twi->port);
1887 return TWI_STATUS_ERROR;
1888 }
1889 */ 我加的
1890 return TWI_STATUS_OK;
1891 }
具体原因,这个是hal_twi_regulator_exit函数,还有一个与他配对的hal_twi_regulator_init函数
他SDK把hal_twi_regulator_init里面都注释掉了,但是这个hal_twi_regulator_exit里面没有注释,
顾头不顾尾了属于是,
所以我把他hal_twi_regulator_exit里面也都注释掉,就不崩溃了。
twi的drv层的测试程序
cmd_drv_twi 需要一个参数,就是port号,即第几个I2C控制器。
不写参数,也会直接崩溃给你看。
但是吧,写了参数,
他的测试程序操作也很迷,
见
fd = rt_device_find(dev_name);
rt_device_open(fd, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
rt_device_control(fd, I2C_SLAVE, &addr);
rt_device_write(fd, 1, buf, 6); //twi write
rt_device_read(fd, 1, buf, 6); //twi read
rt_device_control(fd, I2C_RDWR, &msg); //twi control
rt_device_close(fd);
它这个是神魔意思呢?
通过dev_name比如twi1找到一个rtthread里面注册的设备dev,(初始化时init_twi_device注册好了的)
这个dev是rt_device结构,他是某个sunxi_driver_twi_t的base成员
通过dev找到sunxi_driver_twi_t结构的变量(通过结构体成员找到他所属的结构container_of你懂的)
然后sunxi_driver_twi_t结构的hal_drv里面包含的都是hal层的驱动代码。
这段写的比较乱,可以不看,,,
总之就是drv层的驱动程序,即写又读又control,可能是为了展示他的武器库吧。
反正,我测试下来,把我的at24c02都干懵了,我也不知道他都写了啥,还会报一个错:
[ERR]: [hal_twi_engine_do_xfer:1675]: [twi1] incomplete xfer (status: 0x20, dev addr: 0x50)
我很郁闷,
于是我就基于hal层写自己的驱动了。(本来想基于drv层写at24c02的驱动程序的,,,)
其实很取巧,我就改了改人家原有的测试程序,,,
我的at24c02程序
代码文件名my_test.c放到ekernel/drivers/test/目录
修改ekernel/drivers/test/Makefile
加一行(我加在了12行)
obj-y += my_test.o
代码如下:
#include <getopt.h>
#include <log.h>
#include <rtthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sunxi_hal_twi.h>
#include <sunxi_drv_twi.h>
#define MY_TEST_READ 0
#define MY_TEST_WRITE 1
static int my_twi(int argc, const char **argv)
{
twi_msg_t msg;
twi_port_t port;
uint16_t addr;
char reg_addr, reg_val = 0, rw = MY_TEST_READ;
int c;
if (argc < 5)
{
printk("Usage:\n");
printk("\tmy_twi [port] [slave_addr] [reg] -r\n");
printk("\t -w [val]\n");
return -1;
}
port = strtol(argv[1], NULL, 0);
addr = strtol(argv[2], NULL, 0);
reg_addr = strtol(argv[3], NULL, 0);
while ((c = getopt(argc, (char *const *)argv, "r:w")) != -1)
{
switch (c)
{
case 'r':
rw = MY_TEST_READ;
break;
case 'w':
rw = MY_TEST_WRITE;
reg_val = strtol(argv[5], NULL, 0);
break;
}
}
hal_twi_init(port);
hal_twi_control(port, I2C_SLAVE, &addr);
if (rw == MY_TEST_READ)
{
hal_twi_read(port, reg_addr, ®_val, 1);
printk("reg_val: 0x%x\n", reg_val);
}
else if (rw == MY_TEST_WRITE)
{
/*
* hal_twi_write bug workaround
*/
uint8_t buf[2];
buf[0] = reg_addr;
buf[1] = reg_val;
msg.flags = 0;
msg.addr = addr;
msg.len = 2;
msg.buf = buf;
hal_twi_control(port, I2C_RDWR, &msg);
//hal_twi_write(port, reg_addr, ®_val, 1);
}
hal_twi_uninit(port);
return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS(my_twi, my_twi, hal twi test code);
使用的引脚是PB4作为I2C的clk,PB5作为I2C的sda
所以在测试的时候,port要写成1
测试步骤如下:(读写AT24c02)
msh />cmd_hal_twi
Usage:
cmd_hal_twi [port] [slave_addr] [reg] -r
cmd_hal_twi [port] [slave_addr] [reg] -w [val]
msh />my_twi 1 0x50 0 -w 7
msh />my_twi 1 0x50 1 -w 8
msh />my_twi 1 0x50 2 -w 9
msh />my_twi 1 0x50 0 -r
reg_val: 0x7
msh />my_twi 1 0x50 1 -r
reg_val: 0x8
msh />my_twi 1 0x50 2 -r
reg_val: 0x9
我只研究了驱动层,
其他目录都没看,没有文档也看不懂,大概是一个驱动屏幕很吊的GUI组件,
音视频相关的库在
ls elibrary/bin/
3rd libcharenc.a libeabi.a liblzma.a libminic.a libsyscall.a
libapp_views.a libcharset.a libelibs_ex.a libmediainfo.a libpub0.a readme.txt
一看到不给源码的库,就很难受,不过也是知识产权问题了。
本来吧,他一个做音视频编解码(没细看,可能只是解码)的芯片,跑linux多稳定啊,还有稳定的网络协议栈用。
搞成melis这不成了RTOS了吗,是为了启动更快?不太懂。
我一开始想再搞搞spi的,发现他的引脚只配置了spi0,这个是板卡用的spi norflash的接口,可别乱搞啊。
所以,要是想使用spi1控制器,需要在配置文件中加上spi1使用的4个引脚,配置文件目录是
projects/d1s-nezha/configs/sys_config_nor.fex
为啥我的i2c不需要新配置引脚呢,
因为他已经配置过了,,,
见:
197 [twi1]
198 twi1_scl = port:PB04<4><1><default><default>
199 twi1_sda = port:PB05<4><1><default><default>
加个图
我投机取巧了,给大家一个入门介绍,剖砖引玉了。
完。