导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页
    1. 主页
    2. bigfly
    3. 帖子
    B
    • 资料
    • 关注 0
    • 粉丝 0
    • 我的积分 2140
    • 主题 28
    • 帖子 39
    • 最佳 3
    • 群组 0

    bigfly 发布的帖子

    • 回复: 论坛的一个小小bug

      @zhoudaxia3000 这么看好像是8+1=9和11+1=12,有没有懂的老哥说一下什么情况

      发布在 灌水区
      B
      bigfly
    • 回复: RT-Thread on D1H. LCD work, USB in progress.

      @ylyamin 在 RT-Thread on D1H. LCD work, USB in progress. 中说:

      I’m writing a series of articles covering the knowledge and experience I’ve gained:

      D1-1. Introduction - Motivation and intention.
      D1-2. Boot process - Existing Allwinner D1H bootloaders best practice in example with booting Linux and RT-Thread, also JTAG and GDB.
      D1-3. RT-Thread overview and Build - Overview of RT-Thread structure and libraries. Compile RT-Thread for Allwinner D1H platform.
      D1-4. Makefile and Hardware changes - My repository structure, Makefile and Hardware changes was needed to be done.
      D1-5. LCD Display driver - Display driver for DevTerm R-01, uConsole R-01 and Sipeed Lichee RV.
      D1-6. USB Keyboard - USB Keyboard driver for ClockworkPi DevTerm, still not working.

      Detailed article,nice

      发布在 MR Series
      B
      bigfly
    • 回复: 更改分区

      @yyyyppppp Tina Linux 存储介质切换:eMMC,SPI NAND,SPI NOR,SD Card,SD NAND
      https://bbs.aw-ol.com/topic/1701/share/1

      发布在 其它全志芯片讨论区
      B
      bigfly
    • 回复: Openharmony D1编译下载代码失败

      是哪位大佬给D1移植了Openharmony吗

      发布在 MR Series
      B
      bigfly
    • T113-i RISC-V内核SDK公布了吗?

      T113-i RISC-V内核SDK公布了吗?

      发布在 创龙科技专区
      B
      bigfly
    • 回复: 请问D1-H的SDK是否完全开源免费试用的?

      @a5992230 2级了直接按文档步骤拉就可以用了

      发布在 MR Series
      B
      bigfly
    • 更换lcd屏幕

      我手上有一块480854的屏幕,现在想测试一下 在.fex文件中我发现,只要我把下面的这两个参数改成480854,在后面打包、烧录运行时就会出现问题

      fb0_width                = 480
      fb0_height               = 854
      

      问题如下:
      /etc/init.d/rcS: line 60: 1231 Segmentation fault insmod /system/vendor/modules/mali.ko
      挂载mali.ko文件显示段错误,具体打印消息如下:
      我这种情况是gpu不能用吗?我应该怎么解决这个问题

      [    4.223285] Mali: Enable gpu power successfully.
      [    4.223364] Mali: Set gpu frequency to 384 MHz
      [    4.223434] Mali: Mali GPU initialization finished.
      [    4.223881] Mali: ERR: /home/forlinx/work/lichee/linux-3.10/modules/gpu/mali400/kernel_mode/driver/src/devicedrv/mali/common/mali_mem_validation.c
      [    4.223892]            mali_mem_validation_add_range()  35
                                Failed to add frame buffer memory; incorrect alignment
      
      [    4.223906] Mali: ERR: /home/forlinx/work/lichee/linux-3.10/modules/gpu/mali400/kernel_mode/driver/src/devicedrv/mali/common/mali_kernel_core.c
      [    4.223912]            mali_parse_config_memory() 700
                                Failed to register frame buffer memory region
      
      [    4.224137] Unable to handle kernel paging request at virtual address 00100104
      [    4.224146] pgd = e1938000
      [    4.224152] [00100104] *pgd=6232e831, *pte=00000000, *ppte=00000000
      [    4.224169] Internal error: Oops: 817 [#1] PREEMPT SMP ARM
      [    4.224177] Modules linked in: mali(O+) gt9xxnew_ts
      [    4.224196] CPU: 0 PID: 1231 Comm: insmod Tainted: G        W  O 3.10.65 #446
      [    4.224205] task: e2f47a80 ti: e183a000 task.ti: e183a000
      [    4.224221] PC is at unregister_shrinker+0x30/0x5c
      [    4.224232] LR is at _raw_spin_unlock_irqrestore+0x38/0x58
      [    4.224241] pc : [<c00d4614>]    lr : [<c06ff900>]    psr: 40070013
                     sp : e183bc80  ip : e183bc20  fp : e183bc94
      [    4.224249] r10: e22a9664  r9 : 00000001  r8 : bf03f564
      [    4.224257] r7 : 00000000  r6 : e2e9d600  r5 : c0ad4eb0  r4 : bf03f364
      [    4.224264] r3 : 00200200  r2 : 00100100  r1 : 60070013  r0 : c0ad4eb0
      [    4.224273] Flags: nZcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
      [    4.224280] Control: 10c53c7d  Table: 6193806a  DAC: 00000015
      [    4.224286]
                     PC: 0xc00d4594:
      [    4.224292] 4594  e24cb004 e52de004 e8bd4000 e3a03000 e1a05000 e59f4030 e5803014 e1a00004
      [    4.224316] 45b4  eb18a540 e5943014 e285200c e2841010 e5842014 e585100c e1a00004 e5853010
      [    4.224339] 45d4  e5832000 ebfdd6c9 e89da830 c0ad4eb0 e1a0c00d e92dd830 e24cb004 e52de004
      [    4.224362] 45f4  e8bd4000 e1a04000 e59f5030 e1a00005 eb18a52c e5943010 e1a00005 e594200c
      [    4.224385] 4614  e5823004 e5832000 e59f3014 e584300c e59f3010 e5843010 ebfdd6b4 e89da830
      [    4.224408] 4634  c0ad4eb0 00100100 00200200 e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000
      [    4.224431] 4654  e1a03001 e590214c e1a00003 e59f1004 eb014a32 e89da800 c00d4670 e1a0c00d
      [    4.224454] 4674  e92dd8f0 e24cb004 e24dd008 e52de004 e8bd4000 e59f5074 e3e03000 e50b3024
      [    4.224479]
                     LR: 0xc06ff880:
      [    4.224485] f880  e52de004 e8bd4000 f57ff05b e1d030b0 e2833001 e1c030b0 f57ff04f e320f004
      [    4.224508] f8a0  e3a00001 eb000a32 e1a0300d e3c33d7f e3c3303f e5933000 e3130002 089da800
      [    4.224531] f8c0  ebfffc6d e89da800 e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000 f57ff05b
      [    4.224554] f8e0  e1d030b0 e2833001 e1c030b0 f57ff04f e320f004 e121f001 e3a00001 eb000a1c
      [    4.224577] f900  e1a0300d e3c33d7f e3c3303f e5933000 e3130002 089da800 ebfffc57 e89da800
      [    4.224600] f920  e1a0c00d e92dd800 e24cb004 e52de004 e8bd4000 f57ff05b e1d030b0 e2833001
      [    4.224623] f940  e1c030b0 f57ff04f e320f004 f1080080 e3a00001 eb000a06 e1a0300d e3c33d7f
      [    4.224646] f960  e3c3303f e5933000 e3130002 089da800 ebfffc41 e89da800 e1a0c00d e92dd800
      [    4.224670]
                     SP: 0xe183bc00:
      [    4.224676] bc00  c003d4d0 c06ff4e0 e183bc2c c06ff900 e183bc2c e183bc20 c00d4614 40070013
      [    4.224699] bc20  ffffffff e183bc6c e183bc94 e183bc38 c0700098 c000a16c c0ad4eb0 60070013
      [    4.224722] bc40  00100100 00200200 bf03f364 c0ad4eb0 e2e9d600 00000000 bf03f564 00000001
      [    4.224744] bc60  e22a9664 e183bc94 e183bc20 e183bc80 c06ff900 c00d4614 40070013 ffffffff
      [    4.224767] bc80  bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000
      [    4.224790] bca0  e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8 bf0138a0 e183bcdc e183bcc8
      [    4.224813] bcc0  bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c e183bce0 bf01acc4 bf01aafc
      [    4.224836] bce0  00000001 bf03ff88 00000000 e2e9d600 00000000 bf03f564 00000001 e22a9664
      [    4.224859]
                     IP: 0xe183bba0:
      [    4.224865] bba0  00000000 c06ff958 e183bbc4 e1876b80 00000004 c0bec00c e183bc04 e183bbc8
      [    4.224888] bbc0  c003d04c c004dec8 e183bbfc 00000000 c00fcbb0 e1876b80 e23e75c0 e1876b80
      [    4.224910] bbe0  e183bc24 e183bc30 e1876bc0 e1876b90 00000005 c003d4d0 e183bc6c e183bc08
      [    4.224933] bc00  c003d4d0 c06ff4e0 e183bc2c c06ff900 e183bc2c e183bc20 c00d4614 40070013
      [    4.224956] bc20  ffffffff e183bc6c e183bc94 e183bc38 c0700098 c000a16c c0ad4eb0 60070013
      [    4.224979] bc40  00100100 00200200 bf03f364 c0ad4eb0 e2e9d600 00000000 bf03f564 00000001
      [    4.225001] bc60  e22a9664 e183bc94 e183bc20 e183bc80 c06ff900 c00d4614 40070013 ffffffff
      [    4.225024] bc80  bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000
      [    4.225048]
                     FP: 0xe183bc14:
      [    4.225054] bc14  e183bc20 c00d4614 40070013 ffffffff e183bc6c e183bc94 e183bc38 c0700098
      [    4.225077] bc34  c000a16c c0ad4eb0 60070013 00100100 00200200 bf03f364 c0ad4eb0 e2e9d600
      [    4.225100] bc54  00000000 bf03f564 00000001 e22a9664 e183bc94 e183bc20 e183bc80 c06ff900
      [    4.225122] bc74  c00d4614 40070013 ffffffff bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4
      [    4.225145] bc94  c00d45f0 bf040434 00000000 e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8
      [    4.225168] bcb4  bf0138a0 e183bcdc e183bcc8 bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c
      [    4.225191] bcd4  e183bce0 bf01acc4 bf01aafc 00000001 bf03ff88 00000000 e2e9d600 00000000
      [    4.225213] bcf4  bf03f564 00000001 e22a9664 e183bd2c e183bd10 bf01035c c0040e8c bf040468
      [    4.225237]
                     R0: 0xc0ad4e30:
      [    4.225243] 4e30  00000020 00000000 000001f4 0000000a 00000000 00000000 00000000 61666544
      [    4.225264] 4e50  00746c75 65646f4e 00000000 656e6f5a 00000000 00000001 00000000 c0ad4e6c
      [    4.225286] 4e70  c0ad4e6c 00000000 00000000 0000086f c0c1562c c0c1562c ffff8ca3 c0c15101
      [    4.225309] 4e90  c00ce330 00000000 ffffffff 00000014 0000000a 00000070 00000bb8 000001f4
      [    4.225331] 4eb0  ffffffff 003d003d c0ad4eb8 c0ad4eb8 e2c3ee64 e2030a64 0000003c c00d44f4
      [    4.225353] 4ed0  c00a708c c00a708c c00a708c c00d4444 c00a708c c00a708c c00a708c c00d4280
      [    4.225376] 4ef0  c00a708c c00a708c c00a708c c00d4208 c00a708c c00a708c c00a708c c00d4388
      [    4.225399] 4f10  c00a708c c00a708c c00a708c c00d41bc c00a708c c00a708c c00a708c c00d42f8
      [    4.225424]
                     R5: 0xc0ad4e30:
      [    4.225430] 4e30  00000020 00000000 000001f4 0000000a 00000000 00000000 00000000 61666544
      [    4.225452] 4e50  00746c75 65646f4e 00000000 656e6f5a 00000000 00000001 00000000 c0ad4e6c
      [    4.225473] 4e70  c0ad4e6c 00000000 00000000 0000086f c0c1562c c0c1562c ffff8ca3 c0c15101
      [    4.225496] 4e90  c00ce330 00000000 ffffffff 00000014 0000000a 00000070 00000bb8 000001f4
      [    4.225518] 4eb0  ffffffff 003d003d c0ad4eb8 c0ad4eb8 e2c3ee64 e2030a64 0000003c c00d44f4
      [    4.225541] 4ed0  c00a708c c00a708c c00a708c c00d4444 c00a708c c00a708c c00a708c c00d4280
      [    4.225564] 4ef0  c00a708c c00a708c c00a708c c00d4208 c00a708c c00a708c c00a708c c00d4388
      [    4.225587] 4f10  c00a708c c00a708c c00a708c c00d41bc c00a708c c00a708c c00a708c c00d42f8
      [    4.225611]
                     R6: 0xe2e9d580:
      [    4.225617] d580  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225638] d5a0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225658] d5c0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225679] d5e0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225700] d600  e2e9ec40 ffffffff 00000000 00000000 00000000 e2e97740 e2e9ec40 e2e9d41c
      [    4.225722] d620  e2e9d81c e2d0434c e2d04340 c0b9cfd8 e2da48c8 00000002 00000007 00000000
      [    4.225744] d640  00000000 00000000 00000000 e2e9d64c e2e9d64c e2f47a80 00000000 c0b9d290
      [    4.225766] d660  bf03f564 e20532c0 00000000 00000020 00050005 e2e9d474 e2e9d874 7fffffff
      [    4.225790]
                     R10: 0xe22a95e4:
      [    4.225796] 95e4  00000000 00000000 00000000 00000000 00000000 00000000 00000000 e22a95c0
      [    4.225817] 9604  e22a9604 e22a9604 bf03fe58 00000000 c0adf9c8 e219d3c8 00000001 00000003
      [    4.225839] 9624  00000000 00000000 00000000 00000000 00000000 00000000 00000000 e22a9600
      [    4.225861] 9644  00000001 e22a9d00 00000124 00000024 bf031518 c0078a5c 00000000 00000000
      [    4.225883] 9664  00000000 00000000 00000000 00000000 00000000 00000000 00000000 74636573
      [    4.225904] 9684  736e6f69 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225925] 96a4  00000000 00000000 00000000 00000000 00000000 00000000 00000000 7274732e
      [    4.225946] 96c4  00626174 00000000 00000000 00000000 00000000 00000000 00000000 00000000
      [    4.225970] Process insmod (pid: 1231, stack limit = 0xe183a238)
      [    4.225978] Stack: (0xe183bc80 to 0xe183c000)
      [    4.225990] bc80: bf03f34c 00000000 e183bcb4 e183bc98 bf0138b4 c00d45f0 bf040434 00000000
      [    4.226002] bca0: e2e9d600 00000000 e183bcc4 e183bcb8 bf0124d8 bf0138a0 e183bcdc e183bcc8
      [    4.226014] bcc0: bf01aba4 bf0124c4 ffffffff bf040434 e183bd2c e183bce0 bf01acc4 bf01aafc
      [    4.226025] bce0: 00000001 bf03ff88 00000000 e2e9d600 00000000 bf03f564 00000001 e22a9664
      [    4.226037] bd00: e183bd2c e183bd10 bf01035c c0040e8c bf040468 bf040468 e2e9d600 00000000
      [    4.226048] bd20: e183bd4c e183bd30 bf01c390 bf01abcc e2e9d610 c0c5e31c 00000000 00000001
      [    4.226060] bd40: e183bd5c e183bd50 c0311a48 bf01c2e8 e183bd84 e183bd60 c031061c c0311a30
      [    4.226072] bd60: e2e9d610 e2e9d644 bf03f564 c0b9d290 00000000 00000001 e183bda4 e183bd88
      [    4.226084] bd80: c031082c c0310564 00000000 bf03f564 c03107b4 c0b9d290 e183bdcc e183bda8
      [    4.226095] bda0: c030eb1c c03107c0 e2d1e3dc e2e97774 c06ff8a8 bf03f564 00000000 e2782ac0
      [    4.226107] bdc0: e183bddc e183bdd0 c03100e4 c030eaac e183be04 e183bde0 c030fc80 c03100c8
      [    4.226119] bde0: bf034a1b e183bdf0 bf03f564 bf01c540 c0bf3700 bf03fe58 e183be24 e183be08
      [    4.226132] be00: c0310e3c c030fb98 e183a000 bf01c540 c0bf3700 bf03fe58 e183be34 e183be28
      [    4.226144] be20: c031203c c0310d9c e183be4c e183be38 bf01c55c c0311ff4 e183a000 bf01c540
      [    4.226156] be40: e183be8c e183be50 c000a4d8 bf01c54c c00f4e2c e183bf48 00000001 bf03fe10
      [    4.226167] be60: bf03fe58 e22a9640 e183be8c e183bf48 00000001 bf03fe10 bf03fe58 e22a9640
      [    4.226179] be80: e183bf44 e183be90 c007b3ec c000a43c bf03fe1c 00007fff c00772ec c0be8c40
      [    4.226191] bea0: 000ad8e5 bf03ff74 eb765f84 e183beb8 c0709f2c c0078b88 e22a9648 00000000
      [    4.226203] bec0: bf03fe1c e183a000 c00f5218 c00f49bc ffffffff c007b9f8 c007b9f8 bf03153c
      [    4.226213] bee0: 0000000b bf031594 00000003 00000000 00000000 00000000 00000000 00000000
      [    4.226224] bf00: 00000000 00000000 00000000 00000000 00000000 00000000 ffffffff b6952008
      [    4.226236] bf20: 000ad8e5 00442fd4 00000080 c000fac8 e183a000 00000000 e183bfa4 e183bf48
      [    4.226248] bf40: c007ba74 c0079e44 eb323000 00442fd4 eb7655ac eb65dc38 eb66a4dc 00030958
      [    4.226258] bf60: 0003b498 00000000 00000000 00000000 0000003f 00000040 00000028 00000000
      [    4.226270] bf80: 00000016 00000000 c0013994 00000000 00000069 bee8ede4 00000000 e183bfa8
      [    4.226281] bfa0: c000f880 c007b9ac 00000000 00000069 b6952008 00442fd4 000ad8e5 00000000
      [    4.226292] bfc0: 00000000 00000069 bee8ede4 00000080 00000001 bee8edec b6f20000 0009b9aa
      [    4.226304] bfe0: b6e29901 bee8ea98 0002810f b6e29908 80080030 b6952008 000027ff 00002800
      [    4.226421] [<c00d4614>] (unregister_shrinker+0x30/0x5c) from [<bf0138b4>] (mali_mem_os_term+0x20/0xd0 [mali])
      [    4.226574] [<bf0138b4>] (mali_mem_os_term+0x20/0xd0 [mali]) from [<bf0124d8>] (mali_memory_terminate+0x20/0x34 [mali])
      [    4.226733] [<bf0124d8>] (mali_memory_terminate+0x20/0x34 [mali]) from [<bf01aba4>] (mali_terminate_subsystems+0xb4/0xd0 [mali])
      [    4.226904] [<bf01aba4>] (mali_terminate_subsystems+0xb4/0xd0 [mali]) from [<bf01acc4>] (mali_initialize_subsystems+0x104/0x518 [mali])
      [    4.227076] [<bf01acc4>] (mali_initialize_subsystems+0x104/0x518 [mali]) from [<bf01c390>] (mali_probe+0xb4/0x220 [mali])
      [    4.227174] [<bf01c390>] (mali_probe+0xb4/0x220 [mali]) from [<c0311a48>] (platform_drv_probe+0x24/0x28)
      [    4.227191] [<c0311a48>] (platform_drv_probe+0x24/0x28) from [<c031061c>] (driver_probe_device+0xc4/0x208)
      [    4.227205] [<c031061c>] (driver_probe_device+0xc4/0x208) from [<c031082c>] (__driver_attach+0x78/0x9c)
      [    4.227219] [<c031082c>] (__driver_attach+0x78/0x9c) from [<c030eb1c>] (bus_for_each_dev+0x7c/0xa0)
      [    4.227233] [<c030eb1c>] (bus_for_each_dev+0x7c/0xa0) from [<c03100e4>] (driver_attach+0x28/0x30)
      [    4.227247] [<c03100e4>] (driver_attach+0x28/0x30) from [<c030fc80>] (bus_add_driver+0xf4/0x228)
      [    4.227261] [<c030fc80>] (bus_add_driver+0xf4/0x228) from [<c0310e3c>] (driver_register+0xac/0x130)
      [    4.227276] [<c0310e3c>] (driver_register+0xac/0x130) from [<c031203c>] (platform_driver_register+0x54/0x68)
      [    4.227370] [<c031203c>] (platform_driver_register+0x54/0x68) from [<bf01c55c>] (init_module+0x1c/0x64 [mali])
      [    4.227466] [<bf01c55c>] (init_module+0x1c/0x64 [mali]) from [<c000a4d8>] (do_one_initcall+0xa8/0x144)
      [    4.227483] [<c000a4d8>] (do_one_initcall+0xa8/0x144) from [<c007b3ec>] (load_module+0x15b4/0x1b68)
      [    4.227498] [<c007b3ec>] (load_module+0x15b4/0x1b68) from [<c007ba74>] (SyS_init_module+0xd4/0xdc)
      [    4.227512] [<c007ba74>] (SyS_init_module+0xd4/0xdc) from [<c000f880>] (ret_fast_syscall+0x0/0x30)
      [    4.227524] Code: eb18a52c e5943010 e1a00005 e594200c (e5823004)
      [    4.227534] ---[ end trace c57267c46477aee1 ]---
      [    4.420068]
                     insmod_device_driver
      
      [    4.577148]  fbid=0 uiid=0
      [    4.577166] [DISP] sunxi_fb_to_display,line:590:sunxi_fb_to_display fb0 UIid 0
      [    4.577179] [DISP] sunxi_fb_to_display,line:653:sunxi_fb_to_display set fb0 UIid 0 chan[1]lid[0]z[3]
      
      发布在 飞凌嵌入式专区
      B
      bigfly
    • 按照文档的教程用SPI驱动LCD屏幕初始化失败

      按照文档的教程,https://r128.docs.aw-ol.com/demo/spilcd/
      进行到这一步应该是有正确的输出

      微信图片_20231017100039.png

      但是我这里没有看到SPI初始化的相关内容,以下是我输出的内容

      微信图片_20231017100027.png 微信图片_20231017100035.png

      发布在 A Series
      B
      bigfly
    • R128开发板上的这个元件是啥

      请问模块的这个部分是什么?在线文档里的图片没有标注出来,看上去有点像麦克风

      9F1AFC23-CEB7-409f-8E70-4FD89F1EFFA5.png

      发布在 A Series
      B
      bigfly
    • 【XR806开发板试用】系列之二:出现已经成功编译,但是无法生成镜像文件的问题

      本文主要对于编译成功但是烧录出现问题进行解决,用Hello world 和LED点亮代码作为示范

      文章仅为参考网络资料和自身理解,如有不正确之处请多指正

      1、首先确定自己根目录在哪,我们都在根目录进行hb set和hb build -f,判断方法是寻找ohos_config.json文件所在目录。

      2425078455-65143105a4f77.png

      点开可以看见其中的配置信息,记录的信息都能与自身环境对应上

      1593018543-6514314d51268.png

      2、值得一提的是,我在按照官方步骤操作发现虽然源码已经编译成功但是无法成功烧录到板子上,我刚刚开始找到的原因是product_path下的BUILD.gn文件,官方说明如下,但是我的该目录下的BUILD.gn文件是空的。原来以为是这个的原因导致烧录不成功,经过试错和询问大佬后一直没解决,后面解决后也没有更改这个 BUILD.gn.,所以官方文档可能是想说的从device_path中寻找的BUILD.gn,很是避坑^_^

      851362203-6514328568e9d.png

      3、以下简单说明一下如何将自己的代码添加到编译系统进行编译,详细内容仍旧参考官方文档.

      首先进入 $(root_path)/device/xradio/xr806/ohosdemo,(root_path含义见第一点中提到的oho_config.json),再找到同目录下的BUILD.gn,将其中的依赖(deps)添加或者取消注释,使其加入编译系统的编译过程

      1950750716-651435df48cde.png

      -配置的含义是在相同目录下找到一个名为_hello_world和LED 或者 iot_peripheral/wlan_demo的文件夹,在去到该文件夹中寻找BUILD.gn获取相关源代码和包含头文件的信息,BUILD.gn看不懂不要紧,能够明白流程就够了。

      2964444481-6514379f82c76.png

      完成以上步骤理论上在根目录使用hb set& hb build -f再使用烧录工具就可以完成烧录,但是总会出现一些意外情况

      开始我由于看见了一篇博客【XR806开发板试用】编译中的几个问题以及hello跑起来,让我了解到生成可烧录的镜像文件,如何查找后缀为.a的文件用来链接生成镜像文件:$(root_path)/device/xradio/xr806/xr_skylark 目录下的ohos.mk记录了查找到的文件,果然,当时并没有显示我已经生成的.a文件。博客中说可以手动添加,但是我手动添加会报错,大家可以尝试一下。

      2368549074-65143c093b61d.png

      接下来,我们就要更改生成ohos.mk的配置文件,配置文件是$(root_path)/device/xradio/xr806 下的 libcopy.py

      1436004550-65143e4e3a0cb.png

      更改完成后,用file libcopy.py查看文件换行符的格式

      若显示结果中有with CRLF line terminators,则用dos2unix

      libcopy.py转化成Unix下的换行符格式,如果需要保留源格式,可加上参数-n libcopy_back将原来格式存为备份

      更改完成后,可以尝试在跟目录下重新hb build -f编译,如果没有报错,并且在ohos.mk中发现了正确的链接文件地址,那么恭喜你可以开始编写任何你想要的代码了。但是如果出现了这样的报错(注意观察是从哪开始报错的,并且检查error.log)

      [OHOS ERROR] [253/254] ACTION //device/xradio/xr806:libSDK(//build/lite/toolchain:arm-none-eabi-gcc)
      [OHOS ERROR] FAILED: obj/device/xradio/xr806/libSDK_build_ext_components.txt
      

      解决方法论坛原文:

      $(root_path)/device/xradio/xr806/xr_skylark/project/demo/wlan_ble_demo/image/xr806中的image_auto_cal.cfg复制一份粘贴到$(root_path)/device/xradio/xr806/xr_skylark/project/demo/audio_demo/image/xr806 下面替换掉image.cfg。
      原因可以在$(root_path)/device/xradio/xr806/xr_skylark/project/image_cfg/readme.md 中找到
      

      改完之后就可以通过烧录软件烧录到板子上了^_^ 😂

      发布在 Wireless & Analog Series
      B
      bigfly
    • 【XR806开发板试用】单总线协议驱动DHT11温湿度传感器

      1.昨天刚收到极速社区寄来的全志XR806开发板,之前用过很多全志的SOC芯片,但是像这种无线芯片还是第一次用。这次打算使用XR806芯片驱动一下DHT11温湿度传感器。

      2.代码如下:

      #include "common/framework/platform_init.h"
      #include <stdio.h>
      #include "kernel/os/os.h"
      #include "driver/chip/hal_gpio.h"
      
      #define DHT11_Dout_LOW()      HAL_GPIO_WritePin(GPIO_PORT_A, GPIO_PIN_12,GPIO_PIN_LOW) 
      #define DHT11_Dout_HIGH()     HAL_GPIO_WritePin(GPIO_PORT_A, GPIO_PIN_12,GPIO_PIN_HIGH) 
      #define DHT11_Data_IN()          (uint8_t)HAL_GPIO_ReadPin(GPIO_PORT_A, GPIO_PIN_12)
      
      typedef struct
      {
          uint8_t  humi_high8bit;        //原始数据:湿度高8位
          uint8_t  humi_low8bit;         //原始数据:湿度低8位
          uint8_t  temp_high8bit;         //原始数据:温度高8位
          uint8_t  temp_low8bit;         //原始数据:温度高8位
          uint8_t  check_sum;             //校验和
        float    humidity;        //实际湿度
        float    temperature;     //实际温度  
      } DHT11_Data_TypeDef;
      typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
      
      
      void delay_us(uint16_t us)
      {
          uint16_t i;
          for(i=0;i<us;i++)
          {
              OS_MSleep(0.1);
          }
          
      }
      
      static void DHT11_Mode_IPU(void)
      {
          GPIO_InitParam param;
          param.driving = GPIO_DRIVING_LEVEL_1;
          param.mode = GPIOx_Pn_F0_INPUT;
          param.pull = GPIO_PULL_NONE;
          HAL_GPIO_Init(GPIO_PORT_A, GPIO_PIN_12, &param);
      
      }
      static void DHT11_Mode_Out_PP(void)
      {
          GPIO_InitParam param;
          param.driving = GPIO_DRIVING_LEVEL_1;
          param.mode = GPIOx_Pn_F1_OUTPUT;
          param.pull = GPIO_PULL_NONE;
          HAL_GPIO_Init(GPIO_PORT_A, GPIO_PIN_12, &param);
      
          
      }
      
      
      void DHT11_Init ( void )
      {
      
          DHT11_Mode_Out_PP();
          DHT11_Dout_HIGH();  // 拉高GPIO
      }
      static uint8_t DHT11_ReadByte ( void )
      {
          uint8_t i, temp=0;
          
          for(i=0;i<8;i++)    
          {     
              /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/  
              while(DHT11_Data_IN()==0);
      
              /*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
               *通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 
               */
              delay_us(33);//延时x us 这个延时需要大于数据0持续的时间即可             
          
              if(DHT11_Data_IN()==1)/* x us后仍为高电平表示数据“1” */
              {
                  /* 等待数据1的高电平结束 */
                  while(DHT11_Data_IN()==1);
      
                  temp|=(uint8_t)(0x01<<(7-i));  //把第7-i位置1,MSB先行 
              }
              else     // x us后为低电平表示数据“0”
              {               
                  temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
              }
          }
          return temp;
      }
      
      uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
      {  
        uint8_t temp;
        uint16_t humi_temp;
        
          /*输出模式*/
          DHT11_Mode_Out_PP();
          /*主机拉低*/
          DHT11_Dout_LOW();
          /*延时18ms*/
          OS_MSleep(20);
      
          /*总线拉高 主机延时30us*/
          DHT11_Dout_HIGH(); 
      
          delay_us(25);  //延时30us
      
          /*主机设为输入 判断从机响应信号*/ 
          DHT11_Mode_IPU();
          delay_us(25);   //延时30us
          /*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/   
          if(DHT11_Data_IN()==0)     
          {
          /*轮询直到从机发出 的80us 低电平 响应信号结束*/  
          while(DHT11_Data_IN()==0);
      
          /*轮询直到从机发出的 80us 高电平 标置信号结束*/
          while(DHT11_Data_IN()==1);
      
          /*开始接收数据*/   
          DHT11_Data->humi_high8bit= DHT11_ReadByte();
          DHT11_Data->humi_low8bit = DHT11_ReadByte();
          DHT11_Data->temp_high8bit= DHT11_ReadByte();
          DHT11_Data->temp_low8bit = DHT11_ReadByte();
          DHT11_Data->check_sum    = DHT11_ReadByte();
      
          /*读取结束,引脚改为输出模式*/
          DHT11_Mode_Out_PP();
          /*主机拉高*/
          DHT11_Dout_HIGH();
          
          /* 对数据进行处理 */
          humi_temp=DHT11_Data->humi_high8bit*100+DHT11_Data->humi_low8bit;
          DHT11_Data->humidity =(float)humi_temp/100;
          
          humi_temp=DHT11_Data->temp_high8bit*100+DHT11_Data->temp_low8bit;
          DHT11_Data->temperature=(float)humi_temp/100;    
          /*检查读取的数据是否正确*/
          temp = DHT11_Data->humi_high8bit + DHT11_Data->humi_low8bit + 
                 DHT11_Data->temp_high8bit+ DHT11_Data->temp_low8bit;
          if(DHT11_Data->check_sum==temp)
          { 
            return SUCCESS;
          }
          else 
            return ERROR;
          }    
          else
              return ERROR;
      }
      DHT11_Data_TypeDef DHT11_Data;
      uint8_t TempData;
      uint8_t humidness;
      
      int main(void)
      {
      
          platform_init();
          DHT11_Init();
          
          while (1) 
          {
              
              if(DHT11_Read_TempAndHumidity(&DHT11_Data)==SUCCESS)
              {
          
              }
              TempData=DHT11_Data.temperature;
              humidness=DHT11_Data.humidity;
              printf("Temp=%d\r\n",TempData);
              printf("humidness=%d\r\n",humidness);
              
              OS_MSleep(500);
      
      
          }
          return 0;
      }
      

      1.在SDK目录执行make build -j8编译结果如下

      4171574825-6512eea96a656.png

      2.由于我是用hello_demo改的所以编译路径显示在hello_demo里面
      3.输出的镜像在sdk out文件夹下面,然后使用phoenixMC工具烧录

      2780674078-6512efb09e398.png

      接线 :GND接DHT11模块GND,3.3V接模块的VCC,PA19接模块的信号引脚

      3062874764-6512f0abb383d.png

      打开串口调试工具连接好相应端口重启开发板

      3344616994-6512f0ef97e11.png

      开发板串口成功地输出了温度和湿度

      总结:一开始微妙延时函数使用了OS_MSleep函数输入小数点如:OS_MSleep(0.03);来使用,一直读不出数据,后来用逻辑分析仪测了这种延时方法并不准确,经过逻辑分析仪调试自己写出了delay_us延时函数,终于成功地从DHT11传感器读出了数据。

      发布在 Wireless & Analog Series
      B
      bigfly
    • 启动卡在这,就不会动了,然后也无法烧录了

      启动卡在这,就不会动了,然后也无法烧录了,有什么办法烧录程序?

      6748e5ac-14ef-427f-8bc1-16242e532917-image.png

      发布在 Wireless & Analog Series
      B
      bigfly
    • 100ask-t113pro lvds调试问题

      RGB屏是可以正常显示的,但是配置完lvds设备树内容,显示异常,用fbshow写图片无法显示
      设备树lvds配置如下:

      &lcd0 {
      lcd_used = <1>;
      
          lcd_driver_name     = "default_lcd";
          lcd_backlight       = <50>;
          lcd_if              = <3>;
      
          lcd_x               = <800>;
          lcd_y               = <600>;
          lcd_width           = <108>;
          lcd_height          = <94>;
          lcd_dclk_freq       = <39>;
      
          lcd_pwm_used        = <1>;
          lcd_pwm_ch          = <7>;
          lcd_pwm_freq        = <50000>;
          lcd_pwm_pol         = <0>;
      	
      	lcd_hbp             = <88>;
          lcd_ht              = <1024>;
          lcd_hspw            = <64>;
          lcd_vbp             = <15>;
          lcd_vt              = <625>;
          lcd_vspw            = <6>;
      
          lcd_lvds_if         = <0>;
          lcd_lvds_colordepth = <0>;
          lcd_lvds_mode       = <1>;
      
          lcd_frm = <0>;
          lcd_io_phase = <0x0000>;
          lcd_gamma_en        = <0>;
          lcd_bright_curve_en = <0>;
          lcd_cmap_en         = <0>;
      	
      deu_mode            = <0>;
          lcdgamma4iep        = <22>;
          smart_color         = <90>;
      
          pinctrl-0 = <&lvds0_pins_a>;
          pinctrl-1 = <&lvds0_pins_b>;
      };
      

      请问哪里配置不对吗

      发布在 其它全志芯片讨论区
      B
      bigfly
    • UART1~UART5驱动配置

      TL113-MiniEVM的UART1~UART5的驱动是不是需要自己写?使用QT开发检测出来只有ttyAS0这个串口。

      QQ图片20230906103426.jpg

      QQ图片20230906103439.jpg

      发布在 创龙科技专区
      B
      bigfly
    • 百问网V853开发板 setusbconfig hid创建hid设备失败

      V853开发板,在做usb gadget开发,这板子USB有点毛病,要开下面两条命令后才能用ADB

      cat /sys/devices/platform/soc/usbc0/usb_host
      cat /sys/devices/platform/soc/usbc0/usb_device
      

      而且开第一条命令的时候会不停报错

      96025751a3e962b1442614d93414ddad78d13879.png

      做mass_storage时也是需要先setusbconfig mass_storage,在重复上面的命令才能用,不过这个问题先放一边。

      我把全志D1的setusbconfig脚本替代了我板子上原本的脚本,ADB,mass_storage还是能使用,参考d1-tina-linux-usb-开发指南,开启了内核的HID function

      ec09ee780112d46bdbe008737b0cb930b8b865dc.png

      编译,打包,烧入,开机,先关ADB

      killall adbd 2>/dev/null
      setusbconfig none
      cat /sys/devices/platform/soc/usbc0/usb_null
      

      然后setusbconfig hid,报错

      0f18919732c891198b222aff0d03e934a9086a28.png

      我用命令对/sys/kernel/config/usb_gadget/g1手动配置也是这样的结果

      实在没办法了,网上也找不到相关解决办法,求大神解答!

      发布在 V Series
      B
      bigfly
    • d1s和t113在供电有啥区别?

      请教老铁,d1s和t113在供电有啥区别?我记得vcc-dram有点区别

      这款板子可以直接替换吗?

      微信图片_20230823135302.png

      发布在 MR Series
      B
      bigfly
    • 芒果派T113编译的时候为什么一直让我配置内核的一些选项?

      配置编译的环境来编译驱动,我设置了交叉编译链,还有ARCH参数,以及内核路径,但是我执行make的时候会一直让我配置内核的一些选项,这个是编译时的输出

      QQ图片20230731101348.jpg

      这个是我的makefile

      QQ图片20230731101351.jpg

      发布在 其它全志芯片讨论区
      B
      bigfly
    • linux下编译完成后打包安全固件失败

      linux下编译完成后执行:./build.sh pack_secure

      报错

      ERROR: dragon toc0 run error
      
      发布在 V Series
      B
      bigfly
    • A133_tina编译出错,哪位大神有用过?

      QQ图片20230718094626.jpg

      发布在 其它全志芯片讨论区
      B
      bigfly
    • 回复: V853编译失败,sudo apt-get install u-boot-tools清华源报错

      百度可以ping通

      发布在 V Series
      B
      bigfly
    • V853编译失败,sudo apt-get install u-boot-tools清华源报错

      DD1FDF0A-1247-4504-880B-A23579CB1CF1.png

      发布在 V Series
      B
      bigfly
    • V853那个NPU的demo测试例子中量化图片能量化多张?

      20230616102014.png

      参照教程里的这个地方,batch-size 设置成2就量化不了了

      只用一张图量化的结果不太正常

      QQ图片20230616102426.png

      发布在 V Series
      B
      bigfly
    • 回复: V853编译的vpm_run sample.txt出现segmentation fault怎么办呢?

      @lingzhi12321 明白了,谢谢大佬

      发布在 V Series
      B
      bigfly
    • Melis4.0测试cedar多媒体解码库,视频和lvgl混合显示

      1.测试audio_test命令播放mp3

      首先要把cedar模块编译进内核:在 melis 的根目录执行 make menuconfig 命令,选中 cedar 模块。

      Modules Setup
      	-->cedar module support
      

      9590f04e98624fe8a954fb1096b4c0d6.png

      测试命令也包含进来:

      Kernel Setup 
      	--> Drivers Test Sample
      		--> cedar Test
      

      1eca982f2a9d4243930a0147bff1214e.png

      编译,烧录,运行,输入help命令可以看到下面的命令:

      msh />help
      ......
      cedar_close      - cedar_close
      cedar_test       - cedar_test
      audio_close_test - audio_close_test
      audio_test       - audio_play_test
      ......
      

      1.1 finish命令中文件路径的写法(测试)

      audio_test命令的格式为:

      audio_test [文件名]
      

      我的sd卡目录下有个 mp3 文件夹,在finish中进入文件夹后的路径为:

      cd /mnt/F/mp3
      msh /mnt/F/mp3>ls
      1906.真的爱你-Beyond.mp3 1912.千千阙歌-陈慧娴.mp3 1916.红日-李克勤.mp3 1917.都是你的错-陈慧琳.mp3 1917.都是你的错65k.mp3
      distance.mp3
      

      这时,我要播放distance.mp3,我使用了下面4种路径:

      audio_test /mnt/F/mp3/distance.mp3           ------- 播放失败
      audio_test \\mnt\\F\\mp3\\distance.mp3		 ------- 播放失败
      audio_test F:\\mp3\\distance.mp3             ======= 播放成功
      audio_test F:/mp3/distance.mp3               ------- 播放失败
      

      只有一种路径是正确的:

      audio_test F:\\mp3\\distance.mp3
      

      测试播放纯音频文件不用考虑图层,比较简单。

      2.测试cedar_test命令播放mp4

      先禁止melis桌面加载,在《startup.sh》注释掉相关内容:

      packecho "Execute startup script begin.............."
      #insmod d:\mod\orange.mod
      #insmod d:\apps\desktop.mod
      echo "...............Execute startup script end"
      

      此时开机只显示全志logo。查询一下此时的图层信息:

      msh />disp
      screen 0:
      # allwinner logo使用 ch[0] lyr[0]图层,alpha_mode = 0 (pixel alpha),alpha = 255,zorder 为 0 
         BUF    enable ch[0] lyr[0] z[0] prem[N] a[pixel 255] fmt[  0] fb[ 640, 480; 640, 480; 640, 480] crop[   0,   0, 640, 480] frame[  80,   0, 640, 480] addr[0x4132b000,0x00000000,0x00000000] flags[0x       0] trd[0,0]
      

      alpha = 255属于全覆盖,不和其他图层混合显示。zorder=0表示最底层,其他图层只要大于0就会覆盖它。当然,覆盖是在图层都是alpha=255的情况下。

      2.1 不清除logo图层,无法显示视频

      在这种情况下,使用cedar_test播放视频,只有声音,没有图像。

      msh />cedar_test  F:\\hanfu02.mp4
      

      这种情况下,查看一下图层信息(可以看到2个图层都属于ch[0],图层格式一个是RGB,一个是YUV):

      msh />disp
      screen 0:
         BUF    enable ch[0] lyr[0] z[0] prem[N] a[pixel 255] fmt[  0] fb[ 640, 480; 640, 480; 640, 480] crop[   0,   0, 640, 480] frame[  80,   0, 640, 480] addr[0x4132b000,0x00000000,0x00000000] flags[0x       0] trd[0,0]
         BUF    enable ch[0] lyr[1] z[1] prem[N] a[pixel   0] fmt[ 72] fb[1280, 720; 640, 360; 640, 360] crop[   0,   0,1280, 720] frame[   0,  15, 800, 450] addr[0x42b2d000,0x00000000,0x4273a000] flags[0x       0] trd[0,0]
      

      be26c22eb1224acf8a17cb7814f06470.png
      这里是不是说同一通道的4图层,只能使用相同的格式?

      2.2 使用disp_layer_alpha_test命令清除logo图层,正常播放视频的disp_layer_alpha_test命令再修改一下:

      int disp_layer_alpha_test(int argc, char **argv)
      {
      	......
      	if (argc == 2) {		//	如果带有一个参数,不用理会参数是什么,清除所有图层		
      		disp_layer_clear_all(0);
      		return 0;
      	}else if(argc == 4){	//	带3个参数,分别是:   [1]=mode    [2]=alpha    [3]=zorder 
      		mode = atoi(argv[1]);
      		alpha = atoi(argv[2]);
      		i = atoi(argv[3]);
      		show_ui_layer(&test_cfg, 1, mode, alpha,(unsigned char)i);
      		return 0;
      	} else
      		g_screen_index = 0;
      	......
      }
      

      输入下面的命令,注意:只带一个参数。

      msh />disp_layer_alpha_test 0
      

      查询图层信息(可以看到没有图层信息):

      msh />disp
      screen 0:
      de_rate 300000000 hz, ref_fps:      59
      mgr0: 800x480 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_sync[0] unblank direct_show[false]
      dmabuf: cache[0] cache max[0] umap skip[0] overflow[0]
              lcd output      backlight(192)  fps:58.4         800x 480
              err:77961       skip:16 irq:124292      vsync:0 vsync_skip:0
      

      现在才可以正常播放视频。播放完毕后,查询图层信息:

      msh />disp
      screen 0:
      #	vi图层ch[0] lyr[1]是,alpha_mode = 0 (pixel alpha),alpha = 0,format = 72,zorder 为 1
         BUF    enable ch[0] lyr[1] z[1] prem[N] a[pixel   0] fmt[ 72] fb[1280, 720; 640, 360; 640, 360] crop[   0,   0,1280, 720] frame[   0,  15, 800, 450] addr[0x42b2d000,0x00000000,0x4273a000] flags[0x       0] trd[0,0]
      

      3. lvgl设置

      3.1 ui图层配置

      lvgl属于ui图层,所以使用ch[1] lyr[0] ,alpha_mode = 2 (global pixel alpha),alpha = 255,format = 0(ARGB),zorder 为 2(zorder可以改变,其他参数固定)。仿照 show_ui_layer() 写一个show_lvgl_layer() 的函数:

      int request_lvgl_layer(unsigned char  zorder)
      {
      	static int isMemInited=0;	//
      	struct test_layer_cfg test_cfg;
      	struct test_layer_cfg *cfg = &test_cfg;
      	memset(&test_cfg, 0, sizeof(struct test_layer_cfg));
      
      	printf("request mem_id 0,800, 480,\n");
      	//	第一次初始化,清除所有图层,申请内存;后面就不用了,只是改变zorder
      	if(isMemInited == 0){
      		disp_layer_clear_all(g_screen_index);
      		disp_mem(0, 800, 480, 0, "r");
      		memset(g_p_mem_base,0,800*480*4);
      	}
      	isMemInited = 1;
      	cfg->mem_id = 0;
      	cfg->screen_id = 0;
      	cfg->layer_cfg.channel = 1;
      	cfg->layer_id = 0;
      	cfg->layer_cfg.layer_id = 0;
      
      	cfg->layer_cfg.info.fb.format = 0;
      	cfg->layer_cfg.info.fb.size[0].width = 800;
      	cfg->layer_cfg.info.fb.size[0].height = 480;
      	cfg->layer_cfg.info.fb.crop.x = 0;
      	cfg->layer_cfg.info.fb.crop.y = 0;
      	cfg->layer_cfg.info.fb.crop.width = 800;
      	cfg->layer_cfg.info.fb.crop.height = 480;
      	cfg->layer_cfg.info.fb.align[0] = 4;
      	cfg->layer_cfg.info.mode = 0;
      	cfg->layer_cfg.info.alpha_mode = 2;
      	cfg->layer_cfg.info.alpha_value = 255;
      	cfg->layer_cfg.info.zorder = zorder;
      	cfg->layer_cfg.info.screen_win.x = 0;
      	cfg->layer_cfg.info.screen_win.y = 0;
      
      	return disp_layer_cfg(cfg);
      }
      

      3.2 lvgl本身配置

      参考文章《LVGL视频播放界面实现方法》。

      需要在lv_conf.h中设置参数:

      #define LV_COLOR_SCREEN_TRANSP 1
      

      然后设置界面背景色的透明度,LV_OPA_0 为透明,LV_OPA_COVER为覆盖,根据需要配置:

      /* init screen style */
          static lv_style_t style_scr_act;
              lv_style_init(&style_scr_act);
              /* set style to  LV_OPA_0 为透明,LV_OPA_COVER为覆盖*/
              lv_style_set_bg_opa(&style_scr_act, LV_OPA_0);
              lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
      

      测试界面源码:

      void lv_example_btn_1(void)
      {
          // 创建一个组,稍后将需要使用键盘或编码器或按钮控制的部件(对象)添加进去,并且将输入设备和组关联
          // 如果将这个组设置为默认组,那么对于那些在创建时会添加到默认组的部件(对象)就可以省略 lv_group_add_obj()
          lv_group_t * g = lv_group_create();
      
          // 将上面创建的组设置为默认组
          // 如果稍后创建的部件(对象),使用默认组那必须要在其创建之前设置好默认组,否则不生效
          lv_group_set_default(g);
      
          // 将输入设备和组关联(使用前先打开上面注释掉的头文件)
          lv_indev_set_group(g_keypad_device_object, g);     // 键盘
          //lv_indev_set_group(lv_win32_encoder_device_object, g);      // 鼠标上的滚轮(编码器)
      
          /* init screen style */
          static lv_style_t style_scr_act;
              lv_style_init(&style_scr_act);
              /* set style to  LV_OPA_0,no cover*/
              lv_style_set_bg_opa(&style_scr_act, LV_OPA_0);
              lv_obj_add_style(lv_scr_act(), &style_scr_act, 0);
      #define     RIGHT_OFFSET    40
          /* 创建一个btn部件(对象) */
          lv_obj_t * btn1 = lv_btn_create(lv_scr_act());       // 创建一个btn部件(对象),他的父对象是活动屏幕对象
          lv_obj_set_size(btn1, 100, 50);
          lv_obj_align(btn1, LV_ALIGN_LEFT_MID, 140, 165);
      
          lv_obj_t * btn2 = lv_btn_create(lv_scr_act());       // 创建一个btn部件(对象),他的父对象是活动屏幕对象
          lv_obj_set_size(btn2, 100, 50);
          lv_obj_align_to(btn2, btn1, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0);
      
          lv_obj_t * btn3 = lv_btn_create(lv_scr_act());       // 创建一个btn部件(对象),他的父对象是活动屏幕对象
          lv_obj_set_size(btn3, 100, 50);
          lv_obj_align_to(btn3, btn2, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0);
      
          lv_obj_t * btn4 = lv_btn_create(lv_scr_act());       // 创建一个btn部件(对象),他的父对象是活动屏幕对象
          lv_obj_set_size(btn4, 100, 50);
          lv_obj_align_to(btn4, btn3, LV_ALIGN_OUT_RIGHT_MID, RIGHT_OFFSET, 0);
      
          lv_obj_t * slider = lv_slider_create(lv_scr_act());
          lv_obj_align(slider,  LV_ALIGN_BOTTOM_MID, 0, -20);   
      }
      

      3.3 播放视频效果

      播放视频效果(按键切换):
      fd4d14bc5cc249dc9f0a38ad271c5859.gif

      原文链接:https://blog.csdn.net/hwd00001/article/details/130145030

      发布在 MR Series
      B
      bigfly
    • V853编译的vpm_run sample.txt出现segmentation fault怎么办呢?

      想问一下V853编译的vpm_run sample.txt出现segmentation fault如何怎么办呢?

      QQ图片20230529113612.jpg

      发布在 V Series
      B
      bigfly
    • mango-MQ-R在移植好的lvgl添加物理按键

      续上篇:mango-MQ-R基于Melis移植lvgl

      没有搞定D1s在Melis下的I2c驱动(gt911触摸屏)。先测试物理按键。

      1.lvgl注册keypad驱动

      ##1.1 在melis的ADC按键中发送消息
      先做好ADC按键的驱动,直接在驱动中发送消息。

      如何在rt-thread中使用消息队列发送消息,请参考官方资料: RT-Thread API参考手册-消息队列

      1.1.1 创建消息队列,并初始化

      相关代码在 D1s-Melis/ekernel/drivers/drv/source/input/keyboard/sunxi_keyboard.c 中。完整内容点击链接 sunxi_keyboard.c。

      /* 消息队列控制块 */
       struct rt_messagequeue mq;
      /* 消息队列中用到的放置消息的内存池 */
      static rt_uint8_t msg_pool[2048];
      int sunxi_keyboard_init(void)
      {
      ......
          rt_err_t result;
          /* 初始化消息队列 */
          result = rt_mq_init(&mq,
                              "mqt",
                              &msg_pool[0],               /* 内存池指向msg_pool */
                              1,                          /* 每个消息的大小是 1 字节 */
                              sizeof(msg_pool),           /* 内存池的大小是msg_pool的大小 */
                              RT_IPC_FLAG_FIFO);          /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
          if (result != RT_EOK)
          {
              rt_kprintf("init message queue failed.\n");
              return -1;
          }
          return 0;
      }
      

      1.1.2 扫描按键时,发送按下和松开消息

      这部分代码也在 sunxi_keyboard.c 中。

      int keyboard_irq_callback(uint32_t data_type, uint32_t data)
      {
          if (data_type == GPADC_UP && key_flag == 1)
          {
      ......
                                  /* 发送按键松开消息到消息队列中 */
                                  key_data->compare_later = 0xf6;
                                  result = rt_mq_send(&mq, &(key_data->compare_later), 1);
                                  if (result != RT_EOK)
                                  {
                                      rt_kprintf("rt_mq_send ERR\n");
                                  }
          }
          .......
                                  __log("key: %d",key_data->compare_before);
                                  /* 发送按键按下消息到消息队列中 */
                                  result = rt_mq_send(&mq, &(key_data->compare_before), 1);
                                  if (result != RT_EOK)
                                  {
                                      rt_kprintf("rt_mq_send ERR\n");
                                  } 
          return 0;
      }
      

      1.2 编写读取按键的回调函数

      这里只是通过消息队列读取按键按下和松开的消息。

      收到按键按下的消息值为0,1,2,3,4;
      收到按键松开的消息值为0xF6.

      extern   struct rt_messagequeue mq;
      uint8_t   msgbyte;
      static void melis_keypad_driver_read_cb(lv_indev_drv_t* indev_drv,    lv_indev_data_t* data)
      {
          /* 从消息队列中接收消息 */
          if (rt_mq_recv(&mq, (void *)&msgbyte, sizeof(msgbyte), RT_WAITING_NO) == RT_EOK)
          {
              rt_kprintf("read_cb: recv msg:%d\n", msgbyte);
              data->state = LV_INDEV_STATE_PR;
              switch (msgbyte)
              {
              case 0:
                  data->key = LV_KEY_PREV;            break;
              case 1:
                  data->key = LV_KEY_NEXT;            break;
              case 2:
                  data->key = LV_KEY_ENTER;            break;
              case 3:
                  data->key = LV_KEY_ENTER;            break;
              case 4:
                  data->key = LV_KEY_ESC;            break;
              case 0xf6:
                data->state = LV_INDEV_STATE_REL;	break;
              default:
                  break;
              }
          }
      }
      

      1.3 lvgl按键驱动注册

      完成前面的准备工作后,就可以在 lv_main()中注册按键驱动,完成lvgl物理按键的初始化。

      直接拷贝韦东山老师在windows下键盘的驱动,00_lv_100ask_sim_codeblocks_win/lv_drivers/win32drv/win32drv.c 完整代码点击链接:

      static lv_indev_drv_t keypad_driver;
          lv_indev_drv_init(&keypad_driver);
          keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
          keypad_driver.read_cb = lv_win32_keypad_driver_read_callback;
          lv_win32_keypad_device_object = lv_indev_drv_register(&keypad_driver);
      

      把上面的代码稍作改动。

      lv_win32_keypad_driver_read_callback --> melis_keypad_driver_read_cb
      lv_win32_keypad_device_object --> g_keypad_device_object 【 说明:这个变量其他文件需要用到】
      

      于是,改动后的代码如下(完整代码点击链接 lv_main.c):

      #define   LV_USE_GPADC    1
      lv_indev_t* g_keypad_device_object ;
      static lv_disp_t * hal_init(void  )
      {
      ......
      #if   LV_USE_GPADC    
          static lv_indev_drv_t keypad_driver;
          lv_indev_drv_init(&keypad_driver);
          keypad_driver.type = LV_INDEV_TYPE_KEYPAD;
          keypad_driver.read_cb = melis_keypad_driver_read_cb;
          g_keypad_device_object = lv_indev_drv_register(&keypad_driver);
      #endif
      	lv_disp_t * disp = NULL;
        return disp;
      }
      

      2.在gui中测试物理按键效果

      在gui中应用物理按键(groups)需要3个步骤:

      1.要创建一个 组(Groups) : lv_group_t * g = lv_group_create();
      2.然后将一个对象添加到 组(Groups) 中: lv_group_add_obj(g, obj); 也可以指定默认组:lv_group_set_default(g);
      3.最后要将组(Groups)与输入设备相关联: lv_indev_set_group(g_keypad_device_object , g);

      物理按键中有3个必备的按键消息,这3个消息就可以实现焦点切换和触发焦点对象:

      消息名称 含义
      LV_KEY_NEXT 聚焦到下一个对象
      LV_KEY_PREV 聚焦到上一个对象
      LV_KEY_ENTER 触发 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件

      其他消息:

      消息名称 含义
      LV_KEY_UP 增加值或向上移动
      LV_KEY_DOWN 减少值或向下移动
      LV_KEY_RIGHT 增加值或向右移动
      LV_KEY_LEFT 减少值或向左移动
      LV_KEY_ESC 关闭或退出(例如关闭 下拉列表)
      LV_KEY_DEL 删除(例如 文本区域 中右侧的字符)
      LV_KEY_BACKSPACE 删除左边的一个字符(例如在文本区域)
      LV_KEY_HOME 跳到开头/顶部(例如在 文本区域)
      LV_KEY_END 跳到最后(例如在 文本区域))

      这里我使用了官方例程 lv_example_btn_1.c。

      extern lv_indev_t* g_keypad_device_object ;
      static void event_handler(lv_event_t * e)
      {
          lv_event_code_t code = lv_event_get_code(e);
      
          if(code == LV_EVENT_CLICKED) {
              LV_LOG_USER("Clicked");
          }
          else if(code == LV_EVENT_VALUE_CHANGED) {
              LV_LOG_USER("Toggled");
          }
      }
      
      void lv_example_btn_1(void)
      {
          lv_obj_t * label;
      
          // 创建一个组,稍后将需要使用键盘或编码器或按钮控制的部件(对象)添加进去,并且将输入设备和组关联
          // 如果将这个组设置为默认组,那么对于那些在创建时会添加到默认组的部件(对象)就可以省略 lv_group_add_obj()
          lv_group_t * g = lv_group_create();
      
          // 将上面创建的组设置为默认组
          // 如果稍后创建的部件(对象),使用默认组那必须要在其创建之前设置好默认组,否则不生效
          lv_group_set_default(g);
      
          lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
          lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
          lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);
      
          label = lv_label_create(btn1);
          lv_label_set_text(label, "Button");
          lv_obj_center(label);
      
          lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
          lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);
          lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
          lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
          lv_obj_set_height(btn2, LV_SIZE_CONTENT);
      
          label = lv_label_create(btn2);
          lv_label_set_text(label, "Toggle");
          lv_obj_center(label);
      
          lv_indev_set_group(g_keypad_device_object, g);
      }
      

      原文链接:https://blog.csdn.net/hwd00001/article/details/130106367

      发布在 MR Series
      B
      bigfly
    • mango-MQ-R基于Melis移植lvgl

      1.下载lvgl源码到《D1s-Melis/ekernel/drivers/hal/test/disp2》目录
      我使用的源码是https://github.com/lvgl/lv_port_pc_eclipse,克隆到 D1s-Melis/ekernel/drivers/hal/test/disp2 目录。然后在 D1s-Melis/ekernel/drivers/hal/test/disp2/lv_port_pc_eclipse》目录下建立一个Makefile,把全部的C文件都包含进来编译的。这是因为lvgl的所有非必要的C文件都可以通过宏定义配置是否编译。例如lv_bmp.c里面的代码是否编译,取决于 宏定义

      LV_USE_BMP:
      215a6283b1c54e7dba2ac8c5047e3020.png

      为了简单起见,很多非必要的组件我都没有包含进来,详情见 lv_conf.h 。

      /**
       * @file lv_conf.h
       * Configuration file for v9.0.0-dev
       */
      
      /*
       * Copy this file as `lv_conf.h`
       * 1. simply next to the `lvgl` folder
       * 2. or any other places and
       *    - define `LV_CONF_INCLUDE_SIMPLE`
       *    - add the path as include path
       */
      
      /* clang-format off */
      #if 1 /*Set it to "1" to enable content*/
      
      #ifndef LV_CONF_H
      #define LV_CONF_H
      
      #define LV_USE_DEV_VERSION
      
      /*====================
         COLOR SETTINGS
       *====================*/
      
      /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 24 (RGB888), 32 (ARGB8888)*/
      #define LV_COLOR_DEPTH 32
      
      #define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00)
      /*Enable more complex drawing routines to manage screens transparency.
       *Can be used if the UI is above another layer, e.g. an OSD menu or video player.
       *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
      #define LV_COLOR_SCREEN_TRANSP 1
      /*=========================
         STDLIB WRAPPER SETTINGS
       *=========================*/
      
      /*Enable and configure the built-in memory manager*/
      #define LV_USE_BUILTIN_MALLOC 1
      #if LV_USE_BUILTIN_MALLOC
          /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/
          #define LV_MEM_SIZE (128U * 1024U)          /*[bytes]*/
      
          /*Size of the memory expand for `lv_malloc()` in bytes*/
          #define LV_MEM_POOL_EXPAND_SIZE 0
      
          /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
          #define LV_MEM_ADR 0     /*0: unused*/
          /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
          #if LV_MEM_ADR == 0
              #undef LV_MEM_POOL_INCLUDE
              #undef LV_MEM_POOL_ALLOC
          #endif
      #endif  /*LV_USE_BUILTIN_MALLOC*/
      
      /*Enable lv_memcpy_builtin, lv_memset_builtin, lv_strlen_builtin, lv_strncpy_builtin*/
      #define LV_USE_BUILTIN_MEMCPY 1
      
      /*Enable and configure the built-in (v)snprintf */
      #define LV_USE_BUILTIN_SNPRINTF 1
      #if LV_USE_BUILTIN_SNPRINTF
          #define LV_SPRINTF_USE_FLOAT 0
      #endif  /*LV_USE_BUILTIN_SNPRINTF*/
      
      #define LV_STDLIB_INCLUDE <stdint.h>
      #define LV_STDIO_INCLUDE  <stdint.h>
      #define LV_STRING_INCLUDE <stdint.h>
      #define LV_MALLOC       lv_malloc_builtin
      #define LV_REALLOC      lv_realloc_builtin
      #define LV_FREE         lv_free_builtin
      #define LV_MEMSET       lv_memset_builtin
      #define LV_MEMCPY       lv_memcpy_builtin
      #define LV_SNPRINTF     lv_snprintf_builtin
      #define LV_VSNPRINTF    lv_vsnprintf_builtin
      #define LV_STRLEN       lv_strlen_builtin
      #define LV_STRNCPY      lv_strncpy_builtin
      
      #define LV_COLOR_EXTERN_INCLUDE <stdint.h>
      #define LV_COLOR_MIX      lv_color_mix
      #define LV_COLOR_PREMULT      lv_color_premult
      #define LV_COLOR_MIX_PREMULT      lv_color_mix_premult
      
      /*====================
         HAL SETTINGS
       *====================*/
      
      /*Default display refresh, input device read and animation step period.*/
      #define LV_DEF_REFR_PERIOD  33      /*[ms]*/
      
      /*Use a custom tick source that tells the elapsed time in milliseconds.
       *It removes the need to manually update the tick with `lv_tick_inc()`)*/
      #define LV_TICK_CUSTOM 0
      #if LV_TICK_CUSTOM
          #define LV_TICK_CUSTOM_INCLUDE "Arduino.h"         /*Header for the system time function*/
          #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis())    /*Expression evaluating to current system time in ms*/
          /*If using lvgl as ESP32 component*/
          // #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h"
          // #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL))
      #endif   /*LV_TICK_CUSTOM*/
      
      /*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
       *(Not so important, you can adjust it to modify default sizes and spaces)*/
      #define LV_DPI_DEF 130     /*[px/inch]*/
      
      /*========================
       * DRAW CONFIGURATION
       *========================*/
      
      /*Enable the built in mask engine.
       *Required to draw shadow, rounded corners, circles, arc, skew lines, or any other masks*/
      #define LV_USE_DRAW_MASKS 1
      
      #define LV_USE_DRAW_SW  1
      #if LV_USE_DRAW_SW
      
          /*Enable complex draw engine.
           *Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
          #define LV_DRAW_SW_COMPLEX 1
      
          /* If a widget has `style_opa < 255` (not `bg_opa`, `text_opa` etc) or not NORMAL blend mode
           * it is buffered into a "simple" layer before rendering. The widget can be buffered in smaller chunks.
           * "Transformed layers" (if `transform_angle/zoom` are set) use larger buffers
           * and can't be drawn in chunks. */
      
          /*The target buffer size for simple layer chunks.*/
          #define LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE          (24 * 1024)   /*[bytes]*/
      
          /*Used if `LV_DRAW_SW_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated.*/
          #define LV_DRAW_SW_LAYER_SIMPLE_FALLBACK_BUF_SIZE (3 * 1024)    /*[bytes]*/
      
          /*Allow buffering some shadow calculation.
          *LV_DRAW_SW_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
          *Caching has LV_DRAW_SW_SHADOW_CACHE_SIZE^2 RAM cost*/
          #define LV_DRAW_SW_SHADOW_CACHE_SIZE 0
      
          /* Set number of maximally cached circle data.
          * The circumference of 1/4 circle are saved for anti-aliasing
          * radius * 4 bytes are used per circle (the most often used radiuses are saved)
          * 0: to disable caching */
          #define LV_DRAW_SW_CIRCLE_CACHE_SIZE 4
      
          /*Default gradient buffer size.
           *When LVGL calculates the gradient "maps" it can save them into a cache to avoid calculating them again.
           *LV_DRAW_SW_GRADIENT_CACHE_DEF_SIZE sets the size of this cache in bytes.
           *If the cache is too small the map will be allocated only while it's required for the drawing.
           *0 mean no caching.*/
          #define LV_DRAW_SW_GRADIENT_CACHE_DEF_SIZE 0
      
          /*Allow dithering the gradients (to achieve visual smooth color gradients on limited color depth display)
           *LV_DRAW_SW_GRADIENT_DITHER implies allocating one or two more lines of the object's rendering surface
           *The increase in memory consumption is (32 bits * object width) plus 24 bits * object width if using error diffusion */
          #define LV_DRAW_SW_GRADIENT_DITHER 0
          #if LV_DRAW_SW_GRADIENT_DITHER
              /*Add support for error diffusion dithering.
               *Error diffusion dithering gets a much better visual result, but implies more CPU consumption and memory when drawing.
               *The increase in memory consumption is (24 bits * object's width)*/
              #define LV_DRAW_SW_GRADIENT_DITHER_ERROR_DIFFUSION 0
          #endif
      
          /*Enable subpixel rendering*/
          #define LV_DRAW_SW_FONT_SUBPX 0
          #if LV_DRAW_SW_FONT_SUBPX
              /*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
              #define LV_DRAW_SW_FONT_SUBPX_BGR 0  /*0: RGB; 1:BGR order*/
          #endif
      #endif
      
      /*Use SDL renderer API*/
      #define LV_USE_DRAW_SDL 0
      #if LV_USE_DRAW_SDL
          #define LV_DRAW_SDL_INCLUDE_PATH <SDL2/SDL.h>
          /*Texture cache size, 8MB by default*/
          #define LV_DRAW_SDL_LRU_SIZE (1024 * 1024 * 8)
          /*Custom blend mode for mask drawing, disable if you need to link with older SDL2 lib*/
          #define LV_DRAW_SDL_CUSTOM_BLEND_MODE (SDL_VERSION_ATLEAST(2, 0, 6))
      #endif
      
      /*=====================
       * GPU CONFIGURATION
       *=====================*/
      
      /*Use Arm's 2D acceleration library Arm-2D */
      #define LV_USE_GPU_ARM2D 0
      
      /*Use STM32's DMA2D (aka Chrom Art) GPU*/
      #define LV_USE_GPU_STM32_DMA2D 0
      #if LV_USE_GPU_STM32_DMA2D
          /*Must be defined to include path of CMSIS header of target processor
          e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
          #define LV_GPU_DMA2D_CMSIS_INCLUDE
      #endif
      
      /*Use GD32 IPA GPU
       * This adds support for Image Processing Accelerator on GD32F450 and GD32F470 series MCUs
       *
       * NOTE: IPA on GD32F450 has a bug where the fill operation overwrites data beyond the
       * framebuffer. This driver works around it by saving and restoring affected memory, but
       * this makes it not thread-safe. GD32F470 is not affected. */
      #define LV_USE_GPU_GD32_IPA 0
      
      /*Use NXP's PXP GPU iMX RTxxx platforms*/
      #define LV_USE_GPU_NXP_PXP 0
      #if LV_USE_GPU_NXP_PXP
          /*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
          *   and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS
          *   has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
          *0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
          */
          #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
      #endif
      
      /*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
      #define LV_USE_GPU_NXP_VG_LITE 0
      
      /*Use SWM341's DMA2D GPU*/
      #define LV_USE_GPU_SWM341_DMA2D 0
      #if LV_USE_GPU_SWM341_DMA2D
          #define LV_GPU_SWM341_DMA2D_INCLUDE "SWM341.h"
      #endif
      
      /*=======================
       * FEATURE CONFIGURATION
       *=======================*/
      
      /*-------------
       * Logging
       *-----------*/
      
      /*Enable the log module*/
      #define LV_USE_LOG 0
      #if LV_USE_LOG
      
          /*How important log should be added:
          *LV_LOG_LEVEL_TRACE       A lot of logs to give detailed information
          *LV_LOG_LEVEL_INFO        Log important events
          *LV_LOG_LEVEL_WARN        Log if something unwanted happened but didn't cause a problem
          *LV_LOG_LEVEL_ERROR       Only critical issue, when the system may fail
          *LV_LOG_LEVEL_USER        Only logs added by the user
          *LV_LOG_LEVEL_NONE        Do not log anything*/
          #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
      
          /*1: Print the log with 'printf';
          *0: User need to register a callback with `lv_log_register_print_cb()`*/
          #define LV_LOG_PRINTF 0
      
          /*1: Enable print timestamp;
           *0: Disable print timestamp*/
          #define LV_LOG_USE_TIMESTAMP 1
      
          /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
          #define LV_LOG_TRACE_MEM        1
          #define LV_LOG_TRACE_TIMER      1
          #define LV_LOG_TRACE_INDEV      1
          #define LV_LOG_TRACE_DISP_REFR  1
          #define LV_LOG_TRACE_EVENT      1
          #define LV_LOG_TRACE_OBJ_CREATE 1
          #define LV_LOG_TRACE_LAYOUT     1
          #define LV_LOG_TRACE_ANIM       1
          #define LV_LOG_TRACE_MSG        1
      
      #endif  /*LV_USE_LOG*/
      
      /*-------------
       * Asserts
       *-----------*/
      
      /*Enable asserts if an operation is failed or an invalid data is found.
       *If LV_USE_LOG is enabled an error message will be printed on failure*/
      #define LV_USE_ASSERT_NULL          1   /*Check if the parameter is NULL. (Very fast, recommended)*/
      #define LV_USE_ASSERT_MALLOC        1   /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
      #define LV_USE_ASSERT_STYLE         0   /*Check if the styles are properly initialized. (Very fast, recommended)*/
      #define LV_USE_ASSERT_MEM_INTEGRITY 0   /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
      #define LV_USE_ASSERT_OBJ           0   /*Check the object's type and existence (e.g. not deleted). (Slow)*/
      
      /*Add a custom handler when assert happens e.g. to restart the MCU*/
      #define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
      #define LV_ASSERT_HANDLER while(1);   /*Halt by default*/
      
      /*-------------
       * Others
       *-----------*/
      
      /*1: Show CPU usage and FPS count*/
      #define LV_USE_PERF_MONITOR 0
      #if LV_USE_PERF_MONITOR
          #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
      #endif
      
      /*1: Show the used memory and the memory fragmentation
       * Requires `LV_USE_BUILTIN_MALLOC = 1`*/
      #define LV_USE_MEM_MONITOR 0
      #if LV_USE_MEM_MONITOR
          #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
      #endif
      
      /*1: Draw random colored rectangles over the redrawn areas*/
      #define LV_USE_REFR_DEBUG 0
      
      /*Maximum buffer size to allocate for rotation.
       *Only used if software rotation is enabled in the display driver.*/
      #define LV_DISP_ROT_MAX_BUF (10*1024)
      
      #define LV_USE_USER_DATA 1
      
      /*Garbage Collector settings
       *Used if lvgl is bound to higher level language and the memory is managed by that language*/
      #define LV_ENABLE_GC 0
      #if LV_ENABLE_GC != 0
          #define LV_GC_INCLUDE "gc.h"                           /*Include Garbage Collector related things*/
      #endif /*LV_ENABLE_GC*/
      
      /*Default image cache size. Image caching keeps some images opened.
       *If only the built-in image formats are used there is no real advantage of caching.
       *With other image decoders (e.g. PNG or JPG) caching save the continuous open/decode of images.
       *However the opened images consume additional RAM.
       *0: to disable caching*/
      #define LV_IMG_CACHE_DEF_SIZE 0
      
      
      /*Number of stops allowed per gradient. Increase this to allow more stops.
       *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/
      #define LV_GRADIENT_MAX_STOPS 2
      
      /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
       * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
      #define LV_COLOR_MIX_ROUND_OFS 0
      
      /*=====================
       *  COMPILER SETTINGS
       *====================*/
      
      /*For big endian systems set to 1*/
      #define LV_BIG_ENDIAN_SYSTEM 0
      
      /*Define a custom attribute to `lv_tick_inc` function*/
      #define LV_ATTRIBUTE_TICK_INC
      
      /*Define a custom attribute to `lv_timer_handler` function*/
      #define LV_ATTRIBUTE_TIMER_HANDLER
      
      /*Define a custom attribute to `lv_disp_flush_ready` function*/
      #define LV_ATTRIBUTE_FLUSH_READY
      
      /*Required alignment size for buffers*/
      #define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
      
      /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
       * E.g. __attribute__((aligned(4)))*/
      #define LV_ATTRIBUTE_MEM_ALIGN
      
      /*Attribute to mark large constant arrays for example font's bitmaps*/
      #define LV_ATTRIBUTE_LARGE_CONST
      
      /*Compiler prefix for a big array declaration in RAM*/
      #define LV_ATTRIBUTE_LARGE_RAM_ARRAY
      
      /*Place performance critical functions into a faster memory (e.g RAM)*/
      #define LV_ATTRIBUTE_FAST_MEM
      
      
      /*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
       *should also appear on LVGL binding API such as Micropython.*/
      #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
      
      /*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
      #define LV_USE_LARGE_COORD 0
      
      /*==================
       *   FONT USAGE
       *===================*/
      
      /*Montserrat fonts with ASCII range and some symbols using bpp = 4
       *https://fonts.google.com/specimen/Montserrat*/
      #define LV_FONT_MONTSERRAT_8  1
      #define LV_FONT_MONTSERRAT_10 1
      #define LV_FONT_MONTSERRAT_12 1
      #define LV_FONT_MONTSERRAT_14 1
      #define LV_FONT_MONTSERRAT_16 1
      #define LV_FONT_MONTSERRAT_18 1
      #define LV_FONT_MONTSERRAT_20 1
      #define LV_FONT_MONTSERRAT_22 1
      #define LV_FONT_MONTSERRAT_24 1
      #define LV_FONT_MONTSERRAT_26 1
      #define LV_FONT_MONTSERRAT_28 1
      #define LV_FONT_MONTSERRAT_30 1
      #define LV_FONT_MONTSERRAT_32 1
      #define LV_FONT_MONTSERRAT_34 1
      #define LV_FONT_MONTSERRAT_36 1
      #define LV_FONT_MONTSERRAT_38 1
      #define LV_FONT_MONTSERRAT_40 1
      #define LV_FONT_MONTSERRAT_42 1
      #define LV_FONT_MONTSERRAT_44 1
      #define LV_FONT_MONTSERRAT_46 1
      #define LV_FONT_MONTSERRAT_48 1
      
      /*Demonstrate special features*/
      #define LV_FONT_MONTSERRAT_12_SUBPX      1
      #define LV_FONT_MONTSERRAT_28_COMPRESSED 1  /*bpp = 3*/
      #define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 1  /*Hebrew, Arabic, Persian letters and all their forms*/
      #define LV_FONT_SIMSUN_16_CJK            1  /*1000 most common CJK radicals*/
      
      /*Pixel perfect monospace fonts*/
      #define LV_FONT_UNSCII_8  1
      #define LV_FONT_UNSCII_16 1
      
      /*Optionally declare custom fonts here.
       *You can use these fonts as default font too and they will be available globally.
       *E.g. #define LV_FONT_CUSTOM_DECLARE   LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
      #define LV_FONT_CUSTOM_DECLARE
      
      /*Always set a default font*/
      #define LV_FONT_DEFAULT &lv_font_montserrat_14
      
      /*Enable handling large font and/or fonts with a lot of characters.
       *The limit depends on the font size, font face and bpp.
       *Compiler error will be triggered if a font needs it.*/
      #define LV_FONT_FMT_TXT_LARGE 1
      
      /*Enables/disables support for compressed fonts.*/
      #define LV_USE_FONT_COMPRESSED 1
      
      /*Enable drawing placeholders when glyph dsc is not found*/
      #define LV_USE_FONT_PLACEHOLDER 1
      
      /*=================
       *  TEXT SETTINGS
       *=================*/
      
      /**
       * Select a character encoding for strings.
       * Your IDE or editor should have the same character encoding
       * - LV_TXT_ENC_UTF8
       * - LV_TXT_ENC_ASCII
       */
      #define LV_TXT_ENC LV_TXT_ENC_UTF8
      
      /*Can break (wrap) texts on these chars*/
      #define LV_TXT_BREAK_CHARS " ,.;:-_)]}"
      
      /*If a word is at least this long, will break wherever "prettiest"
       *To disable, set to a value <= 0*/
      #define LV_TXT_LINE_BREAK_LONG_LEN 0
      
      /*Minimum number of characters in a long word to put on a line before a break.
       *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
      #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
      
      /*Minimum number of characters in a long word to put on a line after a break.
       *Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
      #define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
      
      /*The control character to use for signalling text recoloring.*/
      #define LV_TXT_COLOR_CMD "#"
      
      /*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
       *The direction will be processed according to the Unicode Bidirectional Algorithm:
       *https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
      #define LV_USE_BIDI 1
      #if LV_USE_BIDI
          /*Set the default direction. Supported values:
          *`LV_BASE_DIR_LTR` Left-to-Right
          *`LV_BASE_DIR_RTL` Right-to-Left
          *`LV_BASE_DIR_AUTO` detect texts base direction*/
          #define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
      #endif
      
      /*Enable Arabic/Persian processing
       *In these languages characters should be replaced with an other form based on their position in the text*/
      #define LV_USE_ARABIC_PERSIAN_CHARS 1
      
      /*==================
       * WIDGETS
       *================*/
      
      /*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
      
      #define LV_USE_ANIMIMG    1
      
      #define LV_USE_ARC        1
      
      #define LV_USE_BAR        1
      
      #define LV_USE_BTN        1
      
      #define LV_USE_BTNMATRIX  1
      
      #define LV_USE_CALENDAR   1
      #if LV_USE_CALENDAR
          #define LV_CALENDAR_WEEK_STARTS_MONDAY 0
          #if LV_CALENDAR_WEEK_STARTS_MONDAY
              #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
          #else
              #define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
          #endif
      
          #define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March",  "April", "May",  "June", "July", "August", "September", "October", "November", "December"}
          #define LV_USE_CALENDAR_HEADER_ARROW 1
          #define LV_USE_CALENDAR_HEADER_DROPDOWN 1
      #endif  /*LV_USE_CALENDAR*/
      
      #define LV_USE_CANVAS     1
      
      #define LV_USE_CHART      1
      
      #define LV_USE_CHECKBOX   1
      
      #define LV_USE_COLORWHEEL 1
      
      #define LV_USE_DROPDOWN   1   /*Requires: lv_label*/
      
      #define LV_USE_IMG        1   /*Requires: lv_label*/
      
      #define LV_USE_IMGBTN     1
      
      #define LV_USE_KEYBOARD   1
      
      #define LV_USE_LABEL      1
      #if LV_USE_LABEL
          #define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
          #define LV_LABEL_LONG_TXT_HINT 1  /*Store some extra info in labels to speed up drawing of very long texts*/
      #endif
      
      #define LV_USE_LED        1
      
      #define LV_USE_LINE       1
      
      #define LV_USE_LIST       1
      
      #define LV_USE_MENU       1
      
      #define LV_USE_METER      1
      
      #define LV_USE_MSGBOX     1
      
      #define LV_USE_ROLLER     1   /*Requires: lv_label*/
      
      #define LV_USE_SLIDER     1   /*Requires: lv_bar*/
      
      #define LV_USE_SPAN       1
      #if LV_USE_SPAN
          /*A line text can contain maximum num of span descriptor */
          #define LV_SPAN_SNIPPET_STACK_SIZE 64
      #endif
      
      #define LV_USE_SPINBOX    1
      
      #define LV_USE_SPINNER    1
      
      #define LV_USE_SWITCH     1
      
      #define LV_USE_TEXTAREA   1   /*Requires: lv_label*/
      #if LV_USE_TEXTAREA != 0
          #define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500    /*ms*/
      #endif
      
      #define LV_USE_TABLE      1
      
      #define LV_USE_TABVIEW    1
      
      #define LV_USE_TILEVIEW   1
      
      #define LV_USE_WIN        1
      
      /*==================
       * THEMES
       *==================*/
      
      /*A simple, impressive and very complete theme*/
      #define LV_USE_THEME_DEFAULT 1
      #if LV_USE_THEME_DEFAULT
      
          /*0: Light mode; 1: Dark mode*/
          #define LV_THEME_DEFAULT_DARK 0
      
          /*1: Enable grow on press*/
          #define LV_THEME_DEFAULT_GROW 1
      
          /*Default transition time in [ms]*/
          #define LV_THEME_DEFAULT_TRANSITION_TIME 80
      #endif /*LV_USE_THEME_DEFAULT*/
      
      /*A very simple theme that is a good starting point for a custom theme*/
      #define LV_USE_THEME_BASIC 1
      
      /*A theme designed for monochrome displays*/
      #define LV_USE_THEME_MONO 1
      
      /*==================
       * LAYOUTS
       *==================*/
      
      /*A layout similar to Flexbox in CSS.*/
      #define LV_USE_FLEX 1
      
      /*A layout similar to Grid in CSS.*/
      #define LV_USE_GRID 1
      
      /*====================
       * 3RD PARTS LIBRARIES
       *====================*/
      
      /*File system interfaces for common APIs */
      
      /*API for fopen, fread, etc*/
      #define LV_USE_FS_STDIO 0
      #if LV_USE_FS_STDIO
          #define LV_FS_STDIO_LETTER '\0'     /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
          #define LV_FS_STDIO_PATH ""         /*Set the working directory. File/directory paths will be appended to it.*/
          #define LV_FS_STDIO_CACHE_SIZE 0    /*>0 to cache this number of bytes in lv_fs_read()*/
      #endif
      
      /*API for open, read, etc*/
      #define LV_USE_FS_POSIX 0
      #if LV_USE_FS_POSIX
          #define LV_FS_POSIX_LETTER '\0'     /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
          #define LV_FS_POSIX_PATH ""         /*Set the working directory. File/directory paths will be appended to it.*/
          #define LV_FS_POSIX_CACHE_SIZE 0    /*>0 to cache this number of bytes in lv_fs_read()*/
      #endif
      
      /*API for CreateFile, ReadFile, etc*/
      #define LV_USE_FS_WIN32 0
      #if LV_USE_FS_WIN32
          #define LV_FS_WIN32_LETTER '\0'     /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
          #define LV_FS_WIN32_PATH ""         /*Set the working directory. File/directory paths will be appended to it.*/
          #define LV_FS_WIN32_CACHE_SIZE 0    /*>0 to cache this number of bytes in lv_fs_read()*/
      #endif
      
      /*API for FATFS (needs to be added separately). Uses f_open, f_read, etc*/
      #define LV_USE_FS_FATFS 0
      #if LV_USE_FS_FATFS
          #define LV_FS_FATFS_LETTER '\0'     /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
          #define LV_FS_FATFS_CACHE_SIZE 0    /*>0 to cache this number of bytes in lv_fs_read()*/
      #endif
      
      /*PNG decoder library*/
      #define LV_USE_PNG 1
      
      /*BMP decoder library*/
      #define LV_USE_BMP 1
      
      /* JPG + split JPG decoder library.
       * Split JPG is a custom format optimized for embedded systems. */
      #define LV_USE_SJPG 0
      
      /*GIF decoder library*/
      #define LV_USE_GIF 0
      
      /*QR code library*/
      #define LV_USE_QRCODE 0
      
      /*Barcode code library*/
      #define LV_USE_BARCODE 0
      
      /*FreeType library*/
      #define LV_USE_FREETYPE 0
      #if LV_USE_FREETYPE
          /*Memory used by FreeType to cache characters [bytes]*/
          #define LV_FREETYPE_CACHE_SIZE (64 * 1024)
      
          /*Let FreeType to use LVGL memory and file porting*/
          #define LV_FREETYPE_USE_LVGL_PORT 0
      
          /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
          /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
          /* if font size >= 256, must be configured as image cache */
          #define LV_FREETYPE_SBIT_CACHE 0
      
          /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
          /* (0:use system defaults) */
          #define LV_FREETYPE_CACHE_FT_FACES 4
          #define LV_FREETYPE_CACHE_FT_SIZES 4
      #endif
      
      /* Built-in TTF decoder */
      #define LV_USE_TINY_TTF 1
      #if LV_USE_TINY_TTF
          /* Enable loading TTF data from files */
          #define LV_TINY_TTF_FILE_SUPPORT 0
      #endif
      
      /*Rlottie library*/
      #define LV_USE_RLOTTIE 0
      
      /*FFmpeg library for image decoding and playing videos
       *Supports all major image formats so do not enable other image decoder with it*/
      #define LV_USE_FFMPEG 0
      #if LV_USE_FFMPEG
          /*Dump input information to stderr*/
          #define LV_FFMPEG_DUMP_FORMAT 0
      #endif
      
      /*==================
       * OTHERS
       *==================*/
      
      /*1: Enable API to take snapshot for object*/
      #define LV_USE_SNAPSHOT 1
      
      /*1: Enable Monkey test*/
      #define LV_USE_MONKEY   1
      
      /*1: Enable grid navigation*/
      #define LV_USE_GRIDNAV  1
      
      /*1: Enable lv_obj fragment*/
      #define LV_USE_FRAGMENT 1
      
      /*1: Support using images as font in label or span widgets */
      #define LV_USE_IMGFONT  1
      #if LV_USE_IMGFONT
          /*Imgfont image file path maximum length*/
          #define LV_IMGFONT_PATH_MAX_LEN 64
      
          /*1: Use img cache to buffer header information*/
          #define LV_IMGFONT_USE_IMG_CACHE_HEADER 0
      #endif
      
      /*1: Enable a published subscriber based messaging system */
      #define LV_USE_MSG  1
      
      /*1: Enable Pinyin input method*/
      /*Requires: lv_keyboard*/
      #define LV_USE_IME_PINYIN 0
      #if LV_USE_IME_PINYIN
          /*1: Use default thesaurus*/
          /*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
          #define LV_IME_PINYIN_USE_DEFAULT_DICT 1
          /*Set the maximum number of candidate panels that can be displayed*/
          /*This needs to be adjusted according to the size of the screen*/
          #define LV_IME_PINYIN_CAND_TEXT_NUM 6
      
          /*Use 9 key input(k9)*/
          #define LV_IME_PINYIN_USE_K9_MODE      1
          #if LV_IME_PINYIN_USE_K9_MODE == 1
              #define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
          #endif // LV_IME_PINYIN_USE_K9_MODE
      #endif
      
      /*1: Enable file explorer*/
      /*Requires: lv_table*/
      #define LV_USE_FILE_EXPLORER                     0
      #if LV_USE_FILE_EXPLORER
          /*Maximum length of path*/
          #define LV_FILE_EXPLORER_PATH_MAX_LEN        (128)
          /*Quick access bar, 1:use, 0:not use*/
          /*Requires: lv_list*/
          #define LV_FILE_EXPLORER_QUICK_ACCESS        1
      #endif
      
      /*==================
       * DEVICES
       *==================*/
      
      /*Use SDL to open window on PC and handle mouse and keyboard*/
      #define LV_USE_SDL              0
      #if LV_USE_SDL
          #define LV_SDL_INCLUDE_PATH    <SDL2/SDL.h>
          #define LV_SDL_PARTIAL_MODE    0    /*Recommended only to emulate a setup with a display controller*/
      #endif
      
      /*Driver for /dev/fb*/
      #define LV_USE_LINUX_FBDEV      0
      #if LV_USE_LINUX_FBDEV
          #define LV_LINUX_FBDEV_BSD  0
      #endif
      
      /*Interface for TFT_eSPI*/
      #define LV_USE_TFT_ESPI         0
      
      /*==================
      * EXAMPLES
      *==================*/
      
      /*Enable the examples to be built with the library*/
      #define LV_BUILD_EXAMPLES 1
      
      /*===================
       * DEMO USAGE
       ====================*/
      
      /*Show some widget. It might be required to increase `LV_MEM_SIZE` */
      #define LV_USE_DEMO_WIDGETS 1
      #if LV_USE_DEMO_WIDGETS
          #define LV_DEMO_WIDGETS_SLIDESHOW 0
      #endif
      
      /*Demonstrate the usage of encoder and keyboard*/
      #define LV_USE_DEMO_KEYPAD_AND_ENCODER 1
      
      /*Benchmark your system*/
      #define LV_USE_DEMO_BENCHMARK 0
      #if LV_USE_DEMO_BENCHMARK
          /*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
          #define LV_DEMO_BENCHMARK_RGB565A8 0
      #endif
      
      /*Stress test for LVGL*/
      #define LV_USE_DEMO_STRESS 0
      
      /*Music player demo*/
      #define LV_USE_DEMO_MUSIC 0
      #if LV_USE_DEMO_MUSIC
          #define LV_DEMO_MUSIC_SQUARE    0
          #define LV_DEMO_MUSIC_LANDSCAPE 0
          #define LV_DEMO_MUSIC_ROUND     0
          #define LV_DEMO_MUSIC_LARGE     0
          #define LV_DEMO_MUSIC_AUTO_PLAY 0
      #endif
      
      /*Flex layout demo*/
      #define LV_USE_DEMO_FLEX_LAYOUT 0
      
      /*--END OF LV_CONF_H--*/
      
      #endif /*LV_CONF_H*/
      
      #endif /*End of "Content enable"*/
      

      1.1 修改Makefile

      先在disp2目录下的Makefile把子目录disp2/lv_port_pc_eclipse包含进来:

      subdir-ccflags-y +=	-I$(srctree)/ekernel/drivers/include \
      			-I$(srctree)/ekernel/core/rt-thread/include \
      			-I$(srctree)/ekernel/drivers/drv/source/disp2/soc
      obj-y +=  disp_layer_cfg.o disp_mem_hwd.o
      #disp_mem.o
      obj-y += disp_layer_alpha_test.o
      obj-y += disp_layer_scal_test.o
      obj-y += disp_layer_format_test.o
      obj-y += disp_lbc_test.o
      obj-y += lv_port_pc_eclipse/
      

      再将isp2/lv_port_pc_eclipse目录下的Makefile改为下面内容(节选):

      
      
      obj-y += \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_alpha16.o \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_argb.o \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_chroma_keyed.o \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.o \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb.o \
          lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb565a8.o \
          lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_12_compr_az.c.o \
          lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_16_compr_az.c.o \
          lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_28_compr_az.c.o \
          lvgl/demos/benchmark/lv_demo_benchmark.o \
          lvgl/demos/keypad_encoder/lv_demo_keypad_encoder.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_corner_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_list_pause.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_list_pause_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_list_play.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_list_play_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_loop.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_loop_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_next.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_next_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_pause.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_pause_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_play.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_play_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_prev.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_prev_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_rnd.o \
          lvgl/demos/music/assets/img_lv_demo_music_btn_rnd_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_corner_left.o \
          lvgl/demos/music/assets/img_lv_demo_music_corner_left_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_corner_right.o \
          lvgl/demos/music/assets/img_lv_demo_music_corner_right_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_1.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_1_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_2.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_2_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_3.o \
          lvgl/demos/music/assets/img_lv_demo_music_cover_3_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_1.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_1_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_2.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_2_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_3.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_3_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_4.o \
          lvgl/demos/music/assets/img_lv_demo_music_icon_4_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_list_border.o \
          lvgl/demos/music/assets/img_lv_demo_music_list_border_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_logo.o \
          lvgl/demos/music/assets/img_lv_demo_music_slider_knob.o \
          lvgl/demos/music/assets/img_lv_demo_music_slider_knob_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_wave_bottom.o \
          lvgl/demos/music/assets/img_lv_demo_music_wave_bottom_large.o \
          lvgl/demos/music/assets/img_lv_demo_music_wave_top.o \
          lvgl/demos/music/assets/img_lv_demo_music_wave_top_large.o \
          lvgl/demos/music/lv_demo_music.o \
          lvgl/demos/music/lv_demo_music_list.o \
          lvgl/demos/music/lv_demo_music_main.o \
          lvgl/demos/stress/lv_demo_stress.o \
          lvgl/demos/widgets/assets/img_clothes.o \
          lvgl/demos/widgets/assets/img_demo_widgets_avatar.o \
          lvgl/demos/widgets/assets/img_lvgl_logo.o \
          lvgl/demos/widgets/lv_demo_widgets.o \
          lvgl/examples/anim/lv_example_anim_1.o \
          lvgl/examples/anim/lv_example_anim_2.o \
          lvgl/examples/anim/lv_example_anim_3.o \
          lvgl/examples/anim/lv_example_anim_timeline_1.o \
          lvgl/examples/assets/animimg001.o \
          lvgl/examples/assets/animimg002.o \
          lvgl/examples/assets/animimg003.o \
          lvgl/examples/assets/emoji/img_emoji_F617.o \
          lvgl/examples/assets/img_caret_down.o \
          lvgl/examples/assets/img_cogwheel_alpha16.o \
          lvgl/examples/assets/img_cogwheel_argb.o \
          lvgl/examples/assets/img_cogwheel_chroma_keyed.o \
          lvgl/examples/assets/img_cogwheel_indexed16.o \
          lvgl/examples/assets/img_cogwheel_rgb.o \
          lvgl/examples/assets/img_hand.o \
          lvgl/examples/assets/img_skew_strip.o \
          lvgl/examples/assets/img_star.o \
          lvgl/examples/assets/imgbtn_left.o \
          lvgl/examples/assets/imgbtn_mid.o \
          lvgl/examples/assets/imgbtn_right.o \
          lvgl/examples/event/lv_example_event_1.o \
          lvgl/examples/event/lv_example_event_2.o \
          lvgl/examples/event/lv_example_event_3.o \
          lvgl/examples/event/lv_example_event_4.o \
          lvgl/examples/get_started/lv_example_get_started_1.o \
          lvgl/examples/get_started/lv_example_get_started_2.o \
          lvgl/examples/get_started/lv_example_get_started_3.o \
          lvgl/examples/layouts/flex/lv_example_flex_1.o \
          lvgl/examples/layouts/flex/lv_example_flex_2.o \
          lvgl/examples/layouts/flex/lv_example_flex_3.o \
          lvgl/examples/layouts/flex/lv_example_flex_4.o \
          lvgl/examples/layouts/flex/lv_example_flex_5.o \
          lvgl/examples/layouts/flex/lv_example_flex_6.o \
          lvgl/examples/layouts/grid/lv_example_grid_1.o \
          lvgl/examples/layouts/grid/lv_example_grid_2.o \
          lvgl/examples/layouts/grid/lv_example_grid_3.o \
          lvgl/examples/layouts/grid/lv_example_grid_4.o \
          lvgl/examples/layouts/grid/lv_example_grid_5.o \
          lvgl/examples/layouts/grid/lv_example_grid_6.o \
          lvgl/examples/libs/bmp/lv_example_bmp_1.o \
          lvgl/examples/libs/ffmpeg/lv_example_ffmpeg_1.o \
          lvgl/examples/libs/ffmpeg/lv_example_ffmpeg_2.o \
          lvgl/examples/libs/freetype/lv_example_freetype_1.o \
          lvgl/examples/libs/gif/img_bulb_gif.o \
          lvgl/examples/libs/gif/lv_example_gif_1.o \
          lvgl/examples/libs/png/img_wink_png.o \
          lvgl/examples/libs/png/lv_example_png_1.o \
          lvgl/examples/libs/qrcode/lv_example_qrcode_1.o \
          lvgl/examples/libs/rlottie/lv_example_rlottie_1.o \
          lvgl/examples/libs/rlottie/lv_example_rlottie_2.o \
          lvgl/examples/libs/rlottie/lv_example_rlottie_approve.o \
          lvgl/examples/libs/sjpg/lv_example_sjpg_1.o \
          lvgl/examples/others/fragment/lv_example_fragment_1.o \
          lvgl/examples/others/fragment/lv_example_fragment_2.o \
          lvgl/examples/others/gridnav/lv_example_gridnav_1.o \
          lvgl/examples/others/gridnav/lv_example_gridnav_2.o \
          lvgl/examples/others/gridnav/lv_example_gridnav_3.o \
          lvgl/examples/others/gridnav/lv_example_gridnav_4.o \
          lvgl/examples/others/ime/lv_example_ime_pinyin_1.o \
          lvgl/examples/others/ime/lv_example_ime_pinyin_2.o \
          lvgl/examples/others/imgfont/lv_example_imgfont_1.o \
          lvgl/examples/others/monkey/lv_example_monkey_1.o \
          lvgl/examples/others/monkey/lv_example_monkey_2.o \
          lvgl/examples/others/monkey/lv_example_monkey_3.o \
          lvgl/examples/others/msg/lv_example_msg_1.o \
          lvgl/examples/others/msg/lv_example_msg_2.o \
          lvgl/examples/others/msg/lv_example_msg_3.o \
          lvgl/examples/others/snapshot/lv_example_snapshot_1.o \
          lvgl/examples/porting/lv_port_disp_template.o \
          lvgl/examples/porting/lv_port_fs_template.o \
          lvgl/examples/porting/lv_port_indev_template.o \
          lvgl/examples/scroll/lv_example_scroll_1.o \
          lvgl/examples/scroll/lv_example_scroll_2.o \
          lvgl/examples/scroll/lv_example_scroll_3.o \
          lvgl/examples/scroll/lv_example_scroll_4.o \
          lvgl/examples/scroll/lv_example_scroll_5.o \
          lvgl/examples/scroll/lv_example_scroll_6.o \
          lvgl/examples/styles/lv_example_style_1.o \
          lvgl/examples/styles/lv_example_style_10.o \
          lvgl/examples/styles/lv_example_style_11.o \
          lvgl/examples/styles/lv_example_style_12.o \
          lvgl/examples/styles/lv_example_style_13.o \
          lvgl/examples/styles/lv_example_style_14.o \
          lvgl/examples/styles/lv_example_style_15.o \
          lvgl/examples/styles/lv_example_style_2.o \
          lvgl/examples/styles/lv_example_style_3.o \
          lvgl/examples/styles/lv_example_style_4.o \
          lvgl/examples/styles/lv_example_style_5.o \
          lvgl/examples/styles/lv_example_style_6.o \
          lvgl/examples/styles/lv_example_style_7.o \
          lvgl/examples/styles/lv_example_style_8.o \
          lvgl/examples/styles/lv_example_style_9.o \
          lvgl/examples/widgets/animimg/lv_example_animimg_1.o \
          lvgl/examples/widgets/arc/lv_example_arc_1.o \
          lvgl/examples/widgets/arc/lv_example_arc_2.o \
          lvgl/examples/widgets/bar/lv_example_bar_1.o \
          lvgl/examples/widgets/bar/lv_example_bar_2.o \
          lvgl/examples/widgets/bar/lv_example_bar_3.o \
          lvgl/examples/widgets/bar/lv_example_bar_4.o \
          lvgl/examples/widgets/bar/lv_example_bar_5.o \
          lvgl/examples/widgets/bar/lv_example_bar_6.o \
          lvgl/examples/widgets/btn/lv_example_btn_1.o \
          lvgl/examples/widgets/btn/lv_example_btn_2.o \
          lvgl/examples/widgets/btn/lv_example_btn_3.o \
          lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_1.o \
          lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_2.o \
          lvgl/examples/widgets/btnmatrix/lv_example_btnmatrix_3.o \
          lvgl/examples/widgets/calendar/lv_example_calendar_1.o \
          lvgl/examples/widgets/canvas/lv_example_canvas_1.o \
          lvgl/examples/widgets/canvas/lv_example_canvas_2.o \
          lvgl/examples/widgets/chart/lv_example_chart_1.o \
          lvgl/examples/widgets/chart/lv_example_chart_2.o \
          lvgl/examples/widgets/chart/lv_example_chart_3.o \
          lvgl/examples/widgets/chart/lv_example_chart_4.o \
          lvgl/examples/widgets/chart/lv_example_chart_5.o \
          lvgl/examples/widgets/chart/lv_example_chart_6.o \
          lvgl/examples/widgets/chart/lv_example_chart_7.o \
          lvgl/examples/widgets/chart/lv_example_chart_8.o \
          lvgl/examples/widgets/chart/lv_example_chart_9.o \
          lvgl/examples/widgets/checkbox/lv_example_checkbox_1.o \
          lvgl/examples/widgets/checkbox/lv_example_checkbox_2.o \
          lvgl/examples/widgets/colorwheel/lv_example_colorwheel_1.o \
          lvgl/examples/widgets/dropdown/lv_example_dropdown_1.o \
          lvgl/examples/widgets/dropdown/lv_example_dropdown_2.o \
          lvgl/examples/widgets/dropdown/lv_example_dropdown_3.o \
          lvgl/examples/widgets/img/lv_example_img_1.o \
          lvgl/examples/widgets/img/lv_example_img_2.o \
          lvgl/examples/widgets/img/lv_example_img_3.o \
          lvgl/examples/widgets/img/lv_example_img_4.o \
          lvgl/examples/widgets/imgbtn/lv_example_imgbtn_1.o \
          lvgl/examples/widgets/keyboard/lv_example_keyboard_1.o \
          lvgl/examples/widgets/label/lv_example_label_1.o \
          lvgl/examples/widgets/label/lv_example_label_2.o \
          lvgl/examples/widgets/label/lv_example_label_3.o \
          lvgl/examples/widgets/label/lv_example_label_4.o \
          lvgl/examples/widgets/label/lv_example_label_5.o \
          lvgl/examples/widgets/led/lv_example_led_1.o \
          lvgl/examples/widgets/line/lv_example_line_1.o \
          lvgl/examples/widgets/list/lv_example_list_1.o \
          lvgl/examples/widgets/list/lv_example_list_2.o \
          lvgl/examples/widgets/menu/lv_example_menu_1.o \
          lvgl/examples/widgets/menu/lv_example_menu_2.o \
          lvgl/examples/widgets/menu/lv_example_menu_3.o \
          lvgl/examples/widgets/menu/lv_example_menu_4.o \
          lvgl/examples/widgets/menu/lv_example_menu_5.o \
          lvgl/examples/widgets/meter/lv_example_meter_1.o \
          lvgl/examples/widgets/meter/lv_example_meter_2.o \
          lvgl/examples/widgets/meter/lv_example_meter_3.o \
          lvgl/examples/widgets/meter/lv_example_meter_4.o \
          lvgl/examples/widgets/msgbox/lv_example_msgbox_1.o \
          lvgl/examples/widgets/obj/lv_example_obj_1.o \
          lvgl/examples/widgets/obj/lv_example_obj_2.o \
          lvgl/examples/widgets/roller/lv_example_roller_1.o \
          lvgl/examples/widgets/roller/lv_example_roller_2.o \
          lvgl/examples/widgets/roller/lv_example_roller_3.o \
          lvgl/examples/widgets/slider/lv_example_slider_1.o \
          lvgl/examples/widgets/slider/lv_example_slider_2.o \
          lvgl/examples/widgets/slider/lv_example_slider_3.o \
          lvgl/examples/widgets/span/lv_example_span_1.o \
          lvgl/examples/widgets/spinbox/lv_example_spinbox_1.o \
          lvgl/examples/widgets/spinner/lv_example_spinner_1.o \
          lvgl/examples/widgets/switch/lv_example_switch_1.o \
          lvgl/examples/widgets/table/lv_example_table_1.o \
          lvgl/examples/widgets/table/lv_example_table_2.o \
          lvgl/examples/widgets/tabview/lv_example_tabview_1.o \
          lvgl/examples/widgets/tabview/lv_example_tabview_2.o \
          lvgl/examples/widgets/textarea/lv_example_textarea_1.o \
          lvgl/examples/widgets/textarea/lv_example_textarea_2.o \
          lvgl/examples/widgets/textarea/lv_example_textarea_3.o \
          lvgl/examples/widgets/tileview/lv_example_tileview_1.o \
          lvgl/examples/widgets/win/lv_example_win_1.o \
          lvgl/src/core/lv_disp.o \
          lvgl/src/core/lv_event.o \
          lvgl/src/core/lv_group.o \
          lvgl/src/core/lv_indev.o \
          lvgl/src/core/lv_indev_scroll.o \
          lvgl/src/core/lv_obj.o \
          lvgl/src/core/lv_obj_class.o \
          lvgl/src/core/lv_obj_draw.o \
          lvgl/src/core/lv_obj_pos.o \
          lvgl/src/core/lv_obj_scroll.o \
          lvgl/src/core/lv_obj_style.o \
          lvgl/src/core/lv_obj_style_gen.o \
          lvgl/src/core/lv_obj_tree.o \
          lvgl/src/core/lv_refr.o \
          lvgl/src/core/lv_theme.o \
          lvgl/src/draw/arm2d/lv_gpu_arm2d.o \
          lvgl/src/draw/lv_draw.o \
          lvgl/src/draw/lv_draw_arc.o \
          lvgl/src/draw/lv_draw_img.o \
          lvgl/src/draw/lv_draw_label.o \
          lvgl/src/draw/lv_draw_layer.o \
          lvgl/src/draw/lv_draw_line.o \
          lvgl/src/draw/lv_draw_mask.o \
          lvgl/src/draw/lv_draw_rect.o \
          lvgl/src/draw/lv_draw_transform.o \
          lvgl/src/draw/lv_draw_triangle.o \
          lvgl/src/draw/lv_img_buf.o \
          lvgl/src/draw/lv_img_cache.o \
          lvgl/src/draw/lv_img_decoder.o \
          lvgl/src/draw/nxp/lv_gpu_nxp.o \
          lvgl/src/draw/nxp/pxp/lv_draw_pxp_blend.o \
          lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp.o \
          lvgl/src/draw/nxp/pxp/lv_gpu_nxp_pxp_osa.o \
          lvgl/src/draw/nxp/vglite/lv_draw_vglite_arc.o \
          lvgl/src/draw/nxp/vglite/lv_draw_vglite_blend.o \
          lvgl/src/draw/nxp/vglite/lv_draw_vglite_rect.o \
          lvgl/src/draw/nxp/vglite/lv_gpu_nxp_vglite.o \
          lvgl/src/draw/sdl/lv_draw_sdl.o \
          lvgl/src/draw/sdl/lv_draw_sdl_arc.o \
          lvgl/src/draw/sdl/lv_draw_sdl_bg.o \
          lvgl/src/draw/sdl/lv_draw_sdl_composite.o \
          lvgl/src/draw/sdl/lv_draw_sdl_img.o \
          lvgl/src/draw/sdl/lv_draw_sdl_label.o \
          lvgl/src/draw/sdl/lv_draw_sdl_layer.o \
          lvgl/src/draw/sdl/lv_draw_sdl_line.o \
          lvgl/src/draw/sdl/lv_draw_sdl_mask.o \
          lvgl/src/draw/sdl/lv_draw_sdl_polygon.o \
          lvgl/src/draw/sdl/lv_draw_sdl_rect.o \
          lvgl/src/draw/sdl/lv_draw_sdl_stack_blur.o \
          lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.o \
          lvgl/src/draw/sdl/lv_draw_sdl_utils.o \
          lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.o \
          lvgl/src/draw/sw/lv_draw_sw.o \
          lvgl/src/draw/sw/lv_draw_sw_arc.o \
          lvgl/src/draw/sw/lv_draw_sw_blend.o \
          lvgl/src/draw/sw/lv_draw_sw_dither.o \
          lvgl/src/draw/sw/lv_draw_sw_gradient.o \
          lvgl/src/draw/sw/lv_draw_sw_img.o \
          lvgl/src/draw/sw/lv_draw_sw_layer.o \
          lvgl/src/draw/sw/lv_draw_sw_letter.o \
          lvgl/src/draw/sw/lv_draw_sw_line.o \
          lvgl/src/draw/sw/lv_draw_sw_polygon.o \
          lvgl/src/draw/sw/lv_draw_sw_rect.o \
          lvgl/src/draw/sw/lv_draw_sw_transform.o \
          lvgl/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.o \
          lvgl/src/extra/layouts/flex/lv_flex.o \
          lvgl/src/extra/layouts/grid/lv_grid.o \
          lvgl/src/extra/libs/bmp/lv_bmp.o \
          lvgl/src/extra/libs/ffmpeg/lv_ffmpeg.o \
          lvgl/src/extra/libs/freetype/lv_freetype.o \
          lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.o \
          lvgl/src/extra/libs/fsdrv/lv_fs_posix.o \
          lvgl/src/extra/libs/fsdrv/lv_fs_stdio.o \
          lvgl/src/extra/libs/fsdrv/lv_fs_win32.o \
          lvgl/src/extra/libs/gif/gifdec.o \
          lvgl/src/extra/libs/gif/lv_gif.o \
          lvgl/src/extra/libs/png/lodepng.o \
          lvgl/src/extra/libs/png/lv_png.o \
          lvgl/src/extra/libs/qrcode/lv_qrcode.o \
          lvgl/src/extra/libs/qrcode/qrcodegen.o \
          lvgl/src/extra/libs/rlottie/lv_rlottie.o \
          lvgl/src/extra/libs/sjpg/lv_sjpg.o \
          lvgl/src/extra/libs/sjpg/tjpgd.o \
          lvgl/src/extra/lv_extra.o \
          lvgl/src/extra/others/fragment/lv_fragment.o \
          lvgl/src/extra/others/fragment/lv_fragment_manager.o \
          lvgl/src/extra/others/gridnav/lv_gridnav.o \
          lvgl/src/extra/others/ime/lv_ime_pinyin.o \
          lvgl/src/extra/others/imgfont/lv_imgfont.o \
          lvgl/src/extra/others/monkey/lv_monkey.o \
          lvgl/src/extra/others/msg/lv_msg.o \
          lvgl/src/extra/others/snapshot/lv_snapshot.o \
          lvgl/src/extra/themes/basic/lv_theme_basic.o \
          lvgl/src/extra/themes/default/lv_theme_default.o \
          lvgl/src/extra/themes/mono/lv_theme_mono.o \
          lvgl/src/extra/widgets/animimg/lv_animimg.o \
          lvgl/src/extra/widgets/calendar/lv_calendar.o \
          lvgl/src/extra/widgets/calendar/lv_calendar_header_arrow.o \
          lvgl/src/extra/widgets/calendar/lv_calendar_header_dropdown.o \
          lvgl/src/extra/widgets/chart/lv_chart.o \
          lvgl/src/extra/widgets/colorwheel/lv_colorwheel.o \
          lvgl/src/extra/widgets/imgbtn/lv_imgbtn.o \
          lvgl/src/extra/widgets/keyboard/lv_keyboard.o \
          lvgl/src/extra/widgets/led/lv_led.o \
          lvgl/src/extra/widgets/list/lv_list.o \
          lvgl/src/extra/widgets/menu/lv_menu.o \
          lvgl/src/extra/widgets/meter/lv_meter.o \
          lvgl/src/extra/widgets/msgbox/lv_msgbox.o \
          lvgl/src/extra/widgets/span/lv_span.o \
          lvgl/src/extra/widgets/spinbox/lv_spinbox.o \
          lvgl/src/extra/widgets/spinner/lv_spinner.o \
          lvgl/src/extra/widgets/tabview/lv_tabview.o \
          lvgl/src/extra/widgets/tileview/lv_tileview.o \
          lvgl/src/extra/widgets/win/lv_win.o \
          lvgl/src/font/lv_font.o \
          lvgl/src/font/lv_font_dejavu_16_persian_hebrew.o \
          lvgl/src/font/lv_font_fmt_txt.o \
          lvgl/src/font/lv_font_loader.o \
          lvgl/src/font/lv_font_montserrat_10.o \
          lvgl/src/font/lv_font_montserrat_12.o \
          lvgl/src/font/lv_font_montserrat_12_subpx.o \
          lvgl/src/font/lv_font_montserrat_14.o \
          lvgl/src/font/lv_font_montserrat_16.o \
          lvgl/src/font/lv_font_montserrat_18.o \
          lvgl/src/font/lv_font_montserrat_20.o \
          lvgl/src/font/lv_font_montserrat_22.o \
          lvgl/src/font/lv_font_montserrat_24.o \
          lvgl/src/font/lv_font_montserrat_26.o \
          lvgl/src/font/lv_font_montserrat_28.o \
          lvgl/src/font/lv_font_montserrat_28_compressed.o \
          lvgl/src/font/lv_font_montserrat_30.o \
          lvgl/src/font/lv_font_montserrat_32.o \
          lvgl/src/font/lv_font_montserrat_34.o \
          lvgl/src/font/lv_font_montserrat_36.o \
          lvgl/src/font/lv_font_montserrat_38.o \
          lvgl/src/font/lv_font_montserrat_40.o \
          lvgl/src/font/lv_font_montserrat_42.o \
          lvgl/src/font/lv_font_montserrat_44.o \
          lvgl/src/font/lv_font_montserrat_46.o \
          lvgl/src/font/lv_font_montserrat_48.o \
          lvgl/src/font/lv_font_montserrat_8.o \
          lvgl/src/font/lv_font_simsun_16_cjk.o \
          lvgl/src/font/lv_font_unscii_16.o \
          lvgl/src/font/lv_font_unscii_8.o \
          lvgl/src/hal/lv_hal_disp.o \
          lvgl/src/hal/lv_hal_indev.o \
          lvgl/src/hal/lv_hal_tick.o \
          lvgl/src/misc/lv_anim.o \
          lvgl/src/misc/lv_anim_timeline.o \
          lvgl/src/misc/lv_area.o \
          lvgl/src/misc/lv_async.o \
          lvgl/src/misc/lv_bidi.o \
          lvgl/src/misc/lv_color.o \
          lvgl/src/misc/lv_fs.o \
          lvgl/src/misc/lv_gc.o \
          lvgl/src/misc/lv_ll.o \
          lvgl/src/misc/lv_log.o \
          lvgl/src/misc/lv_lru.o \
          lvgl/src/misc/lv_math.o \
          lvgl/src/misc/lv_mem.o \
          lvgl/src/misc/lv_printf.o \
          lvgl/src/misc/lv_style.o \
          lvgl/src/misc/lv_style_gen.o \
          lvgl/src/misc/lv_templ.o \
          lvgl/src/misc/lv_timer.o \
          lvgl/src/misc/lv_tlsf.o \
          lvgl/src/misc/lv_txt.o \
          lvgl/src/misc/lv_txt_ap.o \
          lvgl/src/misc/lv_utils.o \
          lvgl/src/widgets/lv_arc.o \
          lvgl/src/widgets/lv_bar.o \
          lvgl/src/widgets/lv_btn.o \
          lvgl/src/widgets/lv_btnmatrix.o \
          lvgl/src/widgets/lv_canvas.o \
          lvgl/src/widgets/lv_checkbox.o \
          lvgl/src/widgets/lv_dropdown.o \
          lvgl/src/widgets/lv_img.o \
          lvgl/src/widgets/lv_label.o \
          lvgl/src/widgets/lv_line.o \
          lvgl/src/widgets/lv_objx_templ.o \
          lvgl/src/widgets/lv_roller.o \
          lvgl/src/widgets/lv_slider.o \
          lvgl/src/widgets/lv_switch.o \
          lvgl/src/widgets/lv_table.o \
          lvgl/src/widgets/lv_textarea.o \
      	
      	
      	
      	
      	
      	
      	
      	
      	
      

      1.2 快速测试Makefile修改是否有效
      把主函数中和硬件相关的显示,输入等初始化代码屏蔽,main改为lv_main,并把lv_main变成一个命令:

      int lv_main(int argc, char **argv)
      {
        //(void *)argc; /*Unused*/  //(void)argv; /*Unused*/
        printf("lv_main.");
      #if   0
        /*Initialize LVGL*/
        lv_init();
      
        /*Create a default group for keyboard navigation*/
        lv_group_set_default(lv_group_create());
      
        /*Initialize the HAL (display, input devices, tick) for LVGL*/
        hal_init();
      .....
      #endif
        return 0;
      }
      static lv_disp_t * hal_init(void  )
      {
      #if 0
          disp_layer_cfg_def();
      
          static lv_disp_draw_buf_t draw_buf;
      
          lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES);
      
          static lv_disp_drv_t disp_drv;
          lv_disp_drv_init(&disp_drv);
      ......   
          lv_disp_drv_register(&disp_drv);
      #endif
      	lv_disp_t * disp = NULL;
        	return disp;
      }
      FINSH_FUNCTION_EXPORT_ALIAS(lv_main, lv_main, lv_main );
      

      编译通过,烧录测试。输入help,可以看到lv_main命令,输入lv_main,打印“lv_main”:

      msh />help
      RT-Thread shell commands:
      ......
      lv_main          - lv_main
      ......
      msh />lv_main
      lv_main
      

      2.移植刷新显示内存函数dummy_flush_cb
      只要往显存地址 mem = g_disp_mm[mem_id].info_base里面填写像素数据,就可以得到我们要显示的内容,把这个地址传给一个全局变量,在lvgl中使用这个全局变量即可。
      于是我们在disp_mem源码所在的C文件声明一个全局变量:

      uint32_t * g_p_mem_base;
      

      把显存地址传给g_p_mem_base:

      g_p_mem_base = g_disp_mm[mem_id].info_base;
      

      66d07899ccb64e378c1f03b5efecaa02.png

      有了这个地址,我们就可以编写自己的显示回调函数:

      00a3008912034438b7cd5bfb5298e43a.png

      #define HOR_RES 800
      #define VER_RES 480
      extern  uint32_t * g_p_mem_base;
      #define line_length 800 * sizeof(rt_uint32_t) / 4
      static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
      {
          /*Truncate the area to the screen*/
          int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
          int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
          int32_t act_x2 =        area->x2 > (int32_t)HOR_RES - 1 ? (int32_t)HOR_RES - 1 : area->x2;
          int32_t act_y2 =        area->y2 > (int32_t)VER_RES - 1 ? (int32_t)VER_RES - 1 : area->y2;
      
          lv_coord_t w = (act_x2 - act_x1 + 1);
      
          long int location = 0;
      
          /* 32 bit per pixel */
          uint32_t *fbp32 = (uint32_t *)g_p_mem_base;
          uint32_t y;
          for (y = act_y1; y <= act_y2; y++)
          {
              location = act_x1 + y * line_length;
              rt_memcpy(&fbp32[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 4);
              color_p += w;
          }   
              
          lv_disp_flush_ready(disp_drv);
      }
      static lv_color_t disp_buf1[HOR_RES * VER_RES];
      static lv_color_t disp_buf2[HOR_RES * VER_RES];
      int disp_layer_cfg_def(void);
      static lv_disp_t * hal_init(void  )
      {
      #if 1
          disp_layer_cfg_def();
      
          static lv_disp_draw_buf_t draw_buf;
      
          lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES);
      
          static lv_disp_drv_t disp_drv;
          lv_disp_drv_init(&disp_drv);
          disp_drv.draw_buf = &draw_buf;
          disp_drv.flush_cb = dummy_flush_cb;
          disp_drv.hor_res = HOR_RES;
          disp_drv.ver_res = VER_RES;
          lv_disp_drv_register(&disp_drv);
      #endif
      	lv_disp_t * disp = NULL;
        return disp;
      }
      

      再make编译,通过。

      3.创建一个定时器调用lvgl心跳lv_tick_inc()
      Melis使用rt-thread内核,rt-thread的节拍由宏定义 CONFIG_HZ决定:

      #define RT_TICK_PER_SECOND  CONFIG_HZ
      

      CONFIG_HZ通过 命令 make menuconfig 配置:
      20e381ae48f042bba968cbaea018f188.png

      这里是200Hz,也就是一个时钟节拍为5ms。

      static rt_timer_t timer1;      
      //      lv_tick_inc(5);
      static lv_disp_t * hal_init(void  )
      {
      #if 1
          /* 创建定时器1  周期定时器 */
          timer1 = rt_timer_create("timer1", 
          						lv_tick_inc,	//	回调函数
                                   5,				//	回调函数的传入参数
                                   1,	//	一个时钟节拍调用一次回调函数,具体是5ms
                                   RT_TIMER_FLAG_PERIODIC);
          /* 启动定时器1 */
          if (timer1 != RT_NULL)
              rt_timer_start(timer1);
      
          disp_layer_cfg_def();
      
      ......
      #endif
      	lv_disp_t * disp = NULL;
        return disp;
      }
      

      lv_timer_handler()调用间隔是10ms,而lv_tick_inc()调用间隔是5ms,这样比较合理。

      4.pack打包出错:

      root@SK-JNTINRTMRDZW:/home/book/D1s-Melis-master# pack
      INFO: temporarily Enter pack directory: "/home/book/D1s-Melis-master/out/d1s-mq/image", will be back when terminated
      INFO: copying config/boot binary/phoenix plugin files
      /home/book/D1s-Melis-master/tools/phoenixplugin/Tools.fex
      ......
      ......
      INFO: running the function do_finish "sys_partition_nor.bin"
      
      partitation file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sys_partition_nor.bin
      mbr_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sunxi_mbr_nor.fex
      download_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/dlinfo.fex
      
      ERROR: dl file melis_pkg_nor.fex size too large
      ERROR: filename = melis_pkg_nor.fex
      ERROR: dl_file_size = 2272 sector
      ERROR: part_size = 2048 sector
      ERROR: update mbr file fail
      ERROR: update_mbr failed
      

      melis_pkg_nor.fex文件比分配的空间要大,装不下。
      修改分区文件D1s-Melis/projects/d1s-mq/configs/sys_partition_nor.fex第44,45行:
      7ee7954291004b149ebf5be03d803c39.png

      ;---------------------------------------------------------------------------------------------------------
      ; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串
      ;---------------------------------------------------------------------------------------------------------
      
      
      ;--------------------------------------------------------------------------------------------------
      ;                                   固件下载参数配置
      ;--------------------------------------------------------------------------------------------------
      ;****************************************************
      ;    mbr的大小, 以Kbyte为单位
      ;****************************************************
      [mbr]
      size = 16
      
      ;********************************************************************************************************
      ;                                              分区配置
      ;
      ;
      ;  partition 定义范例:
      ;    [partition]                ;  //表示是一个分区
      ;    name        = USERFS2      ; //分区名称
      ;    size        = 16384        ; //分区大小 单位: 扇区.分区表示个数最多2^31 * 512 = 2T
      ;    downloadfile = "123.fex"   ; //下载文件的路径和名称,可以使用相对路径,相对是指相对于image.cfg文件所在分区。也可以使用绝对路径
      ;    keydata     = 1            ; //私有数据分区,重新量产数据将不丢失
      ;    encrypt     = 1            ; //采用加密方式烧录,将提供数据加密,但损失烧录速度
      ;    user_type   = ?            ; //私有用法
      ;    verify      = 1            ; //要求量产完成后校验是否正确
      ;
      ; 注:1、name唯一, 不允许同名
      ;     2、name最大12个字符
      ;     3、size = 0, 将创建一个无大小的空分区
      ;     4、为了安全和效率考虑,分区大小最好保证为16M字节的整数倍
      ;********************************************************************************************************
      [partition_start]
      
      ;[partition]
      ;    name         = boot
      ;    size         = 6656
      ;    downloadfile = "boot.fex"
      ;    user_type    = 0x8000
      
      [partition]
          name         = bootA
          ;size         = 2048
          size         = 4096
          downloadfile = "melis_pkg_nor.fex"
          user_type    = 0x8000
      
      ;[partition]
      ;    name         = bootB
      ;    size         = 6144
      ;    downloadfile = "melis_pkg_nor.fex"
      ;    user_type    = 0x8000
      
      ;[partition]
      ;    name         = env
      ;    size         = 8
      ;    downloadfile = "env.fex"
      ;    user_type    = 0x8000
      
      ;[partition]
      ;    name         = env-redund
      ;    size         = 8
      ;    downloadfile = "env.fex"
      ;    user_type    = 0x8000
      
      ;rootfs 7616 sector in rootfs.ini make 7616*1024/512=15232 sectors for it.
      [partition]
          name         = ROOTFS
          size         = 10240
          ;size         = 20336
          downloadfile = "data_udisk.fex"
          user_type    = 0x8000
      
      [partition]
          name         = UDISK
          ;size = flash size - (boot0 + mbr) size - env - env-redund - ROOTFS
          ;8(or 16) * 1024 * 2 - 64 * 2 - 5632 - 8 - 8 - 10240
          ;size         = 20336
          ;downloadfile = "data_udisk.fex"
          user_type    = 0x8000
      

      再次pack打包成功。烧录运行,输入lv_main命令:

      msh />lv_main
      

      4422f994a95841b9bfb83aebccf15a71.gif

      5.设置开机启动
      修改startup.sh(位于目录 D1s-Melis/projects/d1s-mq/data/UDISK/startup.sh):

      echo "Execute startup script begin.............."
      
      #insmod d:\mod\display.mod
      #insmod d:\mod\orange.mod
      #insmod d:\apps\desktop.mod
      lv_main
      echo "...............Execute startup script end"
      

      6.源码下载
      源码没有startup.sh 和 melis_pkg_nor.fex ,这两个文件的修改比较简单。
      源码链接:https://gitee.com/huangweide001/linux-d1-h-test/tree/master/disp2
      源码包含了可以直接烧录的img文件 melis_d1s-mq_uart0_8Mnor_lvgl.img 。

      ————————————————
      本文为CSDN博主「hwd00001」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
      原文链接:https://blog.csdn.net/hwd00001/article/details/130017849

      发布在 MR Series
      B
      bigfly
    • 按照东山派的官方教程编译buildroot(东山哪吒,D1-H)踩坑记录

      原文链接:https://blog.csdn.net/hwd00001/article/details/127896895
      作者 @ hwd00001

      整个编译的耗时主要是github的下载速度,很多依赖包都需要从github下载。

      这里我以东山派的官方教程为主,根据我的实际情况稍作调整,梳理一下编译buildroot流程。

      官方教程链接:使用buildroot-SDK编译构建系统

      1.编译流程

      1.1获取sdk源码

      有2个服务器github和gitee,我使用gitee的源。

      6ccd5148b6324ff4809608f8d0d74f39.png

      依次执行命令:

      book@virtual-machine:~$ git clone  https://gitee.com/weidognshan/buildroot_dongshannezhastu
      book@virtual-machine:~$ cd buildroot_dshannezhastu
      book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --init --recursive
      book@virtual-machine:~/buildroot_dongshannezhastu$ git submodule update --recursive --remote
      

      这个步骤还是比较快的,10分钟以内,取决于网速。

      1.2 补充:下载riscv64-glibc-gcc-thead_20200702.tar.xz

      这个步骤参考后面的问题2.

      1.3 补充:安装mtool工具

      这个步骤参考后面的问题3.

      1.4 安装必要依赖包

      sudo apt-get install -y  libncurses5-dev   u-boot-tools
      

      1.5 编译sdcard 最小系统镜像

      book@virtual-machine:~/buildroot_dongshannezhastu$ cd buildroot-awol/
      book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make  BR2_EXTERNAL="../br2lvgl  ../br2qt5 ../br2nezhastu"  dongshannezhastu_sdcard_core_defconfig
      
      book@virtual-machine:~/buildroot_dongshannezhastu/buildroot-awol$ make
      

      98f38fa786e041a2b69d62052b31e35d.png

      1.6 烧录最小镜像系统到tf(SD)卡

      原文档:东山哪吒快速启动

      1.6.1 安装烧录工具

      a345c5ffa822422f80de43630cd47225.png

      1.6.2 格式化SD卡

      93edc13a0e704ba0a3f0b1774df76f94.png

      1.6.3 烧录镜像到sd卡

      70d6935eed194d9da3787f8fe9aabd97.png

      1.7 运行系统

      把SD卡插到开发板,上电,检查一下是不是最新编译的:
      a7941988188a4c0ab5aefe14c95e401c.png

      我对比一下原来的一张烧录官方提供的image的文件日期:
      b91058bfbf554a09b5afedf07ff7676a.png

      2.问题踩坑记录

      问题1:make指令不执行

      root@SK-JNTINRTMRDZW:/home/hwd/buildroot_dongshannezhastu/buildroot-awol> make
      
      Your PATH contains spaces, TABs, and/or newline (\n) characters.
      This doesn't work. Fix you PATH.
      support/dependencies/dependencies.mk:27: recipe for target 'dependencies' failed
      make: *** [dependencies] Error 1
      

      百度解决方法:《This doesn‘t work. Fix you PATH》

      采用这个方法顺利解决(切换环境变量)。
      b8c40074460e43cc935a5054b415e4d9.png

      问题2:riscv64-glibc-gcc-thead_20200702.tar.xz File format not recognized

      WARNING: no hash file for riscv64-glibc-gcc-thead_20200702.tar.xz
      ....../riscv64-glibc-gcc-thead_20200702.tar.xz: File format not recognized
      tar: This does not look like a tar archive
      tar: Exiting with failure status due to previous errors
      

      去到该文件所在目录 /home/hwd/buildroot_dongshannezhastu/buildroot-awol/dl/toolchain-external-custom 看到,文件的大小只有1k,不知道是什么原因导致的。
      继续百度搜到《为全志D1/RISCV64设备移植openwrt-22.03系统》,提到要手动下载 riscv64-glibc-gcc-thead_20200702.tar.xz,提供了东山派的官方链接:《快速使用Tina-SDK 指南》:

      4afc74d3210c4311b0f119573029865c.png

      下载完成后,发现文件名是 riscv64-glibc-gcc-thead_20200702tar.xz :
      67a2a301853345b09a504b9ab39a8c25.png
      增加小数点后,不用解压,重新执行make,自动解压成功,往下进行。

      问题3: /bin/sh: 1: mcopy: not found
      e8dacf62a91c4064be8fb18d88395b98.png

      没有安装mtool工具:

      apt-get install mtools
      

      重新make,终于完成:

      a208e83fa12a4cd6bcf7de738b83dc90.png

      发布在 MR Series
      B
      bigfly
    • 求推荐一个视频录像的芯片方案

      需要的功能如下:

      1. 支持数字摄像头输入,
      2. cvbs输入(和数字摄像头输入不是同时进行),
      3. cvbs输出,
      4. LCD屏幕显示(和cvbs输出不是同时进行),
      5. 支持编码器和解码器,最高支持1920X1080@30fps,可以更高。
      6. 支持SD

      我看F1C100S的datasheet,没有H.264编码器。是不是就可以直接排除F1C100S了?

      F1C100S_2.5.png

      发布在 其它全志芯片讨论区
      B
      bigfly
    • T3编译内核报错

      QQ图片20230407105045.png

      发布在 其它全志芯片讨论区
      B
      bigfly
    • 回复: 在DongshanPI-D1上实现MPU6050数据读取

      @yanmingjian 正好要用到类似的项目里,先码住

      发布在 MR Series
      B
      bigfly
    • V851s 引出的 gpio 怎么玩?可以设定成常规的gpio吗

      排插给出的这几个,可以设定成常规的gpio 使用吗
      QQ图片20230331091749.png

      发布在 V Series
      B
      bigfly
    • 电阻触摸不知道为什么有很大的延迟

      用的sunxi-ts驱动 tslib1.22,
      延迟效果如视频显示

      发布在 MR Series
      B
      bigfly
    • 回复: Does D1-H have CAN interface?

      @tsvetan D1-H没有can接口,需要can接口可以考虑 T113

      发布在 MR Series
      B
      bigfly
    • 回复: 参照大佬的教程在Tina下适配 i80 LCD 显示屏,一接屏幕就报错重启

      改个i8080要吐血了,大佬给分析下是不是驱动没加载

      20230310105521.jpg

      20230310105524.jpg

      发布在 MR Series
      B
      bigfly
    • 回复: 参照大佬的教程在Tina下适配 i80 LCD 显示屏,一接屏幕就报错重启

      @bayche 谢谢大佬,还有个问题
      disp_al_manager_apply ouput_type:0 怎么把 ouput_type:改为1,是修改board.dts的disp么 ?

      发布在 MR Series
      B
      bigfly
    • 参照大佬的教程在Tina下适配 i80 LCD 显示屏,一接屏幕就报错重启

      参照大佬的教程来做的:https://www.gloomyghost.com/live/20220424.aspx

      然后一装上屏幕就会报以下错误

      1sdcja15

      然后就重启了,是 板子的io没有配制好还是 电路有问题?

      发布在 MR Series
      B
      bigfly
    • 【米尔MYD-YT507开发板试用】基于Fluter+Django+OpenCV的米尔行车记录仪

      经过充分的学习T507开发板,最终选择应用Fluter+Django+OpenCV架构,来实现了一款米尔行车记录仪,现将实现的具体内容,与大家分享。

      目录:

      • 行车记录仪业务逻辑规划
      • 硬件设备准备
      • 摄像头信息记录和实时画面播放服务开发
      • 摄像头视频信息记录
      • 摄像头服务的完整代码
      • 历史数据RestFul服务开发
      • Flutter Web界面开发
      • 整体运行效果
      • 车试
      • 实际代码使用
      • 感谢
      • 总结

      一、行车记录仪业务逻辑规划

      经过详细的分析,规划了如下的基本业务逻辑结构:

      poYBAGMTXJKAOfJOAAG8aeHxdnc436.png

      整体分为三个部分:

      • 记录服务:用于记录摄像头拍摄的视频信息,以及提供摄像头当前画面的实时播放服务。

      • Django服务:包括RestFul提供API接口获取历史数据信息,以及为Flutter的Web界面提供访问服务。

      • Flutter Web界面,用于实时画面播放、历史记录播放的界面。

      为了又快又好的开发行车记录仪的实际界面,以及后续进行各移动平台的App开发,选择了Flutter。事实证明,坑太多了。不过,跨平台特性,确实好。

      二、硬件设备准备:

      开发这款行车记录仪,实际使用到的硬件设备如下:

      1.主控板:米尔MYD-YT507开发板
      2.摄像头:海康威视DS-E11 720P USB摄像头
      3.存储卡:闪迪32GB高速MicroSD存储卡
      4.路由器:云来宝盒无线路由器

      pYYBAGMTXySAK85zAE2uYyvbG20799.png

      路由器没有拍照,用普通无线路由器即可,当然带宽越高越好。

      开发板上有两个USB3.0接口,选一个接上路由器即可。

      然后,将开发板使用网线连接到路由器,再上电,就可以进行实际的操作了。

      我这边实际使用中,电源接口有点松,容易突然断电,所以使用胶带进行了加固。

      三、摄像头实时画面播放服务开发

      在之前尝试MJPEG视频流直播的时候,使用了mjpeg_streamer,但不清楚如何进行视频的分割。

      因为行车记录仪,一般都是按照一定的时间进行视频的分割存放,避免单个视频过大。

      经过仔细的学习了解,OpenCV也可以获取摄像头的信息,并按照需要写入文件。

      最后,采用了Python+OpenCV的方案,有Python负责具体的逻辑,Python-OpenCV负责摄像头视频数据的采集。

      视频采集部分,包含的具体功能为:

      • 能够采集摄像头的数据
      • 能够提供实时视频查看
      • 能够按时间写入视频数据到文件,自动进行分割

      采集摄像头的数据,Python-opencv搞定。

      写入视频数据到文件,Python简单搞定。

      提供实时视频预览,这个花了不少功夫。

      因为同时要写入到文件,还要提供预览,数据需要复用。

      经过学习了解,可以将Python-opencv采集的画面,按帧在HTTP以JPEG数据发送,那么播放端,就能收到MJPEG数据流,进行播放了。

      因此,第一版,参考资料,实现了一个Python版的MJPEG播放服务,读取帧,写入临时文件,然后从临时文件读取数据返回。

      为了提高效率,还进行了优化,不写入临时文件,直接在内存中进行转换。

      最终形成的代码如下:

      # http服务器请求处理:网页、MJPEG数据流
      class CamHandler(BaseHTTPRequestHandler):
          def do_GET(self):
              # mjpeg推流
              if self.path.endswith('.mjpg'):
                  self.send_response(200)
                  self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
                  self.end_headers()
                  while True:
                      if is_stop:
                          break
                      try:
                          # rc,img = cameraCapture.read()
                          rc,img = success,frame
                          if not rc:
                              continue
                          if True:
                              imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
                              jpg = Image.fromarray(imgRGB)
                              tmpFile = BytesIO()
                              jpg.save(tmpFile,'JPEG')
                              self.wfile.write(b"--jpgboundary")
                              self.send_header(b'Content-type','image/jpeg')
                              self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes))
                              self.end_headers()
                              jpg.save(self.wfile,'JPEG')
                          else:
                              img_fps = JPEG_QUALITY_VALUE
                              img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
                              img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format
                              self.send_header('Content-type','image/jpeg')
                              self.end_headers()
                              self.wfile.write(img_str)
                              self.wfile.write(b"
      --jpgboundary
      ") # end of this part
                          time.sleep(0.033)
                      except KeyboardInterrupt:
                          self.wfile.write(b"
      --jpgboundary--
      ")
                          break
                      except BrokenPipeError:
                          continue
                  return
              # 网页
              if self.path == '/' or self.path.endswith('.html'):
                  self.send_response(200)
                  self.send_header('Content-type','text/html')
                  self.end_headers()
                  self.wfile.write(b'<html><head><title>Live video</title></head><body>')
                  self.wfile.write(('<img src="http://%s/live.mjpg"/>' % self.headers.get('Host')).encode())
                  self.wfile.write(b'</body></html>')
                  return
      

      这段代码,提供了两个功能:

      • 如果通过浏览器访问http://ip:端口/index.html,就会返回包含MJPEG调用地址的网页

      • 如果通过浏览器访问http://ip:端口/live.mjpg,就会返回MJPEG流媒体数据,以便播放

      在开发过程中,运行该服务后,随时可以通过浏览器查看效果。

      其中涉及到opencv相关的知识,以及webserver相关的知识,大家可以了解相关的资料做基础,这里就不详细说了。

      本来以为提供了MJPEG服务,就能够在Flutter开发的Web界面中调用了。然而,实际使用时,发现坑来了。

      Flutter的公共库里面,有MJPEG的库,但是在目前的版本中,已经不能使用了。且官方认为用的人不多,在可预见的将来,不会修复。悲催啊!!!

      条条大道通罗马,此处不通开新路。

      经过再次的学习了解,Flutter的Video功能,支持Stream模式,其可以采用WebSocket的方式来获取数据,然后进行播放。

      那么,只要能够在服务端,将获取的帧数据,使用WebSocket提供,就能够正常播放了。

      最终,使用Python开发了能够提供实时视频数据的WebSocket服务,具体代码如下:

      # websocket服务请求处理
      async def CamTransmitHandler(websocket, path):
          print("Client Connected !")
          try :
              while True:
                  # rc,img = cameraCapture.read()
                  rc,img = success,frame
                  if not rc:
                      continue
      
                  img_fps = JPEG_QUALITY_VALUE
                  img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
                  encoded = cv2.imencode('.jpg', img, img_param)[1]
                  data = str(base64.b64encode(encoded))
                  data = data[2:len(data)-1]
                  await websocket.send(data)
      
                  # cv2.imshow("Transimission", frame)
                  # if cv2.waitKey(1) & 0xFF == ord('q'):
                  #     break
              # cap.release()
          except EXCEPTION_CONNECTION_CLOSE as e:
              print("Client Disconnected !")
              # cap.release()
          except:
              print("Someting went Wrong !")
      

      这个部分比之前的更简单,就是简单的转换数据,喂数据给WebSocket即可。

      上述的两部分代码中,都没有包含完整的逻辑处理过程,只有关键代码部分。

      各部分分别讲完以后,将提供完整的代码以供学习。

      到这里,实时流媒体功能就实现了。

      四、摄像头视频信息记录

      实际上,上一步的实时视频功能,也依赖于这一步,因为其需要共享实际获取的摄像头信息。
        
      其基本逻辑也比较简单,步骤如下:

      • 初始化opencv,开始摄像头数据帧的获取
      • 检测是否达到预定时间
      • 未达到时间,则继续写入当前视频
      • 达到时间了,则关闭当前视频,写入缩略图,并开启新的文件写入
          
        具体代码如下:
      # 捕获摄像头
      cameraCapture = cv2.VideoCapture(CAMERA_NO)
      
      # 摄像头参数设置
      cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
      cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
      cameraCapture.set(cv2.CAP_PROP_SATURATION, 135)
      
      fps = 30
      size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
      
      # 读取捕获的数据
      success,frame = cameraCapture.read()
      

      ...

      while True:
          if is_stop:
              success = False
              break;
      
          success,frame = cameraCapture.read()
          if not success:
              continue
      
          time_now = get_current_time()
          if time_now["time"] - time_record["time"] >= ROTATE_TIME:
              if time_record_prev:
                  thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg')
                  print("[Info] write to thumb: %s" % thubm_file)
                  if not os.path.isfile(thubm_file):
                      cv2.imwrite(thubm_file, frame)
      
              time_record = time_now
              time_record_prev = get_current_time()
              video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT)
              print("[Info] write to video: %s" % video_file)
      
          # encode = cv2.VideoWriter_fourcc(*"mp4v")
          encode = cv2.VideoWriter_fourcc(*'X264')
          # encode = cv2.VideoWriter_fourcc(*'AVC1')
          # encode = cv2.VideoWriter_fourcc(*'XVID')
          # encode = cv2.VideoWriter_fourcc(*'H264')
          videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4
          numFrameRemaining = ROTATE_TIME * fps    #摄像头捕获持续时间
          while success and numFrameRemaining > 0:
              videoWriter.write(frame)
              success,frame = cameraCapture.read()
              numFrameRemaining -= 1
      
      cameraCapture.release()
      

      上述代码的逻辑其实很清晰,有opencv的基础,一看就懂。

      有一个关键点需要注意的就是 encode = cv2.VideoWriter_fourcc(*'X264') ,在不同的环境下面,提供的编码方式不完全相同。

      在米尔MYD-YT507开发板的Ubuntu环境中,可以使用X264编码。

      上述代码,会持续不断的读取摄像头的数据帧,存放到frame变量中,然后写入到视频文件中。并进行时间判断,以确定是否需要写入到新的视频文件中。

      frame变量,在之前实时视频服务中,也会使用,相当于是共享了。

      五、摄像头服务的完整代码

      经过上面的两个部分,就完成了摄像头部分的服务代码。

      整体的代码如下:

      # -*- coding: utf-8 -*-
      import signal
      import cv2
      import time
      from PIL import Image
      from threading import Thread
      from http.server import BaseHTTPRequestHandler,HTTPServer
      from socketserver import ThreadingMixIn
      from io import BytesIO
      
      import os
      import sys
      import websockets
      import asyncio
      import base64
      import ctypes
      import inspect
      
      CAMERA_NO = 2
      ROTATE_TIME = 120
      MJPEG_ENABLE = 1
      WEBSOCKET_ENABLE = 1
      MJPEG_SERVER_PORT = 28888
      WEBSOCKET_PORT = 28889
      JPEG_QUALITY_VALUE = 65
      STORE_DIR = "./data/" if os.uname()[0] == 'Darwin' else "/sdcard/data/"
      MEDIA_EXT = "mkv"
      
      EXCEPTION_CONNECTION_CLOSE = websockets.exceptions.ConnectionClosed if sys.version[:3] == '3.6' else websockets.ConnectionClosed
      
      def _async_raise(tid, exctype):
          """raises the exception, performs cleanup if needed"""
          try:
              tid = ctypes.c_long(tid)
              if not inspect.isclass(exctype):
                  exctype = type(exctype)
              res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
              if res == 0:
                  # pass
                  raise ValueError("invalid thread id")
              elif res != 1:
                  # """if it returns a number greater than one, you're in trouble,
                  # and you should call it again with exc=NULL to revert the effect"""
                  ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
                  raise SystemError("PyThreadState_SetAsyncExc failed")
          except Exception as err:
              print(err)
      
      
      def stop_thread(thread):
          """终止线程"""
          _async_raise(thread.ident, SystemExit)
      
      # 信号处理回调
      def signal_handler(signum, frame):
          # global cameraCapture
          # global thread
          # global server
          # global is_stop
          # global success
          print('signal_handler: caught signal ' + str(signum))
          if signum == signal.SIGINT.value:
              print('stop server:')
              is_stop = True
              success = False
              print("mjpeg server.socket.close...")
              server.socket.close()
              print("mjpeg server.shutdown...")
              server.shutdown()
              print("ws server.socket.close...")
              server_ws.ws_server.close()
              time.sleep(1)
              # print("ws server.shutdown...")
              # await server_ws.ws_server.wait_closed()
              print("mjpeg thread.shutdown...")
              thread_mjpeg.join()
              print("ws loop.shutdown...")  
              # event_loop_ws.stop()
              event_loop_ws.call_soon_threadsafe(event_loop_ws.stop)
              time.sleep(1)
              # print("ws thread.shutdown...")  
              # stop_thread(thread_ws)
              # time.sleep(1)
              # print(server)
              # print(server_ws)
              print(thread_mjpeg.is_alive())
              print(thread_ws.is_alive())
              print(event_loop_ws.is_running())
              # thread_ws.join()
              print("cameraCapture.release...")
              cameraCapture.release()
              print("quit...")
              # print(server_ws)
              sys.exit(0)
      
      # http服务器请求处理:网页、MJPEG数据流
      class CamHandler(BaseHTTPRequestHandler):
          def do_GET(self):
              # mjpeg推流
              if self.path.endswith('.mjpg'):
                  self.send_response(200)
                  self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
                  self.end_headers()
                  while True:
                      if is_stop:
                          break
                      try:
                          # rc,img = cameraCapture.read()
                          rc,img = success,frame
                          if not rc:
                              continue
                          if True:
                              imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
                              jpg = Image.fromarray(imgRGB)
                              tmpFile = BytesIO()
                              jpg.save(tmpFile,'JPEG')
                              self.wfile.write(b"--jpgboundary")
                              self.send_header(b'Content-type','image/jpeg')
                              self.send_header(b'Content-length',str(tmpFile.getbuffer().nbytes))
                              self.end_headers()
                              jpg.save(self.wfile,'JPEG')
                          else:
                              img_fps = JPEG_QUALITY_VALUE
                              img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
                              img_str = cv2.imencode('.jpg', img, img_param)[1].tobytes() # change image to jpeg format
                              self.send_header('Content-type','image/jpeg')
                              self.end_headers()
                              self.wfile.write(img_str)
                              self.wfile.write(b"
      --jpgboundary
      ") # end of this part
                          time.sleep(0.033)
                      except KeyboardInterrupt:
                          self.wfile.write(b"
      --jpgboundary--
      ")
                          break
                      except BrokenPipeError:
                          continue
                  return
              # 网页
              if self.path == '/' or self.path.endswith('.html'):
                  self.send_response(200)
                  self.send_header('Content-type','text/html')
                  self.end_headers()
                  self.wfile.write(b'<html><head><title>Live video</title></head><body>')
                  self.wfile.write(('<img src="http://%s/live.mjpg"/>' % self.headers.get('Host')).encode())
                  self.wfile.write(b'</body></html>')
                  return
      
      class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
          """Handle requests in a separate thread."""
      
      # 启动MJPEG服务
      def mjpeg_server_star():
          global success
          global server
          global thread_mjpeg
      
          try:
              server = ThreadedHTTPServer(('0.0.0.0', MJPEG_SERVER_PORT), CamHandler)
              print("mjpeg server started: http://0.0.0.0:%d" % MJPEG_SERVER_PORT)
              # server.serve_forever()
              thread_mjpeg = Thread(target=server.serve_forever);
              thread_mjpeg.start()
          except KeyboardInterrupt:
              print("mjpeg server stoping...")
              server.socket.close()
              server.shutdown()
              print("mjpeg server stoped")
      
      # websocket服务请求处理
      async def CamTransmitHandler(websocket, path):
          print("Client Connected !")
          try :
              while True:
                  # rc,img = cameraCapture.read()
                  rc,img = success,frame
                  if not rc:
                      continue
      
                  img_fps = JPEG_QUALITY_VALUE
                  img_param = [int(cv2.IMWRITE_JPEG_QUALITY), img_fps]
                  encoded = cv2.imencode('.jpg', img, img_param)[1]
                  data = str(base64.b64encode(encoded))
                  data = data[2:len(data)-1]
                  await websocket.send(data)
      
                  # cv2.imshow("Transimission", frame)
                  # if cv2.waitKey(1) & 0xFF == ord('q'):
                  #     break
              # cap.release()
          except EXCEPTION_CONNECTION_CLOSE as e:
              print("Client Disconnected !")
              # cap.release()
          except:
              print("Someting went Wrong !")
      
      # websocket服务器启动
      def websocket_server_start():
          global thread_ws
          global server_ws
          global event_loop_ws
      
          event_loop_ws = asyncio.new_event_loop()
          def run_server():
              global server_ws
              print("websocket server started: ws://0.0.0.0:%d" % WEBSOCKET_PORT)
              server_ws = websockets.serve(CamTransmitHandler, port=WEBSOCKET_PORT, loop=event_loop_ws)
              event_loop_ws.run_until_complete(server_ws)
              event_loop_ws.run_forever()
      
          thread_ws = Thread(target=run_server)
          thread_ws.start()
          # try:
          #     yield
          # except e:
          #     print("An exception occurred")
          # finally:
          #     event_loop.call_soon_threadsafe(event_loop.stop)
      
      # 获取存储的文件名
      def get_file_name(time_obj, path, ext):
          file_name_time = "%04d-%02d-%02d_%02d-%02d-%02d" % (time_obj["year"], time_obj["month"], time_obj["day"], time_obj["hour"], time_obj["min"], 0)
          return '%s/%s/%s.%s' % (STORE_DIR, path, file_name_time, ext)
      
      # 获取当前整分时间
      def get_current_time():
          time_now = time.localtime()
          time_int = int(time.time())
          return {
              "year": time_now.tm_year,
              "month": time_now.tm_mon,
              "day": time_now.tm_mday,
              "hour": time_now.tm_hour,
              "min": time_now.tm_min,
              "sec": time_now.tm_sec,
              "time": time_int - time_now.tm_sec
          }
      
      # 设置信号回调
      signal.signal(signal.SIGINT, signal_handler)
      signal.signal(signal.SIGTERM, signal_handler)
      
      # 捕获摄像头
      cameraCapture = cv2.VideoCapture(CAMERA_NO)
      
      # 摄像头参数设置
      cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
      cameraCapture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
      cameraCapture.set(cv2.CAP_PROP_SATURATION, 135)
      
      fps = 30
      size=(int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
      
      # 读取捕获的数据
      success,frame = cameraCapture.read()
      
      if not success:
          print("camera start failed.")
          quit()
      
      is_stop = False
      server = None
      server_ws = None
      event_loop_ws = None
      thread_mjpeg = None
      thread_ws = None
      mjpeg_server_star()
      websocket_server_start()
      
      print("record server star:")
      
      thubm_file = None
      video_file = None
      time_start = int(time.time())
      time_record = {"time":0}
      time_record_prev = None
      
      while True:
          if is_stop:
              success = False
              break;
      
          success,frame = cameraCapture.read()
          if not success:
              continue
      
          time_now = get_current_time()
          if time_now["time"] - time_record["time"] >= ROTATE_TIME:
              if time_record_prev:
                  thubm_file = get_file_name(time_record_prev, 'thumbs', 'jpg')
                  print("[Info] write to thumb: %s" % thubm_file)
                  if not os.path.isfile(thubm_file):
                      cv2.imwrite(thubm_file, frame)
      
              time_record = time_now
              time_record_prev = get_current_time()
              video_file = get_file_name(time_record_prev, 'videos', MEDIA_EXT)
              print("[Info] write to video: %s" % video_file)
      
          # encode = cv2.VideoWriter_fourcc(*"mp4v")
          encode = cv2.VideoWriter_fourcc(*'X264')
          # encode = cv2.VideoWriter_fourcc(*'AVC1')
          # encode = cv2.VideoWriter_fourcc(*'XVID')
          # encode = cv2.VideoWriter_fourcc(*'H264')
          videoWriter=cv2.VideoWriter(video_file, encode,fps,size) # mp4
          numFrameRemaining = ROTATE_TIME * fps    #摄像头捕获持续时间
          while success and numFrameRemaining > 0:
              videoWriter.write(frame)
              success,frame = cameraCapture.read()
              numFrameRemaining -= 1
      
      cameraCapture.release()
      

      在上述代码中,除了前面说过的三个部分,还包括启动web和websocket线程的部分。因为核心逻辑为读取视频数据并写入文件,所以其他部分,以线程的模式启动,以便同时进行处理。

      将上述代码保存为DrivingRecorderAndMjpegServer.py,然后运行即可。(依赖包,见代码库中requirements.txt)

      poYBAGMTZ1WAItw5AAOg9WCVryc922.png

      实际访问效果如下:

      poYBAGMTZ2OAA5B3ABgiUZy_8es063.png

      六、历史数据RestFul服务开发

      历史数据服务,本来也可以使用Python直接手写,但考虑到可扩展性,使用Django来进行了编写。

      Djano服务,需要提供如下的功能:

      • 提供api接口,以便获取历史数据记录列表,便于前端界面呈现展示
      • 提供Flutter Web界面代码文件的托管,以便通过浏览器访问
      • 提供静态文件的访问,例如查看历史视频文件

      2和3本质都是一个问题,通过Django的static功能,就能实现。

      也就是在settings.py配置中,提供下面的配置即可:

      STATIC_URL = 'static/'
      
      STATICFILES_DIRS = [
          BASE_DIR / "static"
      ]
      

      1对外提供api服务,则需要设置对应的url接口,以及读取历史文件信息,生成前端需要的json数据结构,这部分的具体代码如下:

      # 媒体文件存放目录,以及缩略图和视频文件的后缀
      THUMB_HOME_DIR = "%s/%s/data/thumbs/" % (BASE_DIR, STATIC_URL)
      VIDEO_HOME_DIR = "%s/%s/data/videos/" % (BASE_DIR, STATIC_URL)
      
      IMG_FILTER = [".jpg"]
      MEDIA_FILTER = [ ".mkv"]
      
      import json
      from django.shortcuts import render, HttpResponse
      from rest_framework.response import Response
      from rest_framework.permissions import AllowAny
      from rest_framework.decorators import api_view, permission_classes
      import os
      from django.conf import settings
      
      THUMB_HOME_DIR = settings.THUMB_HOME_DIR
      VIDEO_HOME_DIR = settings.VIDEO_HOME_DIR
      IMG_FILTER = settings.IMG_FILTER
      MEDIA_FILTER = settings.MEDIA_FILTER
      
      # Create your views here.
      @api_view(['GET'],)
      @permission_classes([AllowAny],)
      def hello_django(request):
          str = '''[
        {
          "id": 1,
          "time": "2022-07-28 21:00",
          "title": "2022-07-28 21:00",
          "body": "videos/2022-07-28_2100.mp4"
        },
        {
          "id": 2,
          "time": "2022-07-28 23:00",
          "title": "2022-07-28 23:00",
          "body": "videos/2022-07-28_2300.mp4"
        },
        {
          "id": 3,
          "time": "2022-07-28 25:00",
          "title": "2022-07-28 25:00",
          "body": "videos/2022-07-28_2500.mp4"
        }
      ]'''
          _json = json.loads(str)
          return HttpResponse(json.dumps(_json), content_type='application/json')
      
      
      @api_view(['GET'],)
      @permission_classes([AllowAny],)
      def history_list(request):
          next = request.GET.get("next", '')
          print(f"thumb next = {next}")
          path = "/".join(request.path.split("/")[3:])
          print(f"thumb request.path= {request.path}")
          print(f"thumb path = {path}")
      
          #print os.listdir(FILE_HOME_DIR+".none/")
          data = {"files":[], "dirs":[]}
          print(data)
          child_path = THUMB_HOME_DIR+next
          print(f"child_path = {child_path}")
          data['cur_dir'] = path+next
          print(data)
          for dir in os.listdir(child_path):
              if os.path.isfile(child_path+"/"+dir):
                  if os.path.splitext(dir)[1] in IMG_FILTER:
                      data['files'].append(dir)
              else:
                  data['dirs'].append(dir)
      
          print(data)
          data['files']=sorted(data['files'])
          data['files'].reverse()
          data['infos'] = []
      
          for i in range(0,len(data['files'])):
              thumb_name = data['files'][i]
              video_name = thumb_name.replace('.jpg', MEDIA_FILTER[0])
              file_time = thumb_name.replace('.jpg', '').replace('_', ' ')
              data['infos'].append(
                {
                  "id": i,
                  "time": file_time,
                  "title": file_time,
                  "body": thumb_name,
                  'thumb': thumb_name, 
                  'video': video_name
                }
              )
          return Response(data['infos'], status = 200)
      

      其中有两个接口:

      hello_django是最开始学习使用的,返回写死的json数据。

      history_list,则是自动遍历缩略图文件夹,获取缩略图文件信息,并生成所需要的json数据格式。

      在对应的代码库文件中,也包含了requirements.txt,其中标明了实际需要的依赖库。

      下载代码,进入manage.py所在的目录后,执行下面的命令即可启动:

      pYYBAGMTagmAdvi-AAEU-8-u8-4912.png

      访问 192.168.1.15:8000/app/hellodjango :

      pYYBAGMTaq-AA0ClAAFIXozvPEg025.png

      访问:History List – Django REST framework

      poYBAGMTasKAWY3ZAAKGge6My1I001.png

      可以看到 history_list接口,已经可以提供实际需要的数据了。

      七、Flutter Web界面开发

      这个部分设计的代码比较多,所以只对关键部分的代码进行说明。

      开发的实际代码,位于lib目录,具体为:

      pYYBAGMTa32AOZqyAAEzENFc2kg639.png

      • globals.dart:全局变量定义
      • main.dart:程序入口
      • home_page.dart:首页
      • live_page.dart:实时播放
      • live_page_mp4.dart:测试播放mp4视频
      • history_page.dart:历史记录列表页面
      • video_detail.dart:单条历史记录详情
      • video_play.dart:播放具体的历史视频
      • video_model.dart:单条记录的数据模型
      • http_service.dart:请求RestFul接口
      • websocket.dart:实时视频的WebSocket请求

      整个界面,使用了Scaffold来模拟手机/Pad的操作界面,具体界面如下:

      poYBAGMTbWyAAzQWAAGRBvXHjAI107.png

      在实时画面界面中,使用了WebSocket监听,获取到信息,就使用Stream模式,推送给视频播放。

      在历史记录界面中,则通过RestFul请求列表数据,然后呈现。

      八、整体运行效果

      实际的运行效果,不用多说,看界面就成:

      实时画面:
      pYYBAGMTblGAc4mAABRLQVukNDU274.png

      历史记录列表:
      poYBAGMTbmOAXSMRAAK9lKwRUWc298.png

      历史记录播放:
      poYBAGMTbnGAYABlABkc5_TtrLw765.png

      九、车试:

      经过反复的测试验证,确保各项功能完整后,进行了上车实测。

      poYBAGMTbtWABcAWAE2YYb8NH3g757.png

      因为最近的疫情原因,所以只在村里转了一圈,进行了实际测试,可以查看最后的视频。后续有机会,再找个晴朗的天气,去环境优美的地方实际拍摄录制。

      十、实际代码说明:

      完整的代码,请通过 米尔行车记录仪: 米尔行车记录仪 (https://gitee.com/honestqiao/MYiR-Driving-Recorder) 获取。

      代码目录说明如下:

      • DrivingRecorder:摄像头服务
      • backend:RestFul服务
      • frontend:Flutter Web界面

      在以上仓库中,包含了详细的代码使用说明。

      在实际应用中,将记录视频的data目录与后端static/data目录关联,以便两者统一。

      十一、感谢

      在研究学习的过程中,参考了数十篇各类资料,先将部分列出如下。对所有学习过的资料的作者,表示深深的感谢。

      janakj/py-mjpeg: Python MJPEG streaming utilities (github.com)
      Simple Python Motion Jpeg (mjpeg server) from webcam. Using: OpenCV,BaseHTTPServer (github.com)
      Python 使用USB Camera录制MP4视频_Frank_Abagnale的博客-CSDN博客
      用 Python、nginx 搭建在线家庭影院 - 知乎 (zhihu.com)
      Django报错解决:RuntimeError: Model class ...apps... doesn't declare an explicit app_label and isn't in a_lyp039078的博客-CSDN博客
      Python OpenCV 调用摄像头并截图保存_Clannad_niu的博客-CSDN博客
      用 Python、nginx 搭建在线家庭影院mob604756e97f09的技术博客51CTO博客
      Python-OpenCV录制H264编码的MP4视频 - 掘金 (juejin.cn)
      [VideoWriter]保存H264/MPEG4格式MP4视频 - image processing (zj-image-processing.readthedocs.io)
      Manual USB camera settings in Linux | KUROKESU
      UVC Web Cameras (indilib.org)
      编写你的第一个 Flutter 网页应用 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
      macOS install | Flutter
      [Django 設定 LANGUAGE_CODE 時所遇到的麻煩] OSError: No translation files found for default language zh-TW. (github.com)**
      Django And Flutter — 样板应用程序|的分步教程作者:Clever Tech Memes |中等 (medium.com)
      joke2k/django-environ: Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application. (github.com)
      django 之跨域访问问题解决 access-control-allow-origin - 腾讯云开发者社区-腾讯云 (tencent.com)
      django-cors-headers · PyPI
      Django项目解决跨域问题 - SegmentFault 思否
      video_player | Flutter Package (pub.dev)
      视频的播放和暂停 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
      5.7 页面骨架(Scaffold) | 《Flutter实战·第二版》 (flutterchina.club)
      itfitness/BottomNavigationBarDemo - 码云 - 开源中国 (gitee.com)
      Flutter底部导航 - 简书 (jianshu.com)
      Flutter之自定义底部导航条以及页面切换实例——Flutter基础系列houruoyu3的博客-CSDN博客flutter 自定义底部导航
      How To Use HTTP Requests in Flutter | DigitalOcean
      在Flutter中发起HTTP网络请求 - Flutter中文网 (flutterchina.club)
      Fetch data from the internet | Flutter
      获取网络数据 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
      深入理解 Function & Closure - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
      Django And Flutter — A Step by Step Tutorial for a Boilerplate Application | by Clever Tech Memes | Medium
      multithreading - Multithreaded web server in python - Stack Overflow
      Simple Python HTTP Server with multi-threading and partial-content support (github.com)
      meska/mjpeg_stream_webcam: Webcam Streamer for Octoprint MacOs (github.com)
      blueimp/mjpeg-server: MJPEG Server implements MJPEG over HTTP using FFmpeg or any other input source capable of piping a multipart JPEG stream to stdout. Its primary use case is providing Webdriver screen recordings. (github.com)
      n3wtron/simple_mjpeg_streamer_http_server: simple python mjpeg streamer http server (github.com)
      Python3远程监控程序实现肥宅Sean的博客-CSDN博客
      opencv imencode跟imdecode函数jpg(python) - PythonTechWorld
      flutter_mjpeg | Flutter Package (pub.dev)
      Can't work on web platform. · Issue #13 · mylisabox/flutter_mjpeg (github.com)
      Consider if fetch is widely supported enough to use · Issue #595 · dart-lang/http (github.com)
      在 Flutter | 中创建实时视频流应用程序作者:Mitrajeet Golsangi |开发人员学生社区 Vishwakarma 技术学院,浦那 |中等 (medium.com)
      Python websockets.serve方法代碼示例 - 純淨天空 (vimsky.com)
      Flutter 常用組件講解 | ImageWidget - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)
      Bad State: Stream has already been listened to. · Issue #29105 · flutter/flutter (github.com)
      flutter - Streambuilder with WebSockets stream in TabBarView: Bad state: Stream has already been listened to - Stack Overflow
      使用WebSockets - Flutter中文网 (flutterchina.club)
      VideoStreaming.dart (github.com)
      在 Flutter | 中创建实时视频流应用程序作者:Mitrajeet Golsangi |开发人员学生社区 Vishwakarma 技术学院,浦那 |中等 (medium.com)
      Flutter:WebSocket封装-实现心跳、重连机制 - 让我留在你身边 (ricardolsw.github.io)
      2.3 状态管理 | 《Flutter实战·第二版》 (flutterchina.club)
      路由和导航 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
      7.6 异步UI更新(FutureBuilder、StreamBuilder) | 《Flutter实战·第二版》 (flutterchina.club)
      Flutter 常用組件講解 | ImageWidget - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)
      Step By Step Tutorial in Learning Flutter: Lesson 12 — Adding Image (Ice Pokemon) | by Misterflutter | Quick Code | Medium
      Django CORS on static asset - Stack Overflow
      配置 | Django 文档 | Django (djangoproject.com)
      Global Variables in Dart - Stack Overflow
      UVC - Community Help Wiki (ubuntu.com)
      利用OpenCV进行H264视频编码的简易方式 - 知乎 (zhihu.com)
      Documentation for OPENCV_FFMPEG_WRITER_OPTIONS and OPENCV_FFMPEG_CAPTURE_OPTIONS · Issue #21155 · opencv/opencv (github.com)
      利用OpenCV进行H264视频编码的简易方式 - 知乎 (zhihu.com)
      FFmpeg概述及编码支持 - 知乎 (zhihu.com)
      Web 渲染器 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

      十二、总结

      在研究学习的过程中,对Linux系统下的UVC框架有了进一步的了解,对Flutter进行应用开发有了实际的了解,对OpenCV的实际应用也有了具体的了解。

      在实际开发的过程中,遇到的最大的坑来自Flutter,因为变化太快,有一些功能可能兼容性没有跟上。不过更多是自己学艺不精导致的。

      另外,目前还只是V1.0版本,后续还存在较大的优化空间。例如对于OpenCV的应用,可以调整参数,优化获取的视频数据的指令和大小等。这些有待于进一步学习后进行。

      最主要的,对米尔MYD-YT507开发板有了深入的了解,进行了实际的应用。作为一款车规级处理器T507的开发板,名不虚传!

      原文链接:https://bbs.elecfans.com/jishu_2303715_1_1.html

      发布在 其它全志芯片讨论区
      B
      bigfly
    • sipeed的maixsense在arecord里看不到音频设备是什么原因呢

      QQ图片20220908112428.jpg

      armbian下现在用arecord -l命令找不到音频设备,难道应该重新刷下系统?

      发布在 A Series
      B
      bigfly
    • 1 / 1