OK536N-C开箱以及在Linux下如何管理开发板
-
前言
OK536N-C终于到我手上了,因为我的主要领域是做嵌入式音视频。例如相机类产品,录像类产品,直播类产品都是我所涉及到的。本片文章一起来开箱见证下OK536N-C有哪些魅力,在音视频领域如何,据说很强。
对于一个嵌入式领域的开发者来说,强不代表一切,还要关注软硬件的资料是否全,各种文档是否详细,技术售后支持是否到位。等一系列因素,如果有一个不太好,就会在整体开发过程中耽搁大事。
对于学生而言,更是如此,没有详细的资料,怎么能够快速开发出来作品,拿什么去打比赛!我个人PC就是Ubuntu,一起看看在Ubuntu下能否一路畅通的玩耍。
truedei@truedei-code:truedei$ uname -a Linux truedei-code 6.11.0-25-generic #25~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 17:20:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linux truedei@truedei-code:truedei$
一、开箱(bu)美照
因为事先去了解过某宝上OK536N-C的套餐,其中就有LVDS 10存屏幕和MIPI 7寸屏幕。10寸的大屏幕, 谁看谁心动呀,特意借到了一个10寸的LVDS的屏幕。
上电后:
这是我改了fbinit_test代码之后的效果:
二、研究如何启动
一开始不要着急插电源开机,先看手册。
手册是真的太详细了,而且手册是在线的,不用翻来翻去打开一个一个的pdf了,太赞了。之前开发全志的芯片,看手册全是一个一个的加密的pdf,很不爽。飞凌的团队把文档做的很细,并且几乎都在线文档化了。而且还是语雀来写的,我真是太高兴了,我是比较喜欢写博客的,平时记录一些东西,也都是在语雀上,使用语雀已经至少6年了,算是重度患者。
找到DC12V电源插口,找到开关,找到串口位置基本上就搞定了,如果有屏幕的话,再找到你对应屏幕的接线位置。
说到屏幕,做的很细心,可以看到,基本上闭眼就可以安装:(给你贴着怎么安装,我就直接安装的,很顺利!)
按照要求接好线
都接好线就可以准备开机了。
三、Ubuntu下连接串口到OK536N-C
因为的我的PC是Ubuntu系统的,所以没有Windows这么多的GUI图形工具可以用.OK536N-C的手册里也并没有提到PC机器是Ubuntu时怎么搭建环境,这个很遗憾.
首先确定USB-A----USB-C的线插到电脑上之后的串口是什么:
插上前执行一次lsusb:
truedei@truedei-code:truedei$ lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 046d:c548 Logitech, Inc. Logi Bolt Receiver Bus 001 Device 003: ID 0b05:1939 ASUSTek Computer, Inc. AURA LED Controller Bus 001 Device 004: ID 05e3:0610 Genesys Logic, Inc. Hub Bus 001 Device 006: ID 3554:fa09 Compx 2.4G Wireless Receiver Bus 001 Device 007: ID 8087:0029 Intel Corp. AX200 Bluetooth Bus 001 Device 008: ID 04e2:1414 Exar Corp. XR21V1414 4-channel UART Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003 Device 002: ID 1d6b:0102 Linux Foundation EEM Gadget Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub truedei@truedei-code:truedei$ truedei@truedei-code:truedei$
拔掉后执行一次:
truedei@truedei-code:truedei$ lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 046d:c548 Logitech, Inc. Logi Bolt Receiver Bus 001 Device 003: ID 0b05:1939 ASUSTek Computer, Inc. AURA LED Controller Bus 001 Device 004: ID 05e3:0610 Genesys Logic, Inc. Hub Bus 001 Device 006: ID 3554:fa09 Compx 2.4G Wireless Receiver Bus 001 Device 007: ID 8087:0029 Intel Corp. AX200 Bluetooth Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003 Device 002: ID 1d6b:0102 Linux Foundation EEM Gadget Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub truedei@truedei-code:truedei$
经过对比即可看出:"XR21V1414 4-channel UART"就是我们想找的.
Bus 001 Device 008: ID 04e2:1414 Exar Corp. XR21V1414 4-channel UART
其实如果先看过文档的话也可以参考:
查看是否生成了/dev/ttyUSB*
truedei@truedei-code:truedei$ ls /dev/ttyUSB* /dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 truedei@truedei-code:truedei$
接下来我们要用到一些ubuntu下的串口工具,例如putty
如果你没有putty的话,可以安装下:
sudo apt install putty
启动putty时记得使用sudo,否则操作串口可能没有权限:
sudo putty
使用ttyUSB0,波特率115200进入:
一路回车,出现OK536 Login就是串口连接成功了:
账号:root
密码:无,直接回车成功后的界面:
四、使用ssh远程
首先连上网,不喜欢wifi的话,就用有线,接上LAN后,在串口里执行udhcpc,就会获取到ip:
然后就可以使用ssh远程了:(没有密码)
truedei@truedei-code:truedei$ ssh root@192.168.2.105 root@OK536:~# root@OK536:~#
我个人调试比较喜欢用scp命令,能使用ssh,基本上就能使用scp。
可以看到/mnt/UDISK有14G的存储空间:
root@OK536:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/root 991M 385M 591M 40% / tmpfs 962M 300K 961M 1% /tmp tmpfs 962M 460K 961M 1% /run devtmpfs 959M 0 959M 0% /dev /dev/mmcblk0p1 128M 5.3M 123M 5% /run/media/mmcblk0p1 /dev/by-name/UDISK 14G 107M 14G 1% /mnt/UDISK root@OK536:~#
之后可以把测试的程序和相关的东西都远程拷贝到/mnt/UDISK即可。
例如:编译了fdinit程序,然后远程拷贝到设备里:
truedei@truedei-code:fbinit_test$ make -j10 -e cp -f fbinit /media/truedei/soft/Ok536N-C/OKT536-linux-sdk/buildroot/package/auto/sdk_demo/bin make finish!!! truedei@truedei-code:fbinit_test$ truedei@truedei-code:fbinit_test$ truedei@truedei-code:fbinit_test$ scp ./fbinit root@192.168.2.105:/mnt/UDISK/ fbinit 100% 23KB 10.1MB/s 00:00 truedei@truedei-code:fbinit_test$
然后设备里就有了:
root@OK536:~# ls -l /mnt/UDISK/fbinit -rwxrwx--- 1 root disk 23376 May 18 17:26 /mnt/UDISK/fbinit root@OK536:~#
然后就可以运行了:
root@OK536:~# /mnt/UDISK/fbinit fbinit test version:V2.0.20220506 ================Usage================ /fbinit means:clean /dev/fb0 /fbinit 0 means:clean /dev/fb0 /fbinit 1 means:clean /dev/fb1 /fbinit 2 means:clean /dev/fb2 ================usage================ cleanning /dev/fb0 ...
这是我改了fbinit_test代码之后的效果,没改的话,只是清空fb:
修改后的代码:
#include <stdio.h> #include <string.h> #include <sys/mman.h> #include <linux/fb.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <semaphore.h> #include <errno.h> #include <stdlib.h> #include <time.h> #include <sys/ioctl.h> #include <unistd.h> #include <linux/videodev2.h> int main(int argc, char *argv[]) { printf("fbinit test version:%s\n", MODULE_VERSION); char dev_name[20]; memset(dev_name, 0, sizeof(dev_name)); if (argc == 1) { printf("================Usage================\n"); printf("/fbinit means:clean /dev/fb0\n"); printf("/fbinit 0 means:clean /dev/fb0\n"); printf("/fbinit 1 means:clean /dev/fb1\n"); printf("/fbinit 2 means:clean /dev/fb2\n"); printf("================usage================\n"); sprintf(dev_name, "/dev/fb0"); } else if (argc == 2) { sprintf(dev_name, "/dev/fb%d", atoi(argv[1])); } printf("cleanning %s ...\n", dev_name); int fd; struct fb_var_screeninfo var; struct fb_fix_screeninfo finfo; // 打开帧缓冲设备 if ((fd = open(dev_name, O_RDWR)) == -1) { printf("open file %s fail. \n", dev_name); return 0; } // 获取固定屏幕信息 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { printf("get fixed screen information failure\n"); close(fd); return -1; } int screensize = finfo.smem_len; // 获取可变屏幕信息 if (ioctl(fd, FBIOGET_VSCREENINFO, &var) == -1) { printf("get variable screen information failure\n"); close(fd); return -1; } // 将帧缓冲区映射到用户空间 char *frameBuffer = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (frameBuffer == MAP_FAILED) { printf("mmap framebuffer failed\n"); close(fd); return -1; } // 动态生成彩条图像(简单动画:每次运行条纹颜色偏移) int width = var.xres; int height = var.yres; int bpp = var.bits_per_pixel / 8; int offset = time(NULL) % width; // 随时间变化的偏移 float PI = 3.14159265358979323846; int fl_num = 100; int t = 0; while (1) { t++; float time = t * 0.05f; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 多重正弦波叠加,制造动态波浪感 float fx = (float)x / width; float fy = (float)y / height; float wave = sinf(2 * PI * fx * 2 + time) + 0.5f * sinf(2 * PI * fx * 4 + time * 1.5f) + 0.25f * sinf(2 * PI * fx * 8 + time * 2.5f); // 波浪影响亮度 float center = height / 2.0f + wave * 50.0f; float dist = fabsf(y - center); // 距离中心波浪越近越亮 float brightness = expf(-dist * 0.03f); // 色彩渐变(可根据需要修改) unsigned char r = (unsigned char)(brightness * 80 + fx * 175); unsigned char g = (unsigned char)(brightness * 180 + fy * 75); unsigned char b = (unsigned char)(brightness * 255); int pos = (y * finfo.line_length) + (x * bpp); if (bpp == 4) { frameBuffer[pos + 0] = b; frameBuffer[pos + 1] = g; frameBuffer[pos + 2] = r; frameBuffer[pos + 3] = 0xFF; } else if (bpp == 3) { frameBuffer[pos + 0] = b; frameBuffer[pos + 1] = g; frameBuffer[pos + 2] = r; } else if (bpp == 2) { unsigned short pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); *((unsigned short *)(frameBuffer + pos)) = pixel; } } } // usleep(30 * 1000); } // 解除映射 munmap(frameBuffer, screensize); close(fd); printf("clean %s finish\n", dev_name); }
文档很详细,很快就能搭建好开发环境,并且修改自己想要的代码,然后编译出来自己的程序进行调试。
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号