您尚未登录。

#1 全志 SOC » 关于全志T113开发板接7寸LCD屏幕显示异常问题的解决方案 » 2023-05-17 10:32:50

LIVPO
回复: 1

在入手全志T113之后,第一时间移植好了之前6ull平台的rootfs。但是在测试QT的过程中发现屏幕最右侧有一部分显示不正常,经过初步推测应该是RGB行场同步时序有问题。本以为在设备树里面稍作修改之后就能OK,但是居然前前后后一共花了至少三个星期的时间。

这里就不给分析经过了,因为是真的真的太漫长了,搞得我头都大了。真的是要吐槽一下全志的代码:

1.函数名字真的看得头疼
2dd89be5404a78d038653cdfbc2ec30ebbc87475.png

2.代码杂乱无章,大量使用全局变量,让分析各种没头绪。

然后在这里直接给出最终分析的结果:

1.设备树里面timing,除了width、height、lcd_x和lcd_y之外的参数全没有用上(一开始不停的源码里面找这些参数在什么地方配置的,最后发现特么的根本就没有地方使用过这些参数)

01a937d9dd6fb0c1832cbd3f21725aff064128b0.png

2.width和height主要是用来计算dpi使用的,我这里写的280最终计算出来的dpi大概是97左右,windows标准的是96,反正相差无几我也没有细调了,lcd_x和lcd_y在原来的代码里主要是用来计算内核里面有一张图片的缩放使用的。

3.lcd timing寄存器里面的值是在uboot里面设置好之后在kernel里面直接拿来用的。

4.uboot里面的timing计算方式有问题,应该是百问没有仔细阅读全志文档的原因造成的,这也是使得屏幕显示向左平移了几十个像素的原因

a3def1e10fca39cd096f892dcd09370f3b375f52.png

5.我忘记我要说什么了…

接下来就说怎么处理吧:

1.首先按照全志的文档把设备树里面的timing改了
cb388eff5f5c52c177e242e89f28e2cfb8af0b8c.png

2.打开 drivers/video/fbdev/sunxi/disp2/disp/de/disp_lcd.c 然后找到 s32 disp_init_lcd(struct disp_bsp_init_para* para) 函数,在前面加上一段代码

typedef struct
{
	volatile unsigned int Timing0;
	volatile unsigned int Timing1;
	volatile unsigned int Timing2;
	volatile unsigned int Timing3;
}RegTypeDef;

static void set_lcd_timings(unsigned int dwLcdRegBase, struct disp_video_timings* pTimings)
{
	RegTypeDef* reg;
	unsigned int dwWidth, dwHeight;
	unsigned int dwHT, dwHBP;
	unsigned int dwVT, dwVBP;
	unsigned int dwHSPW, dwVSPW;

	reg = (RegTypeDef*)(dwLcdRegBase + 0x48);
	
	dwWidth = pTimings->x_res;
	dwHSPW = pTimings->hor_sync_time;
	dwHBP = pTimings->hor_back_porch + pTimings->hor_sync_time;	//在官方文档里:hbp = hbp + hspw,然而在全志的代码里面又将hspw其减去,所以在这里需要加回来
	dwHT = pTimings->hor_total_time;

	dwHeight = pTimings->y_res;;
	dwVSPW = pTimings->ver_sync_time;
	dwVBP = pTimings->ver_back_porch + pTimings->ver_sync_time;
	dwVT = pTimings->ver_total_time;

	reg->Timing0 = ((dwWidth - 1) << 16) | (dwHeight - 1);
	reg->Timing1 = ((dwHT - 1) << 16) | (dwHBP - 1);
	reg->Timing2 = (((dwVT - 1) * 2) << 16) | (dwVBP - 1);
	reg->Timing3 = ((dwHSPW - 1) << 16) | (dwVSPW - 1);

	printk("width: %d, hspw: %d, hbp: %d, ht: %d\n", dwWidth, dwHSPW, dwHBP, dwHT);
	printk("height: %d, vspw: %d, vbp: %d, vt: %d\n", dwHeight, dwVSPW, dwVBP, dwVT);
}

然后在 s32 disp_init_lcd(struct disp_bsp_init_para* para) 函数的 disp_lcd_init(lcd, lcd->disp); 后面加上

set_lcd_timings(para->reg_base[DISP_MOD_LCD0], &lcd->timings);

3.最后编译烧写进去之后重启就搞定了…

4.uboot我就懒得修改了,凑合用吧

#2 全志 SOC » 拆一款早年间将ChatGPT“落地”的AI语音交互机器人,八核A7全志R58主控 » 2023-05-15 15:21:34

LIVPO
回复: 0

视频版拆机:https://www.bilibili.com/video/BV1Qk4y177ja/?spm_id_from=333.999.0.0&vd_source=1c071942348817818731defc73b0bbff

公子·小白是一对由狗尾草智能科技推出的人工智能机器人,该系列中的产品包括公子小白、公子小白Pro、Smart Plus公子小白、公子小白成长版、公子小白青春版......这次要拆的这个机器人是公子小白系列,它在16/17年左右首发价是1880元,但这次从闲鱼淘来它,只花了60元。

_2023050810343520.jpg
_20230428181738.jpg

公子小白机器人主打“情感社交”场景,机器人背后的狗尾草智能科技算是国内比较早一批进行AI语音交互机器人设计的公司,这要是放到现在也可以算是半个ChatGPT概念公司了。

拆开外包装,看到这个说明书,中间连接的钉子都已经生锈了,生产时间写的是2017年的2月。17年生产的东西到现在还是全新未开封啊,可见当时的备货太多了,也是奔着百万级市场去做的,但是现在公司的官网和APP都显示不可用了,微信公众号的最新推文日期已然停留在了2020年,估计已经停止官方支持了。

_20230508170302.jpg
_20230504152246.png

确实,当时这个产品是领先时代的,他们的slogan是“AI虚拟生命终将走进每一个人的生活”,翻译一下就是前些时间爆火的元宇宙概念吗?AI、智慧生命、元宇宙、ChatGPT,这些都是时下最火热的行业话题。

但回到16/17年,那时的人工智能发展尚未成熟,只能进行单论的对话,并且经常答非所问,难一点的问题都无法回答,也无法通过图灵测试,那时候我们经常把人工智能说是“人工智障”,但是如果这个产品放到现在来做,接任ChatGPT,或许会是另一番光景啊。

拆解
这个机器人的表面十分圆滑,想拆开它还要费点劲,在机器人外部找不到任何一颗裸露的螺丝钉,经常一番捣鼓才发现它的拆解之道,首先需要找到隐藏的硅胶塞把它挖出来,把钉子卸了,然后强行把头给撬下来,这样就可以看到里面的大致结构了。

_20230428163457.jpg


首先看到主板上,主控是全志的R58,一款8核的芯片,上面固定了散热片,这颗芯片的价格差不多是10美金,折合人民币60多块钱,如果单从淘散料倒卖的角度来说,就凭这一颗主控就已经差不多回本了,那么到这里拆解就结束了。

_202304281656143.jpg20181225021710234.jpg


全志R58,8核A7*1.8GHz,这差不多是十年前的芯片啊,十年前的国产8核芯片,早期很多国内的带屏智能音箱、视频电话用的都是全志这颗R58的芯片,比如小鱼在家的视频电话,小鱼在家后来被百度收购了,于是也就成了后来小度在家智能视频音箱的原型。由此可见R58性能还是很高的,也有一些安卓平板选用了R58作为主控,在此基础上应该可以升级出很多有趣的玩法。


a507808496b8650f6fc493f0ea28bc7a.jpg
640.jpg

这里有一颗AXP813,是一颗电源管理芯片,集成电源管理,音频解码器,兼容USB3.0的充电器,RTC,模数转换器和硬件DSP,内部音频模块集成动态范围控制器,和自动增益控制,可在录音时提高信噪比,降低背景噪声干扰。这颗芯片也是全志旗下的,作为电源管理芯片一般都是跟主控成套片出售。

_202304281656144.jpg


两颗1GB 的SK 海力士的DDR3。

_202304281656141.jpg


一颗镁光的8GB的nand flash。

_202304281656142.jpg


这有一颗AP6255的wifi/蓝牙模组,这个模组应该是支持2.4G和5G的,16年的时候5G的路由器都不是很普及,机器人内容没有选用AP6212而是用AP6255,真的是对未来充满了期待,是奔着这个产品生命周期会延续很多年来设计的。

_20230428165614.jpg


这里有两颗科声讯的CX208,这是两颗语音处理芯片,里面集成了语音算法。比如降噪、回声消除、声源定位、唤醒词识别等等。但是我们现在基本都不用这种外挂的语音处理芯片了,一般是把语音处理部分放到主控里去跑,有的主控里还集成了专门跑语音算法的DSP或者NPU。

_20230504140934.jpg


每颗CX208可以连接2颗麦克风,所以我们看到上面是一个4麦克风的阵列,用的是早期的驻极体麦克风,现在的智能语音AIOT产品基本都不用这种麦克风了,基本上的都是硅麦。

_202305081702491.jpg
1.png

主板后面接了一个屏幕,是一个方形的5寸左右的屏幕,然后用这个结构件把它框起来,这样看起来就是弧形的脸,把边角的部分挡住,就可以显示那个机器人的各种表情了。这个挡板的结构设计也很有意思。

_202305041447128.jpg


如果设备还能运行的话,可以看到这个屏幕上会显示很多表情。因为现在这家公司的服务器都不运行了,所以都玩不了了。但是我要是这家公司最后的员工啊,我就让这个屏幕继续播放广告,会像某不退押金的共享单车一样,榨干他的最后价值。

这上面还有一个摄像头,是用来扫码和人脸试别用的,他会试别人脸的位置,跟着人动,也可以对人的表情做出判断,比如你不开心就给你讲笑话安慰你,或者是识别到前面是小朋友的时候,就播放适合小朋友的内容。当然这些都是理论功能啊,不知道这些功能有没有实现。

_20230504151318.jpg
_2023050414471211.jpg


然后下面是一个舵机,控制值这个机器人头转动的。我们来听一下这个声音,很有机器人感觉的那个声音,很有未来感,这么多年过去了和是很有质感,一看就是贵东西啊。

_20230508170249.jpg


然后下面这个是充电环的设计,跟airpod耳机底部的充电环是一样的。airpod耳机那个是有专利的,很多耳机厂商早年做tws耳机的时候就中过招。

_20230504151324.jpg


以上是比较重要的几个零部件介绍,其它的还有很多就不一一介绍了,最后上一张拆解的总览图。

_202305081702492.jpg

结语

这是一个16年时候的人工智能产品啊,当时还处于智能语音发展的早期,算法、方案、供应链成熟度都还处于一个刚刚能做产品的状态。AI对话只能试别简单的内容,只能做单轮对话不能做多轮对话,我们说那个时候的人工智能是弱人工智能。

今年随着chatGPT的大火,国内外资本纷纷入局,人工智能又被推到了一个新的高度,如果这个产品放到现在做,或许或有更好的体验和更广阔的市场。

现在的chatGPT已经可以通过图灵测试了,智商达到了一个大学生的水平,但是这些输出在2023年4月的今天,还只是停留在纸面上,不过从技术难度上来说,让它和机器人结合落地已经不存在瓶颈了,只是把输出结果再转化一次成为行代命令而且,所以,我们很期待马上到来的强人工智能时代,期待有更多改变我们生活的伟大产品。

#3 全志 SOC » v851s g2d 模块 sample 深究 » 2023-04-19 10:42:08

LIVPO
回复: 2

作者@chhjnavy
本帖转载自:https://bbs.aw-ol.com/topic/3291/
------------------------------------------------------------------
------------------------------------------------------------------

1. g2d 模块概述

g2d 主要功能:
1)旋转:支持90、180、270旋转;
2)镜像反转:H / V;
3) scale:放缩
4)格式转换:yuv 转 rgb 等,多种格式相互间转换;
5)透明叠加功能:实现两个rgb图片叠加;
6)矩形填充,等诸多功能;

2. g2d 配置

1)源码目录:tina-v853-docker/kernel/linux-4.9/drivers/char/sunxi_g2d

2)make kernel_menuconfig 配置

Device Drivers > Character devices > sunxi g2d driver
按空格键选中【*】
309b3811-659e-4000-8634-7e867717ab87-image.png

3)Device Tree 设备树配置
sun8iw21p1.dtsi路径:
tina-v853-docker/kernel/linux-4.9/arch/arm/boot/dts/sun8iw21p1.dtsi

		g2d: g2d@05410000 {
			compatible = "allwinner,sunxi-g2d";
			reg = <0x0 0x05410000 0x0 0xbffff>;
			interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clk_g2d>;
			iommus = <&mmu_aw 3 1>;
			status = "okay";
		};

status 要设定为“okay” 状态。

4)重新编译内核

mkernel
make -j1 V=s
pack

使用烧录工具PhoenixSuit 将路径:tina-v853-docker/out/v851s/lizard/openwrt/v851s_linux_lizard_uart0.img 下的img 镜像烧录到开发板。

adb shell 打开控制终端查看设备节点G2D:
483651d3-abc6-4e99-9a22-e5bac90a0194-image.png

5)通过G2D 设备节点,对g2d 进行操作

static int SampleG2d_G2dOpen(SAMPLE_G2D_CTX *p_g2d_ctx)
{
    int ret = 0;
    p_g2d_ctx->mG2dFd = open("/dev/g2d", O_RDWR, 0);
    if (p_g2d_ctx->mG2dFd < 0)
    {
        aloge("fatal error! open /dev/g2d failed");
        ret = -1;
    }
    return ret;
}

3. 详解 eyesee-mpp 中g2d sample 具体应用
1)eyesee-mpp 中 g2d sample 编译与执行请参考另一篇帖子
链接文本

2)g2d sample 目录
3e6039cc-ec14-4724-942b-92852b697e74-image.png

3)运用 g2d 进行rotation,scale,格式转换
具体实现:将 nv21 格式的1920x1080图转换成rgb888 格式并放缩为640x360 大小。具体用到两个功能,格式转换和放缩。
步骤如下:
1))根据1920x1080 nv21 格式以及 640x360 rgb888 格式申请虚拟地址空间以及转换成物理地址(注意:g2d 转换是在物理地址中完成的)

1920x1080 nv21 格式空间大小(输入文件):
a804f646-d146-4e43-8f2f-9ee1352cfc8e-image.png
Y 占 19201080 = 2073600 字节
UV 占 19201080 / 2 = 1036800 字节

640x360 rgb888 格式空间大小(输出文件):
RGB 占 6403603 = 691200 字节

另外:虚拟地址转换成物理地址使用如下函数:

g2d_getPhyAddrByVirAddr()
申请虚拟空间并转换成物理空间完整函数如下:
在文件 tina-v853-docker/platform/allwinner/eyesee-mpp/middleware/sun8iw21/sample/sample_g2d/sample_g2d.c/sample_g2d.c 中

static int PrepareFrmBuff(SAMPLE_G2D_CTX *p_g2d_ctx)
{
    SampleG2dConfig *pConfig = NULL;
    unsigned int size = 0;

    pConfig = &p_g2d_ctx->mConfigPara;
    
    p_g2d_ctx->src_frm_info.frm_width = pConfig->mSrcWidth;
    p_g2d_ctx->src_frm_info.frm_height =  pConfig->mSrcHeight;

    p_g2d_ctx->dst_frm_info.frm_width = pConfig->mDstWidth;
    p_g2d_ctx->dst_frm_info.frm_height = pConfig->mDstHeight;

    size = ALIGN(p_g2d_ctx->src_frm_info.frm_width, 16)*ALIGN(p_g2d_ctx->src_frm_info.frm_height, 16);
    if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420 || pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420)
    {
        p_g2d_ctx->src_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size);
        if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[0])
        {
            aloge("malloc_src_frm_y_mem_failed");
            return -1;
        }

        p_g2d_ctx->src_frm_info.p_vir_addr[1] = (void *)g2d_allocMem(size/2);
        if(NULL == p_g2d_ctx->src_frm_info.p_vir_addr[1])
        {
            g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]);
            aloge("malloc_src_frm_c_mem_failed");    
            return -1;
        }

        p_g2d_ctx->src_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[0]); 
        p_g2d_ctx->src_frm_info.p_phy_addr[1] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->src_frm_info.p_vir_addr[1]);
    }

	if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888)
	{
		size = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height * 3;
		p_g2d_ctx->dst_frm_info.p_vir_addr[0] = (void *)g2d_allocMem(size);
		if(NULL == p_g2d_ctx->dst_frm_info.p_vir_addr[0])
		{
			if(p_g2d_ctx->src_frm_info.p_vir_addr[0] != NULL)
			{
				g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[0]); 
			}
			if(p_g2d_ctx->src_frm_info.p_vir_addr[1] != NULL)
			{
				g2d_freeMem(p_g2d_ctx->src_frm_info.p_vir_addr[1]);
			}
			aloge("malloc_dst_frm_y_mem_failed");
			return -1;
		}
		p_g2d_ctx->dst_frm_info.p_phy_addr[0] = (void *)g2d_getPhyAddrByVirAddr(p_g2d_ctx->dst_frm_info.p_vir_addr[0]); 
	}

    return 0; 
}

2))通过fopen 传菜间两个文件句柄,fd_in fd_out 用来操作输入输出两个文件资源

        p_g2d_ctx->fd_in = fopen(p_g2d_ctx->mConfigPara.SrcFile,"r");
        if(NULL == p_g2d_ctx->fd_in)
        {
            aloge("open src file failed");
            ret = -1;
            goto _err2;
        }
        fseek(p_g2d_ctx->fd_in, 0, SEEK_SET);

            p_g2d_ctx->fd_out = fopen(p_g2d_ctx->mConfigPara.DstFile, "wb");
            if (NULL == p_g2d_ctx->fd_out)
            {
                aloge("open out file failed");
                ret = -1;
                goto _err2;
            }
            fseek(p_g2d_ctx->fd_out, 0, SEEK_SET);

3))读出 1920x1080 nv21 图资放入 虚拟空间

read_len = p_g2d_ctx->src_frm_info.frm_width * p_g2d_ctx->src_frm_info.frm_height;
        if(pConfig->mPicFormat == MM_PIXEL_FORMAT_YVU_SEMIPLANAR_420|| pConfig->mPicFormat == MM_PIXEL_FORMAT_YUV_SEMIPLANAR_420)
        {
            size1 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[0] , 1, read_len, p_g2d_ctx->fd_in);
            if(size1 != read_len)
            {
                aloge("read_y_data_frm_src_file_invalid");
            }
            size2 = fread(p_g2d_ctx->src_frm_info.p_vir_addr[1], 1, read_len /2, p_g2d_ctx->fd_in);
            if(size2 != read_len/2)
            {
                aloge("read_c_data_frm_src_file_invalid");
            }

            fclose(p_g2d_ctx->fd_in);

            g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[0], read_len);
            g2d_flushCache((void *)p_g2d_ctx->src_frm_info.p_vir_addr[1], read_len/2);
        }

4))打开g2d 初始化,并开始转换

ret = SampleG2d_G2dOpen(p_g2d_ctx);
    if (ret < 0)
    {
        aloge("fatal error! open /dev/g2d fail!");
        goto _err2;
    }
    ret = SampleG2d_G2dConvert(p_g2d_ctx);
    if (ret < 0)
    {
        aloge("fatal error! g2d convert fail!");
        goto _close_g2d;
    }
//具体转化函数:

static int SampleG2d_G2dConvert_scale(SAMPLE_G2D_CTX *p_g2d_ctx)
{
    int ret = 0;
    g2d_blt_h blit;
    g2d_fmt_enh eSrcFormat, eDstFormat; 
    SampleG2dConfig *pConfig = NULL;

    pConfig = &p_g2d_ctx->mConfigPara;

    ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mPicFormat, &eSrcFormat);
    if(ret!=SUCCESS)
    {
        aloge("fatal error! src pixel format[0x%x] is invalid!", pConfig->mPicFormat);
        return -1;
    }
    ret = convert_PIXEL_FORMAT_E_to_g2d_fmt_enh(pConfig->mDstPicFormat, &eDstFormat);
    if(ret!=SUCCESS)
    {
        aloge("fatal error! dst pixel format[0x%x] is invalid!", pConfig->mPicFormat);
        return -1;
    }

    //config blit
    memset(&blit, 0, sizeof(g2d_blt_h));

    if(0 != pConfig->mDstRotate)
    {
        aloge("fatal_err: rotation can't be performed when do scaling");
    }

    blit.flag_h = G2D_BLT_NONE_H;       // angle rotation used
//    switch(pConfig->mDstRotate)
//    {
//        case 0:
//            blit.flag_h = G2D_BLT_NONE_H;   //G2D_ROT_0, G2D_BLT_NONE_H
//            break;
//        case 90:
//            blit.flag_h = G2D_ROT_90;
//            break;
//        case 180:
//            blit.flag_h = G2D_ROT_180;
//            break;
//        case 270:
//            blit.flag_h = G2D_ROT_270;
//            break;
//        default:
//            aloge("fatal error! rotation[%d] is invalid!", pConfig->mDstRotate);
//            blit.flag_h = G2D_BLT_NONE_H;
//            break;
//    }
    //blit.src_image_h.bbuff = 1;
    //blit.src_image_h.color = 0xff;
    blit.src_image_h.format = eSrcFormat;
    blit.src_image_h.laddr[0] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[0];
    blit.src_image_h.laddr[1] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[1];
    blit.src_image_h.laddr[2] = (unsigned int)p_g2d_ctx->src_frm_info.p_phy_addr[2];
    //blit.src_image_h.haddr[] = 
    blit.src_image_h.width = p_g2d_ctx->src_frm_info.frm_width;
    blit.src_image_h.height = p_g2d_ctx->src_frm_info.frm_height;
    blit.src_image_h.align[0] = 0;
    blit.src_image_h.align[1] = 0;
    blit.src_image_h.align[2] = 0;
    blit.src_image_h.clip_rect.x = pConfig->mSrcRectX;
    blit.src_image_h.clip_rect.y = pConfig->mSrcRectY;
    blit.src_image_h.clip_rect.w = pConfig->mSrcRectW;
    blit.src_image_h.clip_rect.h = pConfig->mSrcRectH;
    blit.src_image_h.gamut = G2D_BT601;
    blit.src_image_h.bpremul = 0;
    //blit.src_image_h.alpha = 0xff;
    blit.src_image_h.mode = G2D_PIXEL_ALPHA;   //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA
    blit.src_image_h.fd = -1;
    blit.src_image_h.use_phy_addr = 1;

    //blit.dst_image_h.bbuff = 1;
    //blit.dst_image_h.color = 0xff;
    blit.dst_image_h.format = eDstFormat;
    blit.dst_image_h.laddr[0] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[0];
    blit.dst_image_h.laddr[1] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[1];
    blit.dst_image_h.laddr[2] = (unsigned int)p_g2d_ctx->dst_frm_info.p_phy_addr[2];
    //blit.dst_image_h.haddr[] = 
    blit.dst_image_h.width = p_g2d_ctx->dst_frm_info.frm_width;
    blit.dst_image_h.height = p_g2d_ctx->dst_frm_info.frm_height;
    blit.dst_image_h.align[0] = 0;
    blit.dst_image_h.align[1] = 0;
    blit.dst_image_h.align[2] = 0;
    blit.dst_image_h.clip_rect.x = pConfig->mDstRectX;
    blit.dst_image_h.clip_rect.y = pConfig->mDstRectY;
    blit.dst_image_h.clip_rect.w = pConfig->mDstRectW;
    blit.dst_image_h.clip_rect.h = pConfig->mDstRectH;
    blit.dst_image_h.gamut = G2D_BT601;
    blit.dst_image_h.bpremul = 0;
    //blit.dst_image_h.alpha = 0xff;
    blit.dst_image_h.mode = G2D_PIXEL_ALPHA;   //G2D_PIXEL_ALPHA, G2D_GLOBAL_ALPHA
    blit.dst_image_h.fd = -1;
    blit.dst_image_h.use_phy_addr = 1;

    ret = ioctl(p_g2d_ctx->mG2dFd, G2D_CMD_BITBLT_H, (unsigned long)&blit);
    if(ret < 0)
    {
        aloge("fatal error! bit-block(image) transfer failed[%d]", ret);
        system("cd /sys/class/sunxi_dump;echo 0x14A8000,0x14A8100 > dump;cat dump");
    }

    return ret;
} 

5))转化完成后将640x360 rgb888 图资通过fd_out句柄存储起来

if(pConfig->mDstPicFormat == MM_PIXEL_FORMAT_RGB_888)
        {
            out_len = p_g2d_ctx->dst_frm_info.frm_width * p_g2d_ctx->dst_frm_info.frm_height *3;
            g2d_flushCache((void *)p_g2d_ctx->dst_frm_info.p_vir_addr[0], out_len);

            fwrite(p_g2d_ctx->dst_frm_info.p_vir_addr[0], 1, out_len, p_g2d_ctx->fd_out);
        }

4. 总结转化步骤

通过步骤3中的模块化分析,可以看出g2d 转化大概分为一下步骤:

1)为打开 iomen 初始化;
2)为src以及dst图资申请虚拟地址空间并转换成物理地址空间;
3)将src图资放入虚拟地址空间,然后自动映射到物理地址空间;
4)打开g2d 设备节点进行转换(最重要的一环,可以通过手册分析具体怎么转换的);
5)将转换好的dst图资保存起来;

#4 全志 SOC » v85x MPP 模块概述以及编译 sample 步骤 » 2023-04-17 10:03:24

LIVPO
回复: 0

1. MPP 模块概述

MPP 系统控制模块,根据芯片特性,完成硬件各个部件的复位、基本初始化工作,同时负责完成 MPP(Media Process Platform 媒体处理平台)系统各个业务模块的初始化、去初始化以及管MPP 系统各个业务模块的工作状态、提供当前 MPP 系统的版本信息等功能。

应用程序启动 MPP 业务前,必须完成 MPP 系统初始化工作。同理,应用程序退出 MPP 业务后,也要完成 MPP 系统去初始化工作,释放资源。

功能描述
(1)初始化 MPP 组件的运行环境,完成音频输入输出、视频输入输出等硬件设备的初始化配置。
(2)提供绑定组件的接口。
(3)提供媒体内存分配、释放、查询的接口。

主要模块缩写:
VI :视频输入模块
VO:视频输出模块
VENC:视频编码模块
VDEC:视频解码模块
AI:音频输入
AO:音频输出
AENC:音频编码模块
ADEC:音频解码模块

2. v851s MPP sample
MPP sample 源码目录:
tina-v853-docker/platform/allwinner/eyesee-mpp/middleware/sun8iw21/sample

MPP sample 配置目录(kconfig、makefile):
tina-v853-docker/openwrt/package/allwinner/eyesee-mpp/middleware/

3. 编译一个MPP 模块步骤(以 sample_g2d 为例)
1)make menuconfig 配置配置项,选中sample_g2d
路径:Allwinner > eyesee-mppp > select mpp sample > sample_g2d 空格选中变成 【*】

1637dcc6-fcb0-4da9-b0a7-6f2cbab42925-image.png

3f77919a-9b0d-4ad3-ae06-c8561b910cbd-image.png

2)到配置目录下编译
MPP sample 配置目录(kconfig、makefile):
tina-v853-docker/openwrt/package/allwinner/eyesee-mpp/middleware/

执行:

mm -B
将会在源码目录(上面已给出)的bin 文件夹下产生可执行文件以及配置文件(如果bin 文件夹下没产生,请到源码sample 下查看)

ae41dce9-5657-4e8d-b311-0ca156ef8223-image.png

3)将其adb push 到v851s开发板中
执行:

./sample_vi_g2d -path sample_vi_g2d.conf
g2d 具体作用,请看源码code 中的 readme.txt 以及 g2d 手册

4. 其他sample 同理
注意:
1)执行某个sample 一定要先在make menuconfig 中选中
2)其他 sample 可能有依赖文件或者lib,通过错误提示,在make menuconfig 按“/” 搜索,然后选中即可
3)想知道每个sample 的具体含义,多看readme.txt 以及 官方手册

#5 Re: 全志 SOC » 全志D1芯片之终极探索 » 2023-04-11 10:53:13

Copper 说:

lz消失一年多了?
最近刚听说D1芯片的新型号D1H,都说是D1芯片换了个丝印,这不会是老D1把ARM核给去掉了吧?

D1H和D1应该是一样的,据说是HDMI组织要求加上个H在后面,参考A40i-H

#6 全志 SOC » D1s上实现MPU6050数据读取 » 2023-04-11 10:03:08

LIVPO
回复: 0

本文转载自:https://bbs.elecfans.com/jishu_2348036_1_1.html

前言
上一篇文章使用RT-Smart的IIC驱动OLED屏幕,进行基本的字符串显示,在使用过程中对RT-Smart有了一定熟悉,准备使用SPI驱动ST7789,但SPI接口没有引出,本次使用手上已有的传感器MPU6050进行使用。

过程
本次直接开始添加离线包

在/D1S/userapps/rt-thread/bsp/allwinner/d1s下输入scons –menuconfig进行内核配置,添加MPU605使用所需的配置。

wKgZomQeZFuAdaP3AA.png

使用IIC0进行陀螺仪数据的读取,在RT-Thread Compents 下选择Device Drivers

wKgZomQpB36AKtliAAB1qQs8ZWA2.png

使能I2C device drivers

wKgaomQpB3-ANeGfAAOctasnCXg0.png

在RT-Thread online packages下选择MPU6050离线包

wKgaomQpB3-AeFmuAAMcAFXRLlc7.png

在General Drivers Configuration下配置IIC

wKgZomQpB4CAL7WqAACD0V3c37U0.png

保存退出,更新一下,发现报错,不能更新MPU6050的离线包

wKgaomQpB4CAAIzjAABlLilpEnc4.png

解决方法,打开rt-studio随意新建一个工程,下发MPU6050的芯片包

wKgZomQpB4GAEpQ_AAFEkUtpDwQ0.png

查看离线包的json文件,如下所示:

wKgZomQpB4GARmDtAAEjz8WRzO40.png

打开自己的工程,发现使能的MPU6050后.json文件中没有进行相应的配置,将rt-studio生成的.json文件生成的内容复制到自己的工程。

wKgaomQpB4KASyxbAAI8aGFdzjE0.png

在次更新,下载成功

wKgZomQpB4KAYSnNAAA_Tro3h1s1.png

将mpu使用的I2C设备修改为I2C0

wKgaomQpB4OAXpWUAADId5OzbR88.png

保存,使用scons编译

wKgZomQeZF-AKcwbAAB7rPOi8Kc1.png

将sd.bin拖到xfel同级目录下

wKgZomQeZF-AVRgSAAD8NbdLH3A1.png

替换掉原来的sd.bin

wKgaomQeZGCACXBhAAEdKHDg5NM6.png

三、固件下载
先将SD卡格式化

wKgZomQeZGGAFErHAAA8rI5KS2M5.png

然后插入开发板中,先安全FEL按键,然后按一下复位按键,使开发板进入FEL模式。

wKgaomQpB4WAamfeAAEzshPsYTg0.png

按一下复位按键,查看串口输出

wKgZomQpB4aAPcfqAADG9vnlhVo7.png

输入help命令

wKgaomQpB4aAHo9sAABOrEoaJcM2.png

输入mpu5xxx_test

wKgaomQpB4aAHo9sAABOrEoaJcM2.png

将陀螺仪换个位置读取,数据读取成功

wKgZomQpB4aAUTihAABvA_OUkZE2.png

五、总结
本次完成了MPU6050的数据读取,成功的使用的该外设,当然是底层驱动,还为进行应用层的开发,在驱动层已经有了大致的了解,驱动使用时容易出现MenuConfig配置了但rtconfig.h不更新,每次都要手动的添加,当然在使用的过程中也遇到了很多错误,然后重新下载源码进行开发。

#7 全志 SOC » D1S在rt-smart下驱动OLED » 2023-04-11 09:50:53

LIVPO
回复: 0

本文转载自:https://bbs.elecfans.com/jishu_2344522_1_1.html

前言
本次使用RT-Smart的IIC驱动OLED屏幕,进行基本的字符串显示,在使用的过程中遇到一些问题,在这里做记录分享,本次以熟悉RT-Smart使用为主。

过程
本次直接开始添加离线包,环境搭建请参考上一篇文章:https://bbs.aw-ol.com/topic/3145/

在/D1S/userapps/rt-thread/bsp/allwinner/d1s下输入scons –menuconfig进行内核配置,添加OLED使用所需的配置。

wKgZomQeZFuAdaP3AAC4y4IWXug1.png

选择SSD1306离线包

wKgaomQeZFyAHiFQAATIwgQIjj01.png

使用IIC3,同时使用ssd1306 sample

wKgZomQeZFyAAYeqAAEXihAyLAc4.png

使能IIC3驱动

wKgaomQeZF2AWplkAAC1iCbcfF06.png

保存退出,更新一下

修改rtconfig.h

wKgZomQeZF6AGetrAAVWWZNsKn40.png

保存,使用scons编译

wKgZomQeZF-AKcwbAAB7rPOi8Kc1.png

将sd.bin拖到xfel同级目录下

wKgZomQeZF-AVRgSAAD8NbdLH3A1.png

替换掉原来的sd.bin

wKgaomQeZGCACXBhAAEdKHDg5NM6.png

三、固件下载
先将SD卡格式化

wKgZomQeZGGAFErHAAA8rI5KS2M5.png

然后插入开发板中,先安全FEL按键,然后按一下复位按键,使开发板进入FEL模式。

wKgaomQeZGGAeymaAABOjlAet-M0.png

按一下复位按键,查看串口输出

wKgZomQeZGGAXDa-AAFskPuq7PI8.png

输入help命令

wKgaomQeZGKAAD4eAADsT-b2KJg0.png

输入ssd1306_test进行测试,报错

wKgaomQeZGKAIzvQAAIbrfJNdFA8.png

查看硬件原理图,PB6,PB7被占用,使用IIC0进行。

wKgZomQeZGOAeo7lAABjuEiw-_M3.png

重新下载程序后,复位开发板,IIC0已经注册

wKgaomQeZGOAM_yoAAE8CUIzs-U6.png

输入ssd1306测试命令

wKgZomQeZGSAGwFbAAC8C90DQ1s8.png

查看OLED屏幕输出

4BEB2C03-AE94-48d6-BCCB-83C6F2B3A69E.png

硬件连接
对应芯片引脚:

wKgaomQeZGaATBvsAAVTC6RjldM7.png

对应排针:

wKgaomQeZGaACzi4AAFv4kFlHRM8.png

五、总结
RT-Smart文档使用资料有点少,花费大量时间摸索完成了OLED屏幕显示,在摸索过程中也逐渐知道了外设的使用方式。接下里下一步开始驱动2.8寸的LCDTFT。

#8 全志 SOC » 全志V85x开源硬件设计大赛 PCB方案汇总 » 2023-03-31 09:57:19

LIVPO
回复: 1

1、V853-智能交互摄像头开发板

该参赛作品基于全志V853开发板制作的一款类似眼镜外挂的小产品,可以对场景进行辅助识别,并通过云端交互实现物联网控制,进一步实现物联网与人机交互的融合。

开发板配置了摄像头和小屏幕接口,并外挂DDR3和EMMC,充分发挥了主控的编解码能力和边缘计算能力(NPU),是一个很有创意的边缘计算设计。

_20230314144834.jpg
_202303141028319.jpg


2、V853-DouPi方案设计


该参赛作品基于全志V853芯片设计了SCB 单板,使用了V853的音视频接口和丰富的外设接口,并外接AXP电源管理芯片。

在SCB单板上包含了一路千兆网口、一路UART、一路MIPI CSI、一路MIPI DSI、一路USB OTG、板载WiFi/蓝牙以及15个GPIO管脚输出。

_202303141028316.jpg
_202303141028312.jpg



3、V853-服务器管理及协处理卡


该参赛作品基于全志V853芯片设计了一个服务器的管理设备,实现服务器管理及协处理卡功能,对服务器进行管理和检测,实时反馈信息,通过物联网接入网络,可以远程在线管理。

开发板集成了1路百兆管理网口,1路UART调试功能,1路VGA显示功能,1路音频输出,1路USB功能,主板电压检测功能,1路视频检测功能,WIFI功能。

_202303141028315.jpg

4、V853-全功能BTB学习开发板

该参赛作品基于全志V853芯片设计了一块开发板,分为核心板和底板两个部分,引用了V853所支持的大部分功能引脚,是名副其实的“全功能”开发板。

核心板采用BTB设计,并板载了eMMC、DDR、AXP电源芯片,最大支持 1G DDR3 32GB eMMC存储;核心板背面采用了3x60pin排针设计,支持自贴NAND FLASH。

底板上引出了绝大部分资源,具体包括两个百兆网口、RGB888及MIPI DSI显示接口、USB OTG、MIPI CSI摄像头、MIC、TF卡接口等其它接口。

目前开发板功能还在验证中,验证没有问题后,会公开底板配套的原理图、尺寸图、使用文档,配套的视频以及嵌入式AI开发等所有资源。


_202303141028317.jpg


5、V853-全功能BTB学习开发板


该参赛作品基于全志V853芯片设计了一款开发板,引出console调试串口和端子外接4G+GPS模块,并集成SD CARD,千兆以太网,百兆以太网,WiFi,音频输入输出,MIPI CSI ,MIPI DSI ,按键,LED,G-SENSOR,USB及USB HUB,引出console调试串口,ADC引脚引出,2.54端子引出一路串口,两路PWM及GPIO。

_20230314104332.png

6. V851s-显示终端

该参赛作品计划将V851S芯片设计成核心板和底板结构,驱动LCD显示,接收CAN和RS485通信的数据显示在LCD显示屏上。

_202303141028314.jpg
_202303141028313.jpg

7.V851s-多媒体开发板

该参赛作品基于全志V851s芯片设计了一个极简版本的双目摄像头开发板,可外接屏幕和以太网。

在开发板设计技巧方面,为了简化电路图采用的内部LDO输出的1.8V;为了方面模块化的特点,采用核心外设独立设计;为了便于开发与调试,采用了LCD;针对V851s自身的特点,采用MIPI高速摄像头进行设计。

_202303141028318.jpg

8.V853-多功能串口服务器

该参赛作品基于全志V853芯片设计了一个单片机管理设备,通过以太网控制V853设备再对多台单片机进行管理,并设计了配套的上位机软件;原理图主要在官方参考设计上进行修改,通过RS232和TTL控制下位机。

_20230314151051.png

9.V853-音频播放器开发板

该参赛作品基于全志V853芯片设计了一个小音频管理系统,类似于一个个人小声卡,主要用于家里音乐试听,并针对多通道功放进行音效调音,满足室内的音响效果调优,增加diy 调音乐趣

开发板将实现codec音频驱动以实现基础硬件功能。硬件调试完成后,进行驱动验证、音频链路验证,主要涉及boot 文件系统驱动等调试,alsa 驱动移植等工作。在此基础上实现调音架构,实现delay gain biquad 等模块的功能实现,并整理出调音接口。

_20230314102831.jpg
_202303141028311.jpg


资料获取

以上参赛方案详细设计资料均可获取:

#9 全志 SOC » 全志系列芯片在Tina Linux中使用脚本完成定制化升级 » 2023-03-20 10:12:51

LIVPO
回复: 1

在OTA升级过程中,添加定制化需求,实现控制变量升级。所以选择利用swupdate升级满足定制化脚本需求

该方法在831,853,t113两个平台上测试有效

因为swupdate支持脚本,所以在升级过程中,添加能够实现定制升级的脚本即可,将带有定制升级的脚本编入策略描述文件(sw-descrition)OTA升级配置文件中(sw-subimgs),在打包ota升级包时,将脚本一起打包进ota包中。在进行下面的配置后,输入升级命令时,首先开始执行脚本中的内容,满足升级条件后,再进行升级流程。下面进行详细的步骤介绍:

1.swupdate支持shellscript脚本,需要以下功能配置(默认选中)

执行:make menuconfig/make ota_menuconfig
Allwinner  --->
    <*> swupdate............................. software update for embedded system
        Swupdate Settings  --->
            General Configuration  --->
                [*] enable pre and postinstall scripts
        Image Handlers  --->
            [*] shellscript

2.在swupdate文件夹下创建脚本,名字随意,在脚本中写入要实现的功能。例如:目前有一个方案需要升级,但是分为A,B两种产品,对应做了不同的功能,为了防止升级混淆,可以利用脚本去控制变量升级,比如A产品方案中的env,可以添加一个变量project=a,B产品方案中的env添加一个变量project=b,那么脚本中的内容就可以判断project=a或b时,继续完成升级。env中添加内容和脚本内容举例如下:
env中:
437b4dfb25d84a1888090f5e7e82f323.png
脚本内容如下:
5d311321539a4651a33d32c62650894d.png

3.在描述文件中添加脚本功能,在sw-description中添加以下代码:
09a9b95225664e3c8e7b8fd5e7dcdbb2.png

4.将脚本打包进ota包中,脚本名字可以任意起,我这里是preinstall_checkAB.sh。
e547c5d447ba4368a39fb6db128e7ded.png

5.重新编译主系统和recovery系统,烧录固件,打包ota包,再进行验证。

6.验证:当校验失败时,返回值为1,会看到如下打印,不能升级。
d58b2c9b048e4c6780f6a8ebafe08cc1.png
校验成功时,返回值为0,看到如下打印,升级成功。
1d1de11a87624a8d846a01351fd0b79b.png

#10 Re: 全志 SOC » R128可以在FreeRTOS下查看并更改RISC-V、ARM、DSP三个CPU核的默认运行频率了 » 2023-03-15 14:38:05

zhenxin 说:

芯片可以购买了吗

据说快了,芯片能不能卖,晕哥肯定会有一手消息

#11 Re: 全志 SOC » R128可以在FreeRTOS下查看并更改RISC-V、ARM、DSP三个CPU核的默认运行频率了 » 2023-03-15 14:36:37

kekemuyu 说:

r128的c906最大能到多少,d1h好像也是c906架构频率可以1g左右

从爆料看是C906 600 MHz,DSP 400 MHz,M33 240 MHz这样

#12 全志 SOC » R128可以在FreeRTOS下查看并更改RISC-V、ARM、DSP三个CPU核的默认运行频率了 » 2023-03-15 10:02:04

LIVPO
回复: 7

1.主题
FreeRTOS_R128_如何查看并更改各CPU核的默认运行频率

2.问题背景
硬件:R128
软件:FreeRTOS

在日常开发过程中,需要评估各CPU核的默认运行频率,有时候需要降低默认运行频率来降低功耗,有时候又需要提升默认运行频率来增加算力。

那么如何从查看并更改R128上各CPU核的默认运行频率?

3.解决办法

  • 查看各CPU核默认运行频率

默认启动各个CPU核时会打印对应CPU核的运行频率,如下图所示:
80c8acb32612488186b30fa3459d0a39.jpg

  • 更改各CPU核默认运行频率方法

由于R128中各CPU核的默认运行频率是M33核上的代码配置的,因此只需修改M33核的代码即可。
具体步骤为:

首先通过执行crtos命令切换到rtos代码目录,rtos代码目录路径为:lichee/rtos
然后修改文件arch/arm/armv8m/sun20iw2p1/sun20i.c里设置相关时钟频率的地方


  • M33核

M33核相关时钟硬件如下图:
0cc4f97b59954c0c9b53e32c06f4b9b1.jpg

目前SDK中M33核时钟ar200a_hclk的来源为:DPLL1输出时钟经过第一个分频器输出ck1_m33时钟,然后通过第二个分频器输出sysclk钟,最后通过一个多路选择器输出ar200a_hclk。

DPLL1输出时钟的频率已经确定为1920M,因此要修改M33核的时钟,则只需要修改这2个分频器的分频值即可。

由于SDK中默认将第一个分频器的分频值定为5(此分频器的分频值取值范围为4-8),也即ck1_m33时钟频率为1920/5=384M,而第二个分频器的分频值取值范围为1-16,因此如果要修改的M33核时钟频率在24M到384M之间且可以被384M整除,则只需要修改第2个分频器的分频值,例如将M33核默认运行频率修改为128M,则只需修改宏AR200A_FREQ即可,如下所示:

diff --git a/arch/arm/armv8m/sun20iw2p1/sun20i.c b/arch/arm/armv8m/sun20iw2p1/sun20i.c
index 9b8c1cb1..c09444fc 100755
--- a/arch/arm/armv8m/sun20iw2p1/sun20i.c
+++ b/arch/arm/armv8m/sun20iw2p1/sun20i.c
@@ -445,7 +445,7 @@ static void rcosc_init(void)
 #define DPLL1_FREQ     (1920000000)
 #define DPLL2_FREQ     (1920000000)
 #define DPLL3_FREQ     (1600000000)
-#define AR200A_FREQ    ( 192000000)
+#define AR200A_FREQ    ( 128000000)
 #define DEVICE_FREQ    ( 192000000)
 static int sys_clk_init(void)
 {

若要修改的M33核时钟频率不满足上述条件,则需要同时修改函数ar200a_clk_set里设置ck1_m33时钟频率的地方,例如修改ck1_m33时钟为240M(1920/8=240M):

diff --git a/arch/arm/armv8m/sun20iw2p1/sun20i.c b/arch/arm/armv8m/sun20iw2p1/sun20i.c
index 9b8c1cb1..29b71137 100755
--- a/arch/arm/armv8m/sun20iw2p1/sun20i.c
+++ b/arch/arm/armv8m/sun20iw2p1/sun20i.c
@@ -190,7 +190,7 @@ static int ar200a_clk_set(u32 freq)
        /*fixed 384M*/
        //sr32(CCMU_AON_BASE+0xa4,  0, 3, 0x3);
        //0x4004c4a4: 0x8080000b
-       ret = hal_clk_set_rate(clk_ck1_m33, 384000000);
+       ret = hal_clk_set_rate(clk_ck1_m33, 240000000);
        if (HAL_CLK_STATUS_OK != ret) {
                ret = -1;
                goto err2;
  • C906核

C906核相关时钟硬件如下图:
d4aa3df37a9e44519698a5824b31e87b.jpg

目前SDK中C906核时钟rv_sys_clk的来源为:DPLL1输出时钟经过第一个分频器输出ck1_906时钟,然后通过第二个分频器输出rv_sys_clk时钟。

DPLL1输出时钟的频率已经确定为1920M,因此要修改C906核的时钟,则只需要修改这2个分频器的分频值即可,第一个分频器的分频值可取2、2.5、3、4、7,第二个分频器的分频值可取1、2、4、8。

例如将C906核默认运行频率修改为320M,需要修改sun20i_boot_c906函数中2处设置频率的地方,:

diff --git a/arch/arm/armv8m/sun20iw2p1/sun20i.c b/arch/arm/armv8m/sun20iw2p1/sun20i.c
index 9b8c1cb1..5798657b 100755
--- a/arch/arm/armv8m/sun20iw2p1/sun20i.c
+++ b/arch/arm/armv8m/sun20iw2p1/sun20i.c
@@ -596,7 +596,7 @@ int sun20i_boot_c906(void)

        //set clk_ck1_c906 clk to 480M
        //sr32(CCMU_AON_BASE+0xa4,  4, 3, 0x1);
-       ret = hal_clk_set_rate(clk_ck1_c906, 480000000);
+       ret = hal_clk_set_rate(clk_ck1_c906, 640000000);
        if (HAL_CLK_STATUS_OK != ret) {
                ret = -1;
                goto err2;
@@ -632,7 +632,7 @@ int sun20i_boot_c906(void)
        //set clk_ck_c906_div to 480000000;
        //sr32(CCMU_BASE+0x064, 0, 2, 0x0);
        clk_c906_div = hal_clock_get(HAL_SUNXI_CCU, CLK_RISCV_DIV);
-       ret = hal_clk_set_rate(clk_c906_div, 480000000);
+       ret = hal_clk_set_rate(clk_c906_div, 320000000);
        if (HAL_CLK_STATUS_OK != ret) {
                ret = -1;
                goto err6;

PS:由于第一个分频器无法输出320M时钟,故先配置第一个分频器输出640M的ck1_c906时钟,然后由第二个分频器再进行2分频,从而得到320M的C906核时钟。

  • DSP核

DSP核相关时钟硬件如下图:
5c7c605e6faf4876a9f94dad41297e71.jpg

目前SDK中DSP核时钟dsp_sys_clk的来源为:DPLL3输出时钟经过第一个分频器输出ck3_hifi5时钟,然后通过第二个分频器输出dsp_sys_clk时钟。

DPLL3输出时钟的频率已经确定为1600M,因此要修改DSP核的时钟,则只需要修改这2个分频器的分频值即可,第一个分频器的分频值可取3、4、5、6、7,第二个分频器的分频值可取1、2、4、8。

例如将DSP核默认运行频率修改为320M,只需修改宏DSP_CORE_CLOCK_FREQ即可,:

diff --git a/arch/arm/armv8m/sun20iw2p1/sun20i.c b/arch/arm/armv8m/sun20iw2p1/sun20i.c
index 9b8c1cb1..97d03ad7 100755
--- a/arch/arm/armv8m/sun20iw2p1/sun20i.c
+++ b/arch/arm/armv8m/sun20iw2p1/sun20i.c
@@ -703,7 +703,7 @@ err1:

 #if defined(CONFIG_ARCH_ARMV8M_DEFAULT_BOOT_DSP) || defined(CONFIG_COMMAND_BOOT_DSP) \
        || defined(CONFIG_PM_SUBSYS_DSP_SUPPORT)
-#define DSP_CORE_CLOCK_FREQ (400000000)
+#define DSP_CORE_CLOCK_FREQ (320000000)
 #define DSP_LDO_WORK_VOLT (1200) //400M@1.2V, 274M@1.1V
 int __sun20i_boot_dsp_with_start_addr(uint32_t dsp_start_addr)
 {

另外目前SDK代码中第一个分频器和第二个分频都配置成了相同的频率,若第一个分频器无法直接输出想要设置的频率,则需要分别将2个分频器配置成不同的输出频率。例如将DSP核默认运行频率修改为200M,第一个分频器最低输出时钟频率为1600/7=228.57M,无法直接输出200M,因此需要先配置第一个分频器输出400M的ck3_hifi5时钟,然后由第二个分频器进行2分频从而得到200M的dsp_sys_clk时钟,主要修改如下所示:

diff --git a/arch/arm/armv8m/sun20iw2p1/sun20i.c b/arch/arm/armv8m/sun20iw2p1/sun20i.c
index 9b8c1cb1..53f6828a 100755
--- a/arch/arm/armv8m/sun20iw2p1/sun20i.c
+++ b/arch/arm/armv8m/sun20iw2p1/sun20i.c
@@ -703,7 +703,7 @@ err1:

 #if defined(CONFIG_ARCH_ARMV8M_DEFAULT_BOOT_DSP) || defined(CONFIG_COMMAND_BOOT_DSP) \
        || defined(CONFIG_PM_SUBSYS_DSP_SUPPORT)
-#define DSP_CORE_CLOCK_FREQ (400000000)
+#define DSP_CORE_CLOCK_FREQ (200000000)
 #define DSP_LDO_WORK_VOLT (1200) //400M@1.2V, 274M@1.1V
 int __sun20i_boot_dsp_with_start_addr(uint32_t dsp_start_addr)
 {
@@ -752,7 +752,7 @@ int __sun20i_boot_dsp_with_start_addr(uint32_t dsp_start_addr)

     //set clk_ck3_hifi5 clk to 400M
     //sr32(CCMU_AON_BASE+0xa8,  8, 3, 0x3);
-    ret = hal_clk_set_rate(clk_ck3_hifi5, DSP_CORE_CLOCK_FREQ);
+    ret = hal_clk_set_rate(clk_ck3_hifi5, 400000000);
     if (HAL_CLK_STATUS_OK != ret) {
         ret = -1;
         goto err2;

修改完成后重新编译M33核固件,因为R128中各CPU核的默认运行频率是M33核上的代码配置的。
可先执行lunch_rtos选择对应方案的M33核,然后再执行mrtos编译以及执行pack命令打包固件。

下图是修改M33核频率为128M、C906核频率为320M、DSP核频率为320M后的效果:
35661a5b7edf4ffdbb02d9fab5759950.jpg

#13 全志 SOC » RTT D1s RDC2022纪念版开发板开箱使用分享与折腾记录 » 2023-03-01 10:53:52

LIVPO
回复: 0

全志D1S芯片介绍
全志D1S是由全志公司推出的,基于阿里平头哥的C906内核的全新一代应用处理器。

C906兼容RISC-V架构,标配内存管理单元,可运行Linux等操作系统。C906采用5级整型流水线设计,并可选性能优异的单双精度浮点和128位矢量运算单元,
适用于消费类IPC、多媒体、消费类电子等应用领域

全志D1s,又名 F133,它是今年早些时候和支持 Linux 的开发板一起推出的全志D1 RISC-V 处理器的低成本版,它和D1的主要区别在于D1s内置的RAM是 64MB DDR2。

原理图解析:
RTT D1s RDC2022纪念版开发板使用了核心板+底板的设计方式,一般核心板使用多层板设计,完成最小系统设计后,底板可以使用双面板设计,这样可以节省制作成本,也方便开发板在项目直接购核心板,自行根据项目需求设计底板,降低了硬件设计的繁琐程度。

98a06dfd-d182-40f0-8fe8-04ccd626b0e2-image.png

主供电采用EA3036,提供0.9V, 1.8V, 3.3V三路电源供电,其中0.9V电压为内核电压,1.8V为全志D1S内封的DDR2内存供电,3.3V为外设接口供电。

a59fcb29-d224-4dbe-a39b-81c0356a0289-image.png

80601111-d65e-4491-9949-9e62bed79a64-image.png

3.png

板载了一颗贴片SD卡,四线SDIO模式,方便量产时直接SMT即可完成贴片,通过丝印查找出其型号为苏州澜智公司推出的1Gb (128MByte) SD NAND,采用SLC,稳定性比普通的TF卡高。


板载的CH340连接到的是D1s的GP8/PG9/USART3引脚,这个有印象即可,其他接口后面使用到的时候再做提及。

2: RT-Thread smart开发

RT-THREAD SMART介绍
RT-Thread Smart 是基于 RT-Thread 操作系统上的混合操作系统,简称为 rt-smart,它把应用从内核中独立出来,形成独立的用户态应用程序,并具备独立的地址空间(32 位系统上是 4G 的独立地址空间)。

以下是 rt-smart 的整体结构框图,在硬件平台的基础上通过 MMU、系统调用的方式把整个系统分成了内核态及用户态。



基于RTT D1S 开发板运行RT-SMART
从上面的架构图中,我们可以看出,RM-smart层级关系是和linux内核具有一些相似之处的,都是分为用户态和内核态,我们开发一般也是从这两方面入手。

通过查阅全志D1的用户手册,我们可以知道,在默认情况下,其启动顺序为:

SMHC0 -> SPI NOR -> SPI NAND -> SMHC2

而RTT D1s开发板上的贴片SD卡连接到的正是SDIO0 (也就是SMHC0),那么我们只要把rt-smart的系统烧录到贴片SD卡里面,上电后就能够运行rt-smart操作系统了。

RT-smart操作系统在SD卡中的分区如下图:

8-emmc_partition.png

从0处开始的8KB空间是MBR分区头,这是文件系统规定的,直接跳过即可。
从0x2000开始的是SPL ,SPL类似于arm 嵌入式开发中常用的uboot,主要起到的功能是初始化DDR2,从SD卡中把内核或下一阶段的引导程序等复制到DDR2中,然后把程序指针指向内存空间中对应的起始地址并运行。
从0xE000开始的就是OpenSBI , 设备树和RT-smart内核,这一段代码会被复制到内存中以内核态运行。
从0x800000开始的是用户态程序,用户自己编写的程序就下载到这个位置,以用户态运行。
内核态与用户态的编译
本段内容主要参考了这篇文章:快来尝鲜!!使用 D1s (RDC2022 纪念版) 运行 RT-Smart

SPL
当前阶段,RT-smart的SPL程序尚未开源,所以该部分程序我们直接在上面的帖子里翻到最后,下载附件里的二进制文件即可。最终SPL程序文件名称为:

boot0_sdcard_sun20iw1p1_f133.bin

内核程序
开发环境:

虚拟机/实体机等方式运行Ubuntu20.04
首先创建一个工作文件夹:

mkdir ~/work/rttd1s
cd ~/work/rttd1s

然后克隆用户态仓库到该目录:

git clone https://github.com/RT-Thread/userapps.git

进入该目录后,下载RT-smart内核代码,并执行环境变量配置:

cd userapps
git clone https://github.com/RT-Thread/rt-thread.git
source smart-env.sh riscv64

结果出现了报错:
1.png

打开脚本后,发现是SHELL_FOLDER这个变量获取失败了,他获取的是执行该命令时第一个参数的所在位置。我们这个脚本是通过source命令来执行的。

SHELL_FOLDER=$(cd $(dirname $0); pwd)

我们可以通过直接硬编码其位置来修复这个问题,就像下图这样:
9-fix_err.png

再次执行,没有再出现错误。

10-fix_err_ok.png

配置工具链:

python3 tools/get_toolchain.py riscv64

编译内核程序

进入 rt-thread/bsp/allwinner/d1s 目录下

使用 scons --menuconfig 查看配置。smart 使用的串口为 UART3 ,对应引脚为 PG8 和 PG9。检查 UART3 是否开启,以及引脚是否正确。

> General Drivers Configuration 
    > General Purpose UARTs 
        > Enable UART3 

11_enable_uart.png

然后检查内核是否是使用的uart3

> RT-Thread Kernel > Kernel Device Object 

12_kernel_uart3.png

后面我们会需要点亮屏幕,所以在这里提前打开LCD驱动:

> General Drivers Configuration ─────

12_1_lcd.png

使用 scons 命令编译 内核
编译完内核之后,会自动执行打包命令 ./mksdimg.sh 打包出 sd.bin 镜像文件。该文件就是rt-smart系统的内核文件,根据上文中描述的那样,我们后面就会将其下载到SD卡的对应位置。

......
LINK rtthread.elf
riscv64-unknown-linux-musl-objcopy -O binary rtthread.elf rtthread.bin
riscv64-unknown-linux-musl-size rtthread.elf
   text    data     bss     dec     hex filename
 879356   60472  274136 1213964  12860c rtthread.elf
./mksdimg.sh
Allwinner TOC1 Image
Size: 1072640 bytes
Contents: 3 items
 00000000:00000490 Headers
 00000600:000188e0 => 40000000 opensbi
 00019000:00007475 => 40200000 dtb
 00020600:000e5748 => 40400000 kernel
scons: done building targets.

13-build-kernel.png

编译用户态程序
打包用户态程序需要用到当前目录下制作SDcard镜像的脚本,我们回到userapps主目录然后把脚本复制过去.

cd ~/work/rttd1s/userapps/
cp rt-thread/bsp/allwinner/d1s/mksdcard.sh ./mksdcard.sh

在当前目录下执行scons ,编译用户态程序,当出现提示scons: done building targets后,即为编译成功。

$ scons
.....
....
scons: done building targets

然后在当前目录下运行mkcard.sh,没有提示报错,即为成功,在当前目录下会生成sdroot.bin,这就是我们的用户态镜像,我们会将其烧录到sd卡的对应位置。

14_mkcard_ok.png

下载烧录
通过前文的努力,我们已经获得了所需的3个文件,分别是rt-smart提供的SPL,我们自己编译的内核文件和用户态文件,下面我介绍将其下载到开发板上SD卡的方法:

我们需要使用带数据传输功能的USB-TYPE-C线缆连接开发板的USB接口和电脑。这里有两种方法:

首先按住开发板上的FEL按键,然后插入电脑上电
先把线缆连接好,然后按住FEL按键,点击一次RST按键
,默认情况下会出现一个新的USB设备,但是会提示没有驱动。

15_drv_1.png

然后我们需要使用zadig这个软件给该设备强制安装winusb驱动,zadig这个软件在前面的帖子里或者互联网上都可以找到。打开软件后,确认当前显示的设备是Unknown Device #1,然后安装驱动。

15_drv_2.png

15_drv_3.png

驱动安装完成之后,我们就可以使用xfel这个软件来下载程序了,改软件同样在上面帖子最后的附件里。

烧录的命令有三个,分别如下:

烧录boot镜像:

xfel.exe sd write 8192 boot0_sdcard_sun20iw1p1_f133.bin

烧录内核镜像:

xfel.exe sd write 57344 sd.bin

烧录用户态应用

xfel.exe sd write 8388608 sdroot.bin

我们把从Ubuntu中编译完的镜像复制到xfel同级目录,然后依次运行以上命令即可。命令中的sd write就是指烧录到贴片sd卡里,后面的数字是烧录的起始地址,就对应着SPL, 内核和用户态程序的起始地址。

PS E:\MP\RTT-D1S\RDC资料\出厂固件+工具> ./xfel.exe sd write 8192 boot0_sdcard_sun20iw1p1_f133.bin
write 48Kbytes
swap buf:00023E00,len=512, cmdlen=512
Found SD card 125173760 bytes
100% [================================================] 48.000 KB, 226.353 KB/s
PS E:\MP\RTT-D1S\RDC资料\出厂固件+工具> ./xfel.exe sd write 57344 sd.bin
align up to 8KB, write 1072640 ==> 1048Kbytes
swap buf:00023E00,len=512, cmdlen=512
Found SD card 125173760 bytes
100% [================================================] 1.023 MB, 218.882 KB/s
PS E:\MP\RTT-D1S\RDC资料\出厂固件+工具> ./xfel.exe sd write 8388608 sdroot.bin
write 8192Kbytes
swap buf:00023E00,len=512, cmdlen=512
Found SD card 125173760 bytes
100% [================================================] 8.000 MB, 217.951 KB/s

烧录完成后,我们将串口的USB接口连接到电脑,然后重新上电即可运行。

串口的软件这里推荐使用mobaXterm,打开软件后, 创建一个新的串口,波特率默认为500000。依次点击以下按钮:

16_uart_open.png

然后按下重启键,就可以看到rt-smart系统已经运行起来了。

 \ | /
- RT -     Thread Smart Operating System
 / | \     5.0.0 build Feb 22 2023 22:26:54
 2006 - 2022 Copyright by RT-Thread team
hal_sdc_create 0
card_detect insert
Initial card success. capacity :60014MB
sdmmc bytes_per_secotr:200, sector count:7537400
found part[0], begin: 8388608, size: 58.614GB
found partition:sd0 of mbr at offset 0x0000000000004000, size:0x0000000007533400
hal_sdc_create 1
card_detect insert
Initial card failed!!
[E/drv-sdmmc] init sdmmc failed!
[E/drv-sdmmc] sdmmc_init failed!
[D/FAL] (fal_flash_init:47) Flash device |                  sdcard0 | addr: 0x00000000 | len: 0xa6e80000 | blk_size: 0x00000200 |initialized finish.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name       | flash_dev |   offset   |    length  |
[I/FAL] -------------------------------------------------------------
[I/FAL] | download   | sdcard0   | 0x00800000 | 0x00800000 |
[I/FAL] | easyflash  | sdcard0   | 0x01000000 | 0x00100000 |
[I/FAL] | filesystem | sdcard0   | 0x01100000 | 0x00c00000 |
[I/FAL] =============================================================
[I/FAL] RT-Thread Flash Abstraction Layer initialize success.
Hello RISC-V
[W/DBG] disp:[parser_disp_init_para 575]of_property_read screen1_output_type fail


msh />Mount "sd0p0" on "/" success
hal_sdc_create 1
[os E] OS_MutexCreate():42, handle 0x4056e348
card_detect insert
mmc_send_app_op_cond,109 100
Initial card failed!!
[E/drv-sdmmc] init sdmmc failed!
sdmmc bytes_per_secotr:200, sector count:0
[E/drv-sdmmc] read offset 0 over part sector 0
[E/drv-sdmmc] device read mbr 1-sector failure

msh />ls bin/
Directory bin/:
hello.elf           341224
ping.elf            347336
pong.elf            342160
umailbox.elf        357440
vi.elf              517464
webclient.elf       393032
webserver.elf       489416
msh />

而RT-smart的msh就类似于linux里的shell,使用ls命令是查看文件, 用户态程序存放在bin文件夹下。

用户程序开发
RT-smart的用户态程序是和内核分离的,我们在userapps文件夹下可以看到一个叫做apps的文件夹,里面存放的就是用户程序的代码,每个程序以文件夹的形式分开。

17_userapp_1.png

默认带的这些程序就是rt-smart自带的示例,用于演示相关api的使用。

比如这里的hello程序,执行后功能就是在控制台打印出一行hello, world!\n。

我们需要开发任何用户程序都是按照类似的流程做的。

我们在msh里运行bin/hello,查看一下效果:

msh />bin/hello.elf
msh />hello world!

如果我们要创建新的程序,就复制hello程序目录到当前文件夹,然后在此基础上进行开发,程序写完后依然是使用scons命令完成编译,mksdcard.sh打包镜像即可

运行LVGL

在rt-smart上运行lvgl也很方便,而且得益于rt-smart的内核态与用户态分离,我们可以很方便的借(zhao)鉴(chao)大佬们之前的研究成果。

这里非常感谢网友Rb君的努力!他的工作如下:

丝滑的在RT-Smart用户态运行LVGL

https://club.rt-thread.org/ask/article/e8bc90918bd055eb.html

具体的原理我这里不再赘述,大家可以进他的帖子看看,我这里给出最快速的体验方法:

首先克隆 lvgl用户态程序

mkdir git_projs
cd git_projs/
git clone https://github.com/Rbb666/RT-Smart-UserAPP.git
cd .. # 回到userapps目录
cp -r git_projs/RT-Smart-UserAPP/userapps/media/ ./  # 复制media文件夹到我们的userapps

然后我们需要修改scons的编译脚本,这里用任何喜欢的编辑器打开userapps目录下的SConstruct文件,翻到最后,添加一行编译media文件夹:

18_userapp_2.png

因为我手上只有一块不支持电容触摸的RGB-LCD屏幕,所以很遗憾,我在这里将lvgldemo 里的auto play打开,达到不需要触屏,自动播放的效果。

19_userapp_3.png

然后依然是使用scons编译用户程序,mksdcard.sh打包镜像,重新下载到贴片TF卡中后,即可运行lvgl程序下面是效果演示:

4-lvg-resized.jpg

可以看到效果还是很不错的,480*272分辨率的屏幕能够达到60fps.

3: 感想

RISCV内核是一种全新开放指令集risc核心,打断了之前arm内核在相关领域内的垄断低位,几年内就推出了应用处理器级别的SOC,具有强大的性能,而且开发方式和之前基于arm的开发基本没有什么区别。

RT-smart操作系统其实我之前并未怎么了解,只知道是一种用于应用处理器(带MMU)的实时操作系统。

经过实际使用下来,我感觉用起来还是很舒服的,有别于linux,其具有启动快,中断快等优点,(arm-linux启动一般都需要数十秒,rt-smart可能只需要1秒)

使用scons开发,这一点也有别于linux的那一套makefile。需要一定的学习过程。

但是最大的问题是相关的文档还是太缺少了,光是对rt-smart这一套概念的理解就花了不少的时间,希望国内厂商以后还是能够在文档相关的工作做的更好。

4: 感谢

快来尝鲜!!使用 D1s (RDC2022 纪念版) 运行 RT-Smart

丝滑的在RT-Smart用户态运行LVGL

#14 全志 SOC » D1s RDC2022纪念版开发板开箱评测及点屏教程 » 2023-02-23 09:54:44

LIVPO
回复: 2

本文转载自:https://bbs.aw-ol.com/topic/3005/
作者@new_bee

目录
1.芯片介绍
2.开发板介绍
3.RT-Smart用户态系统编译使用
4.感想
5.引用

1. 芯片介绍
RISC-V架构由于其精简和开源的特性,得到业界的认可,近几年可谓相当热门。操作系统方面有RT-Thread,Linux等支持。在今年早些时候,Google希望RISC-V成为Android支持的“一级”架构。

D1s 是22nm 64bit RISC-V 架构的处理器,主频720MHz。内置64M DDR2。支持RGB,MIPI等视频输出接口,ADC、DAC、I2S、PCM、DMIC、OWA 等多种音频接口。音视频编解码支持如下:

Video decoding
    H.265 up to 1080p@60fps 
    H.264 up to 1080p@60fps 
    MPEG-1/2/4, JPEG, VC1 up to 1080p@60fps

Video encoding
    JPEG/MJPEG up to 1080p@60fps
    Supports input picture scaler up/down

芯片框图如下:
d1ssoc.png

2. 开发板介绍
RDC2022 纪念版开发板是基于D1s芯片的小尺寸开发板,尺寸为5.5cm*4cm。正面包含一块D1s核心板,外围电路采用ME3116作为DCDC降压芯片,CH340N作为USB-TTL芯片,PT4103作为背光驱动,并包含一块LM4890音频功放。总体电路比较简洁。

开发板上方USB为烧录口,下方为串口,可以在开发板启动后接串口调试。

.jpg

开发板背面为SD卡插槽,一个RGB888接口接显示屏,和一个触摸屏接口。该开发板还包含两组12脚的PMOD接口用于接插外设。

.jpg

RGB接口按引脚定义可以接入通用RGB屏幕,我这里接的是480*272的屏幕,引脚定义如下:

rgb口定义.png


3. RT-SMART用户态系统编译使用
RT-Smart 是基于 RT-Thread 操作系统上的混合操作系统,把应用从内核中独立出来,形成独立的用户态应用程序。这样更加安全。
以下编译过程参考了快来尝鲜!!使用 D1s (RDC2022 纪念版) 运行 RT-Smart,并将过程中一些小坑记录下,方便后面遇到同样问题的人。

3.1 刷机&调试环境准备

操作系统:Windows
zadig.7z

首先用typec数据线一端插入烧录口,按住FEL按钮同时另一端插入电脑,此时设备进入FEL模式。第一次插入设备管理器会发现未知设备。运行Zadig安装驱动,如下图:
zadig.png
之后就可以在FEL模式下刷机。

用typec数据线一端插入调试口,另一端插入电脑。电脑打开串口软件,选择对应串口,波特率设为500000,则可以通过串口进行调试。
serial.png

3.2 开发编译环境准备
操作系统:Ubuntu 20.04

下载用户态代码:

git clone https://github.com/RT-Thread/userapps.git

下载内核态代码:
注:位置可以与用户态代码分开,只要设置RISCV64的工具链环境变量即可

git clone https://github.com/RT-Thread/rt-thread.git

下载RISC-V 64工具链

cd userapps
python3 tools/get_toolchain.py riscv64

配置RISC-V 64工具链环境变量
注意:按官方脚本需要执行

source smart-env.sh riscv64

这个脚本完成两个工作:

设置RTT_CC等环境变量
copy riscv的config到.config
但是某些shell下获取当前脚本目录错误,导致无法完成copy,第一次使用的话会继续用默认的arm工具链编译。
比较简单的解决办法是执行两步:

source smart-env.sh riscv64
cp configs/def_config_riscv64 .config

3.3 编译rt-thread内核
进入bsp目录

cd rt-thread/bsp/allwinner/d1s

修改编译配置

scons --menuconfig

首先打开UART3串口,路径为

General Deivers Configuration->General Purpose UARTs

选中UART3,并修改TX引脚为GPIOG08,RX引脚为GPIOG09
uart3.png

设置终端使用UART3,路径为

RT-Thread Kernel->Kernel Device Object

修改为uart3
uart3modify.png

这回目标是点屏,所以要打开LCD驱动,路径为

General Deivers Configuration->Enable LCD

lcd.png

以上完成内核配置,保存退出。

编译内核:

scons

编译成功后会生成内核文件:
.png
烧录内核
下载xfel工具:xfel_v1.2.9.7z
将sd.bin拷贝到windows下xfel工具目录下。按住开发板FEL按钮同时另一端插入电脑。执行命令完成烧录:

xfel.exe sd write 57344 sd.bin

3.4 编译rt-smart用户态应用点屏
首先将D1s bsp目录下 mksdcard.sh 脚本拷贝到userapps目录下。
这里借用丝滑的在RT-Smart用户态运行LVGL的LVGL移植成果

下载修改代码:

https://github.com/Rbb666/RT-Smart-UserAPP.git

拷贝项目下的lvgl到userapps/apps目录下

由于一些宏定义缺失,需要将lvgl-nes/lv_rtt_port下的lv_conf.h和lv_port.h拷到对应目录下
.png
同时,由于我没有触摸屏设备,所以注释掉lv_demo.c中的触摸屏初始化代码
disabletouch.png

在用户态代码根目录下,编译用户态应用

scons

执行脚本制作root文件系统

./mksdcard.sh

生成sdroot.bin


最后烧录文件系统

xfel.exe sd write 8388608 sdroot.bin

3.5 点屏
烧录完成后重启,就可以用调试口看到目录下有lvgl.elf。执行点亮屏幕

./lvgl.elf

lvgl.jpg

4. 感想
总体而言,RISC-V的生态在厂商和开源社区的努力下逐步完善起来。芯片,开发板,操作系统都有诸多选择,工具链也可以较透明的无缝移植。
但是感触比较深的还是缺少更多的文档和入门教程,对于新人不会像树莓派等有开箱即用的效果(当然树莓派现在的性价比就不说了)。
另外,scons编译确实较方便,不过针对一些复杂的基于makefile的开源项目,移植到scons较为繁复。在用RISCV工具链编译一些基于makefile的开源项目时,也遇到了一些坑,之后会写文章分享。当然RISCV的发展不是一蹴而就的事,仍需业界和开源社区大力支持。

5. 引用
D1s
RT-Thread文档中心
快来尝鲜!!使用 D1s (RDC2022 纪念版) 运行 RT-Smart
丝滑的在RT-Smart用户态运行LVGL

#15 全志 SOC » 在Tina V853开发板上切换sensor » 2023-02-13 13:59:17

LIVPO
回复: 0

目的
V85x某方案目前默认Sensor是GC2053。实际使用时若需要用到GC4663(比如wdr功能)和SC530AI(支持500W),可按如下步骤完成切换。

步骤
下面以GC4663为例,SC530AI按相应方式适配。


  • Step1 检查Sensor驱动是否被编译成.ko文件

GC4663 Sensor驱动文件gc4663_mipi.c和配置Sensor驱动编译的Makefile文件路径的路径:

cpp
tina\lichee\linux-4.9\drivers\media\platform\sunxi-vin\modules\sensor

修改配置Sensor驱动编译的Makefile文件:
badd8248785d443697081edf9832fb5a.png


添加后,重新mkernel即可编译出GC4663驱动的ko文件。

fea9bceba2d343f795e9e87b6d0854e2.png


  • Step2 检查ISP效果文件是否已适配

效果文件gc4663_mipi_wdr_default_v853.h路径:

cpp
tina\external\eyesee-mpp\middleware\sun8iw21\media\LIBRARY\libisp\isp_cfg\SENSOR_H\gc4663

效果文件解析文件isp_ini_parse.c路径:

cpp
tina\external\eyesee-mpp\middleware\sun8iw21\media\LIBRARY\libisp\isp_cfg\

若没有sensor对应的效果文件,则需要先添加和适配。

适配后,通过make menuconfig修改sensor为gc4663。
6ba18ae08ed94d9c82c4287be85e280d.png

  • Step3 检查board.dts是否已适配

板级配置文件board.dts的路径:

cpp
tina\device\config\chips\v853\configs\perf1

cd8738d697024303abc0df74e8cd710c.png

其中,I2C地址可以从GC4663 Sensor驱动中找到。

cpp
tina\lichee\linux-4.9\drivers\media\platform\sunxi-vin\modules\sensor\gc4663_mipi.c

4315d546df96410b842e83b42f17fb0c.png

  • Step4 修改ko自动加载脚本

先将ko拷贝到/lib/modules/下,然后加载ko。
(1)拷贝ko
modules.mk的路径:

cpp
tina\target\allwinner\v853-perf1

02aa8ceffcd54e88b29f3b1da4ed89ef.png

(2)加载ko
S00mpp的路径:

cpp
tina\target\allwinner\v853-perf1\busybox-init-base-files\etc\init.d

ec50b82e7d93429da29f9b3e4672e389.png


  • Step5 重新编译mpp和固件

重新编译mpp和固件的命令:

cleanmpp && mkmpp && mp

#16 全志 SOC » LVGL视频播放界面实现方法 » 2022-12-27 14:10:23

LIVPO
回复: 4

1.主题
LVGL视频播放界面实现方法

2.问题背景
使用LVGL开发且需要在UI下显示视频或者显示摄像头数据,但是不知道如何实现,要么是只显示UI,要么就只显示视频。

3.具体表现
可以看下视频播放的时候有哪些元素。

0164d50146e9494692b31cf4010ba3fd.png

有播放按钮,进度条,设置等可交互的控件,这些都位于UI层。

UI的下方就是视频解码后的一帧数据,视频数据位于视频层。

4.问题分析
一般UI层位于视频层的上方,如果UI层没有设置透明度,那么会有一个背景色,覆盖了视频层,导致只能看到背景色和一些控制按钮。

5.根本原因
首先需要知道有图层的概念,下面的命令可以看到图层的信息:

cpp
root@TinaLinux:/# cat /sys/class/disp/disp/attr/sys
screen 0:
de_rate 300000000 hz, ref_fps:59
mgr0: 1280x800 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[1] force_sync[1] unblank direct_show[false] iommu[1]
dmabuf: cache[4] cache max[4] umap skip[0] umap skip max[18]
        lcd output      backlight( 50)  fps:60.0        1280x 800
        err:0   skip:67 irq:2300        vsync:0 vsync_skip:0
   BUF    enable ch[0] lyr[0] z[0] prem[N] a[pixel   0] fmt[ 77] fb[1280, 736; 640, 368; 640, 368] crop[   0,   0,1280, 720] frame[   0,   0,1280, 800] addr[fb200000,fb2e6000,fb359000] flags[0x       0] trd[0,0]
depth[ 0]    BUF    enable ch[1] lyr[0] z[16] prem[N] a[pixel 255] fmt[  0] fb[1280, 800;1280, 800;1280, 800] crop[   0,   0,1280, 800] frame[   0,   0,1280, 800] addr[ff800000,       0,       0] flags[0x
  0] trd[0,0]

在内核初始化过程中,显示驱动注册/dev/fb0,会申请UI层,可以看到ch[1] lyr[0],一般UI就一个地址addr[ff800000, 0, 0],并且也是最顶层的z[16],混合模式a[pixel 255]表示由应用控制UI层的透明度。

视频播放(使用TPlayer接口)的时候会通过中间件申请视频图层,可以看到ch[0] lyr[0],并且yuv三个地址一直在变化addr[fb200000,fb2e6000,fb359000],通常视频会放到最底层z[0]。

当应用没有透明时,因为UI层的zorder比视频层大,因此只能看到UI,看不到视频,所以应用需要“挖空”。

6.解决办法
下面代码里的屏幕,一般是指/dev/fb0,LVGL版本是8.3.2。

使用下面的代码前需要在lv_conf.h中设置参数:

cpp
#define LV_COLOR_SCREEN_TRANSP 1
cpp
/* 初始化屏幕风格 */
static lv_style_t style_scr_act;
if (style_scr_act.prop_cnt == 0) {
    lv_style_init(&style_scr_act);
    /* 默认不是透明的,后面按需要切换即可 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_COVER);
    /* 一定要应用风格,不然也是没有效果的 */
    lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
}

/* 这里根据按钮状态,切换不同风格,一种是UI能够透明看到底下的视频,一种是UI覆盖视频,视频就看不到了 */
if (lv_obj_has_state(btn, LV_STATE_CHECKED)) {
    /* 这里切换为UI透明 */
    lv_label_set_text(label, "Stop");
    /* 这里设置屏幕是透明的 */
    lv_disp_get_default()->driver->screen_transp = 1;
    /* 这里设置屏幕背景是透明的 */
    lv_disp_set_bg_opa(lv_disp_get_default(), LV_OPA_TRANSP);
    /* 这里清空屏幕,不清空的话,可能不会生效 */
    lv_memset_00(lv_disp_get_default()->driver->draw_buf->buf_act,
            lv_disp_get_default()->driver->draw_buf->size
                    * sizeof(lv_color32_t));
    /* 这里屏幕风格切换为透明的 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_TRANSP);
    /* 通知风格变化,需要更新 */
    lv_obj_report_style_change(&style_scr_act);
} else {
    /* 这里切换为UI不透明,也就是覆盖视频 */
    lv_label_set_text(label, "Play");
    /* 这里设置屏幕是不透明的 */
    lv_disp_get_default()->driver->screen_transp = 0;
    /* 这里设置屏幕背景是不透明的 */
    lv_disp_set_bg_opa(lv_disp_get_default(), LV_OPA_COVER);
    /* 这里屏幕风格切换为不透明的 */
    lv_style_set_bg_opa(&style_scr_act, LV_OPA_COVER);
    /* 通知风格变化,需要更新 */
    lv_obj_report_style_change(&style_scr_act);
}

#17 全志 SOC » D1 DOCK PRO buildroot编译的内核烧录之后上电 » 2022-11-29 09:53:49

LIVPO
回复: 1

请问我在将用buildroot编译的内核烧录之后上电出现这种报错是为什么呀

6b215055556481e0.png

#18 全志 SOC » 全志D1-H开发板接OLED的MIPI屏幕实时亮度改变问题 » 2022-11-18 15:38:07

LIVPO
回复: 1

问题一
在驱动中有个接口:

/* sel: 0:lcd0; 1:lcd1 */
static s32 LCD_set_bright(u32 sel, u32 bright)
{
	sunxi_lcd_dsi_dcs_write_1para(sel,0x51,bright);
	return 0;
}

操作这个接口调整亮度的话,显示是无法正常的。是否驱动在操作这个接口过程中需要等待屏幕数据发帧结束? 感觉是要等的,但是目前还没详细看代码流程。

解答:

发送命令要处于LP模式,在送帧(HP模式)的时候去切换模式肯定会导致黑屏的,需要在中断的消隐区间去设置背光,可以翻一下lcd调试说明文档,里面有esd这个章节,显示驱动中也有esd相关代码,做esd就是在中断的消隐区间去读mipi的寄存器,判断屏的状态。可以读那么就可以写了。

问题二

模仿esd程序进行中断中修改亮度操作,可以写入亮度成功,也可以读到东西,但是中断就无法重新进入了。是否有什么注意到的地方。

static s32 lcd_set_oled_bright(u32 sel,u32 bright)
{
	s32 ret = 0;
	u8 result[16] = {0};
	s32 nump = 1;

	ret = sunxi_lcd_dsi_dcs_read(0, 0x54, result,&nump);

	dsi_dcs_wr_1para(sel, 0xFE, 0x00);	 //{ 0xFE,1,{0x00} },
	dsi_dcs_wr_1para(sel, 0x51, 0x50);


	printk(KERN_WARNING	"wwwwwwwwwwww lcd_set_oled_bright :bright = %d  read result :%02x \n",bright,result[0]);
	return 0;	
}


/*此处省略*/

struct __lcd_panel rm69330_139_panel = {
	/* panel driver name, must mach the name of
	 * lcd_drv_name in sys_config.fex
	 */
	.name = "rm69330_139",
	.func = {
		.cfg_panel_info = lcd_cfg_panel_info,
			.cfg_open_flow = lcd_open_flow,
			.cfg_close_flow = lcd_close_flow,
			.lcd_user_defined_func = lcd_user_defined_func,
			.set_bright = LCD_set_bright,
			.esd_check = lcd_esd_check,
			.reset_panel = lcd_reset_panel,
			.set_esd_info = lcd_set_esd_info,	
			.oled_set_bright = lcd_set_oled_bright,
	},
};
#if defined(__LINUX_PLAT__)
static irqreturn_t disp_lcd_event_proc(int irq, void *parg)
#else
static irqreturn_t disp_lcd_event_proc(void *parg)
#endif
{
	struct disp_device *lcd = (struct disp_device *)parg;
	struct disp_lcd_private_data *lcdp = NULL;
	struct disp_manager *mgr = NULL;
#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)
	struct disp_eink_manager *eink_manager = NULL;
#endif
	u32 hwdev_index;
	u32 irq_flag = 0;
	unsigned int panel_extend_dirty;
	unsigned int panel_extend_modify_oledbright;
	unsigned long flags;

	if (lcd == NULL)
		return DISP_IRQ_RETURN;

	hwdev_index = lcd->hwdev_index;
	lcdp = disp_lcd_get_priv(lcd);

	if (lcdp == NULL)
		return DISP_IRQ_RETURN;

#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)
	eink_manager = disp_get_eink_manager(0);
	if (eink_manager == NULL)
		return DISP_IRQ_RETURN;
#endif

	if (disp_al_lcd_query_irq
	    (hwdev_index, LCD_IRQ_TCON0_VBLK, &lcdp->panel_info)) {
#if defined(SUPPORT_EINK) && defined(CONFIG_EINK_PANEL_USED)

		eink_display_one_frame(eink_manager);
#else
		int cur_line =
		    disp_al_lcd_get_cur_line(hwdev_index, &lcdp->panel_info);
		int start_delay =
		    disp_al_lcd_get_start_delay(hwdev_index, &lcdp->panel_info);
#if defined(CONFIG_DISP2_LCD_ESD_DETECT)
		if (lcdp->lcd_panel_fun.esd_check &&
		    lcdp->lcd_panel_fun.reset_panel) {
			++lcdp->esd_inf.cnt;
			if (cur_line < 2 &&
			    !atomic_read(&lcdp->lcd_resetting) &&
			    lcdp->esd_inf.cnt >= lcdp->esd_inf.freq) {
				disp_al_lcd_disable_irq(hwdev_index, LCD_IRQ_TCON0_VBLK,
				&lcdp->panel_info);

				if (!lcdp->esd_inf.esd_check_func_pos ||
				    lcdp->lcd_panel_fun.esd_check(lcd->disp)) {
					/*request reset*/
					atomic_set(&lcdp->lcd_resetting, 1);
					schedule_work(&lcdp->reflush_work);
					printk(KERN_WARNING	"wwwwwwwwwwww lcd_esd_check disp_lcd_event_proc 1633 \n");
				}
					disp_al_lcd_enable_irq(hwdev_index, LCD_IRQ_TCON0_VBLK,
			       &lcdp->panel_info);
				printk(KERN_WARNING	"wwwwwwwwwwww after lcd_esd_check disp_lcd_event_proc 1635 \n");
				lcdp->esd_inf.cnt = 0;
			}
		}
#endif

		mgr = lcd->manager;
		if (mgr == NULL)
		{
			printk(KERN_WARNING	"wwwwwwwwwwww after if (mgr == NULL) 1644 \n");
			return DISP_IRQ_RETURN;
		}

		if (cur_line <= (start_delay - lcdp->judge_line))
			sync_event_proc(mgr->disp, false);
		else
			sync_event_proc(mgr->disp, true);
#endif
	} else {
		irq_flag = disp_al_lcd_query_irq(hwdev_index, LCD_IRQ_TCON0_CNTR,
						&lcdp->panel_info);
		irq_flag |=
		    disp_al_lcd_query_irq(hwdev_index, LCD_IRQ_TCON0_TRIF,
					  &lcdp->panel_info);

		if (irq_flag == 0)
			goto exit;

		if (disp_al_lcd_tri_busy(hwdev_index, &lcdp->panel_info)) {
			/* if lcd is still busy when tri/cnt irq coming,
			 * take it as failture, record failture times,
			 * when it reach 2 times, clear counter
			 */
			lcdp->tri_finish_fail++;
			lcdp->tri_finish_fail = (lcdp->tri_finish_fail == 2) ?
			    0 : lcdp->tri_finish_fail;
		} else
			lcdp->tri_finish_fail = 0;

		mgr = lcd->manager;
		if (mgr == NULL)
			return DISP_IRQ_RETURN;

#if defined(CONFIG_DISP2_LCD_ESD_DETECT)
		if (lcdp->lcd_panel_fun.esd_check &&
		    lcdp->lcd_panel_fun.reset_panel) {
			++lcdp->esd_inf.cnt;
			if (!atomic_read(&lcdp->lcd_resetting) &&
			    lcdp->esd_inf.cnt >= lcdp->esd_inf.freq) {
				if (!lcdp->esd_inf.esd_check_func_pos ||
				    lcdp->lcd_panel_fun.esd_check(lcd->disp)) {
					/*request reset*/
					atomic_set(&lcdp->lcd_resetting, 1);
					schedule_work(&lcdp->reflush_work);
					printk(KERN_WARNING	"wwwwwwwwwwww lcd_esd_check disp_lcd_event_proc 1685 \n");
				}
				printk(KERN_WARNING	"wwwwwwwwwwww after lcd_esd_check disp_lcd_event_proc 1688 \n");
				lcdp->esd_inf.cnt = 0;
			}
		}
#endif

		if (lcdp->tri_finish_fail == 0) {
			sync_event_proc(mgr->disp, false);
			disp_al_lcd_tri_start(hwdev_index, &lcdp->panel_info);
		} else
			sync_event_proc(mgr->disp, true);
	}

	spin_lock_irqsave(&lcd_data_lock, flags);
	panel_extend_dirty = lcdp->panel_extend_dirty;
	lcdp->panel_extend_dirty = 0;
	/*这里是我添加的调整oled亮度的地方, bright的值通过ioctl修改,并 lcdp->panel_extend_modify_oledbright; 置位,让中断来处理这个亮度*/
	panel_extend_modify_oledbright = lcdp->panel_extend_modify_oledbright;
	lcdp->panel_extend_modify_oledbright = 0;
	spin_unlock_irqrestore(&lcd_data_lock, flags);
	if (panel_extend_dirty == 1)
		disp_al_lcd_cfg_ext(lcd->disp, &lcdp->panel_extend_info_set);

	if(panel_extend_modify_oledbright == 1)
	{
		if(lcdp->lcd_panel_fun.oled_set_bright)
		{
			u32 getbl = disp_lcd_get_bright(lcd);
			
			lcdp->lcd_panel_fun.oled_set_bright(lcd->disp,getbl);
		}
	}
	
exit:
	printk(KERN_WARNING	"wwwwwwwwwwww before DISP_IRQ_RETURN  1709 \n");
/*尝试加入的打印信息, 一旦执行了亮度调整,这个中断服务不再重新进入了,但是亮度调节是成功的*/
	return DISP_IRQ_RETURN;
}

解答:

在代码块2里做如下修改

#if 1
	if(panel_extend_modify_oledbright == 1)
	{
		if(lcdp->lcd_panel_fun.oled_set_bright)
		{
			u32 getbl = disp_lcd_get_bright(lcd);
			
			lcdp->lcd_panel_fun.oled_set_bright(lcd->disp,getbl);
/*加入下面这部分逻辑,让他重新触发中断即可*/
			if (lcdp->tri_finish_fail == 0) {
				sync_event_proc(mgr->disp, false);
				disp_al_lcd_tri_start(hwdev_index, &lcdp->panel_info);
			} else
				sync_event_proc(mgr->disp, true);			
		}

	}

#19 全志 SOC » 在MQ-R(F133)上 进行全志Melis-4.0(rt-thread内核)环境搭建与初步编译介绍 (转载) » 2022-11-02 10:50:33

LIVPO
回复: 8

转载地址: https://blog.csdn.net/qq_43280079/article/details/127189338

什么是MELIS?

      Melis是全志科技自研的一套rtos系统。自全志科技创建以来,该系统就已经问世,并持续抗战了近十年,其主要应用其自家的F系列芯片产品上,在MP3与老人机非常流行的时代,该系统配合着其F系列的芯片,真的是能抗能打,早在2012-2013年的时候,Melis的装机量就已经过亿,但因为其属于自研系统,全志科技并没有将其开源,导致虽装机量很多,但是很少人知道。
  Melis之所以能抗战那么久,或者说全志科技之所以能在那个芯片行业并不出彩的年代坚持下来,我觉得主要归功于其F1C100s/F1C200s这个代的芯片。这款芯片差不多是十年前的产品,但是因为其具有很强的编解码能力,以及异于常人的性价比,现如今依然活跃在各个微媒体市场。
  Melis经过了多个迭代,现如今配合着其最新推出的F133(risc-V)芯片,推出了最新的Melis4.0系统,并使用了更多人熟悉的RT-thread内核,在GitHub上,部分进行了开源,引领广大开发爱好者参与进risc-V的生态建设中。最近想用F133做一点有趣的开发,因此也开始研究Melis4.0。
  个人觉得,通过学习melis系统,可以让学习者更了解系统的构成,什么是系统调用?系统是如何加载模块的?什么是BSP?等,对于学习者来说,是非常不错的入门选择。

开发环境

Ubuntu22.04虚拟机
MQ-R(F133) 芒果派开发板

代码下载
GitHub的项目地址如下:

https://github.com/Tina-Linux/d1s-melis

仓库的简介提示,如果需要编译代码,需要手动下载一下相应的工具链并将工具链放在对应目录里。

工具链地址如下:

https://github.com/Tina-Linux/d1s-melis/releases

建议直接下载这个,因为工程中默认的也是这个

866b889317404ca1b2f9ddc9e2eec3a7.png

代码下载好后,解压。并将下载好并解压好的工具链放在代码的toolchain目录下。(我这里将原项目目录更名为了source,并不影响其它)

59aa7ebbbda34e6b8e9e03fca377ef1b.png

一切准备就绪后,即可开始编译。如果是新的系统,建议先安装一些依赖库,后续可能会用到。

sudo apt install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

编译
环境变量
在代码编译之前,我们可能需要设置很多环境变量(lunch 、croot、pack等),因为每一次的环境变量都是比较固定的,因此,项目中,将这些初始化环境变量的操作,都整合成了两个脚本,分别是"envsetup.sh"和“melis-env.sh”。因为melis-env.sh最终会自动调用“envsetup.sh”,因此,我们只需要执行“melis-env.sh”即可

#初始化环境变量
melis-env.sh

初始化环境变量后,我们需要通过“lunch”来选择我们需要编译的项目,lunch是通过扫描projects文件夹下的文件夹,进行识别一共有多少套方案,lunch选中后,系统的编译参数、打包参数,运行参数等,就会使用对应方案文件夹中的配置文件。(具体为什么叫lunch,原因不详,或许本应该是launch?学习英语任重道远!)

对应方案

#通过lunch来选择要编译的项目
lunch

238c5f319f3f4294bd88fb32c7027bdb.png

因为我使用的是麻雀的开发板,因此我这里选择3.

编译
以上流程走完后,原工程是可以直接make的,但是第一次编译,或者选择了不同方案后编译,建议都是要clean一下,重新lunch一次,避免环境不干净。

#先clean一下
make clean

#再把方案清一下
make distclean

#重新lunch,再选择一次方案
lunch

#执行make操作
make

注意,如果你在kconfig中,增加了某些选项,但是没有在deconfig中增加对应的配置,直接make可能会报错。需要通过make menuconfig来重新生成默认的编译配置。

#通过make menuconfig选择编译参数
make menuconfig

注意:curses.h: No such file or directory ,那是因为环境没弄好,“sudo apt install libncurses5-dev” 即可

2326e51f410b4585ac031a1e9fb66b74.png

第一次编译,直接保存即可。配置默认是保存在当前目录下的 “.config”文件中,最好不要改文件名。如果不想每次编译都make menuconfig,那么就将当前的“.config”的内容,更新到对应方案目录下的deconfig文件中。比如我要改的话,那我就需要将“.config”文件中的内容,全部替换到**“projects/d1s-mq/configs/deconfig”**文件中,这样每次lunch之后,系统默认来这里来拿编译参数。

以上完成后,就可以直接make了,如果没改过任何东西的话,是可以直接编译通过的。如果不通过,可能要检查一下自己的环境是否安装完善,勤加百度,即可解决问题。

打包
编译成功后,可以通过pack,将编译好的文件,全部打包成一个.img的固件。
因为固件可能是用于卡烧录的,用于nor烧录的,用于nand烧录的,根据烧录方式的不同,需要搭配不同的参数,默认是打包生成nor烧录的固件。

#通过pack指令,打包生成固件(默认生成nor固件)
pack

#生成nand烧录固件
pack -a nand

#生成卡烧录的固件
pack -a card

最终的固件将会生成在“out/对应方案/”目录下。

注意:如果出现如下错误:

78a656727f054bd08345a4376815e359.png

这个时候,打包是没有成功的,cd到对应目录下,查看文件夹下,又是存在这个dragon文件,有点神奇。其实是因为dragon这个程序是在32位机器上编译出来的,这是32位的程序,在64位的Ubuntu中运行需要提前安装32位的库。

请执行操作:

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 -y
sudo apt install lib32z1 -y

重新pack后,没有提示,打包成功。

注意事项:
source melis-env.sh 的操作仅在当前终端有效,新开终端,或者关闭了终端后,需要重新source一下,才能进行下面的操作。

lunch操作与source操作一样,都是只对当前终端有效,每次打开新终端,都需要进行一次source、lunch。

小贴士:

source了之后,可以使用各种快捷调整指令,方便开发

croot   回到项目根目录
ckernel   跳转至kernel文件夹
cmodoule  跳转至模块文件夹
。。。(更多操作,可以看环境脚本“envsetup.sh”中的function有哪些)

#20 全志 SOC » Tina下 DNS配置好后 重启消失问题 » 2022-10-27 10:20:01

LIVPO
回复: 0

请教一下各位大佬,在Tina下配置DNS时,在/etc/resolv.conf写入DNS的nameserver,写好以后是OK的,可以正常Ping通网址。但是重启以后,/etc/resolv.conf的内容就消失了,这个是什么情况

#21 Re: 全志 SOC » t113每次重启网卡的mac地址随机问题 » 2022-10-12 13:34:40

神棍地海棠 说:

看起来是不是 md5 没编译进去

是的,按照你说的需要将md5加到内核里

另外还有一个问题就是#define sunxi_get_soc_chipid(x) {}这里获取id的函数是空的,

qq图片20220915164600.jpg

然后参考了一下全志其他的代码是用到了sunxi-sid.c里的,然后加了一下这个头文件,就可以获取到chipid了

qq图片20220915164605.jpg

这样就没有上面的报错了

#22 全志 SOC » t113每次重启网卡的mac地址随机问题 » 2022-10-09 14:47:19

LIVPO
回复: 2

请教下各位大佬,t113每次重启网卡的mac地址都是随机的,跟了内核后发现是这里失败了 crypto_alloc_ahash

QQ图片20220915164531.jpg

内核打印Failed to alloc md5,错误内容如下

QQ图片20220915164525.jpg

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn