DongshanPI-D1s开发板使用教程之melis烧写、I2C驱动AT24c02(功力太浅,剖砖引玉了)

烧写

先说烧写,胖友们好多反应烧写失败的,这里特此贴出我参考的地址:
快速启动 - 東山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, &reg_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, &reg_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>

加个图

 
 
 

我投机取巧了,给大家一个入门介绍,剖砖引玉了。
完。

3 个赞