G2D图像处理硬件调用和测试-基于米尔-全志T113-i开发板

米尔电子嵌入式 2024-04-08 08:01

本篇测评由电子工程世界的优秀测评者“jf_99374259”提供。


本文将介绍基于米尔电子MYD-YT113i开发板的G2D图像处理硬件调用和测试。

MYC-YT113i核心板及开发板

真正的国产核心板,100%国产物料认证
  • 国产T113-i处理器配备2*Cortex-A7@1.2GHz ,RISC-V

  • 外置DDR3接口、支持视频编解码器、HiFi4 DSP

  • 接口丰富:视频采集接口、显示器接口、USB2.0 接口、CAN 接口、千兆以太网接口

  • 工业级:-40℃~+85℃、尺寸37mm*39mm

  • 邮票孔+LGA,140+50PIN

全志 T113-i 2D图形加速硬件支持情况

  • Supports layer size up to 2048 x 2048 pixels

  • Supports pre-multiply alpha image data

  • Supports color key

  • Supports two pipes Porter-Duff alpha blending

  • Supports multiple video formats 4:2:0, 4:2:2, 4:1:1 and multiple pixel formats (8/16/24/32 bits graphics
    layer)

  • Supports memory scan order option

  • Supports any format convert function

  • Supports 1/16× to 32× resize ratio

  • Supports 32-phase 8-tap horizontal anti-alias filter and 32-phase 4-tap vertical anti-alias filter

  • Supports window clip

  • Supports FillRectangle, BitBlit, StretchBlit and MaskBlit

  • Supports horizontal and vertical flip, clockwise 0/90/180/270 degree rotate for normal buffer

  • Supports horizontal flip, clockwise 0/90/270 degree rotate for LBC buffer

可以看到 g2d 硬件支持相当多的2D图像处理,包括颜色空间转换,分辨率缩放,图层叠加,旋转等

开发环境配置

基础开发环境搭建参考上上上一篇
https://bbs.elecfans.com/jishu_2408808_1_1.html
除了工具链外,我们使用 opencv-mobile 加载输入图片和保存结果,用来查看颜色转换是否正常
g2d硬件直接采用标准的 Linux ioctl 操纵,只需要引入相关结构体定义即可,无需链接so
https://github.com/MYIR-ALLWINNER/framework/blob/develop-yt113-framework/auto/sdk_lib/include/g2d_driver.h
此外,g2d的输入和输出数据必须在dmaion buffer上,因此还需要dmaion.h头文件,用来分配和释放dmaion buffer
https://github.com/MYIR-ALLWINNER/framework/blob/develop-yt113-framework/auto/sdk_lib/include/DmaIon.h

基于C语言实现的YUV转RGB

这里复用之前T113-i JPG解码的函数
void yuv420sp2rgb(const unsigned char* yuv420sp, int w, int h, unsigned char* rgb){    const unsigned char* yptr = yuv420sp;    const unsigned char* vuptr = yuv420sp + w * h;
for (int y = 0; y < h; y += 2) { const unsigned char* yptr0 = yptr; const unsigned char* yptr1 = yptr + w; unsigned char* rgb0 = rgb; unsigned char* rgb1 = rgb + w * 3;
int remain = w;
#define SATURATE_CAST_UCHAR(X) (unsigned char)::std::min(::std::max((int)(X), 0), 255); for (; remain > 0; remain -= 2) { // R = 1.164 * yy + 1.596 * vv // G = 1.164 * yy - 0.813 * vv - 0.391 * uu // B = 1.164 * yy + 2.018 * uu
// R = Y + (1.370705 * (V-128)) // G = Y - (0.698001 * (V-128)) - (0.337633 * (U-128)) // B = Y + (1.732446 * (U-128))
// R = ((Y << 6) + 87.72512 * (V-128)) >> 6 // G = ((Y << 6) - 44.672064 * (V-128) - 21.608512 * (U-128)) >> 6 // B = ((Y << 6) + 110.876544 * (U-128)) >> 6
// R = ((Y << 6) + 90 * (V-128)) >> 6 // G = ((Y << 6) - 46 * (V-128) - 22 * (U-128)) >> 6 // B = ((Y << 6) + 113 * (U-128)) >> 6
// R = (yy + 90 * vv) >> 6 // G = (yy - 46 * vv - 22 * uu) >> 6 // B = (yy + 113 * uu) >> 6
int v = vuptr[0] - 128; int u = vuptr[1] - 128;
int ruv = 90 * v; int guv = -46 * v + -22 * u; int buv = 113 * u;
int y00 = yptr0[0] << 6; rgb0[0] = SATURATE_CAST_UCHAR((y00 + ruv) >> 6); rgb0[1] = SATURATE_CAST_UCHAR((y00 + guv) >> 6); rgb0[2] = SATURATE_CAST_UCHAR((y00 + buv) >> 6);
int y01 = yptr0[1] << 6; rgb0[3] = SATURATE_CAST_UCHAR((y01 + ruv) >> 6); rgb0[4] = SATURATE_CAST_UCHAR((y01 + guv) >> 6); rgb0[5] = SATURATE_CAST_UCHAR((y01 + buv) >> 6);
int y10 = yptr1[0] << 6; rgb1[0] = SATURATE_CAST_UCHAR((y10 + ruv) >> 6); rgb1[1] = SATURATE_CAST_UCHAR((y10 + guv) >> 6); rgb1[2] = SATURATE_CAST_UCHAR((y10 + buv) >> 6);
int y11 = yptr1[1] << 6; rgb1[3] = SATURATE_CAST_UCHAR((y11 + ruv) >> 6); rgb1[4] = SATURATE_CAST_UCHAR((y11 + guv) >> 6); rgb1[5] = SATURATE_CAST_UCHAR((y11 + buv) >> 6);
yptr0 += 2; yptr1 += 2; vuptr += 2; rgb0 += 6; rgb1 += 6; }#undef SATURATE_CAST_UCHAR
yptr += 2 * w; rgb += 2 * 3 * w; }}

基于ARM neon指令集优化的YUV转RGB

考虑到armv7编译器的自动neon优化能力较差,这里针对性的编写 arm neon inline assembly 实现YUV2RGB内核部分,达到最优化的性能,榨干cpu性能

void yuv420sp2rgb_neon(const unsigned char* yuv420sp, int w, int h, unsigned char* rgb){    const unsigned char* yptr = yuv420sp;    const unsigned char* vuptr = yuv420sp + w * h;
#if __ARM_NEON uint8x8_t _v128 = vdup_n_u8(128); int8x8_t _v90 = vdup_n_s8(90); int8x8_t _v46 = vdup_n_s8(46); int8x8_t _v22 = vdup_n_s8(22); int8x8_t _v113 = vdup_n_s8(113);#endif // __ARM_NEON
for (int y = 0; y < h; y += 2) { const unsigned char* yptr0 = yptr; const unsigned char* yptr1 = yptr + w; unsigned char* rgb0 = rgb; unsigned char* rgb1 = rgb + w * 3;
#if __ARM_NEON int nn = w >> 3; int remain = w - (nn << 3);#else int remain = w;#endif // __ARM_NEON
#if __ARM_NEON#if __aarch64__ for (; nn > 0; nn--) { int16x8_t _yy0 = vreinterpretq_s16_u16(vshll_n_u8(vld1_u8(yptr0), 6)); int16x8_t _yy1 = vreinterpretq_s16_u16(vshll_n_u8(vld1_u8(yptr1), 6));
int8x8_t _vvuu = vreinterpret_s8_u8(vsub_u8(vld1_u8(vuptr), _v128)); int8x8x2_t _vvvvuuuu = vtrn_s8(_vvuu, _vvuu); int8x8_t _vv = _vvvvuuuu.val[0]; int8x8_t _uu = _vvvvuuuu.val[1];
int16x8_t _r0 = vmlal_s8(_yy0, _vv, _v90); int16x8_t _g0 = vmlsl_s8(_yy0, _vv, _v46); _g0 = vmlsl_s8(_g0, _uu, _v22); int16x8_t _b0 = vmlal_s8(_yy0, _uu, _v113);
int16x8_t _r1 = vmlal_s8(_yy1, _vv, _v90); int16x8_t _g1 = vmlsl_s8(_yy1, _vv, _v46); _g1 = vmlsl_s8(_g1, _uu, _v22); int16x8_t _b1 = vmlal_s8(_yy1, _uu, _v113);
uint8x8x3_t _rgb0; _rgb0.val[0] = vqshrun_n_s16(_r0, 6); _rgb0.val[1] = vqshrun_n_s16(_g0, 6); _rgb0.val[2] = vqshrun_n_s16(_b0, 6);
uint8x8x3_t _rgb1; _rgb1.val[0] = vqshrun_n_s16(_r1, 6); _rgb1.val[1] = vqshrun_n_s16(_g1, 6); _rgb1.val[2] = vqshrun_n_s16(_b1, 6);
vst3_u8(rgb0, _rgb0); vst3_u8(rgb1, _rgb1);
yptr0 += 8; yptr1 += 8; vuptr += 8; rgb0 += 24; rgb1 += 24; }#else if (nn > 0) { asm volatile( "0: \n" "pld [%3, #128] \n" "vld1.u8 {d2}, [%3]! \n" "vsub.s8 d2, d2, %12 \n" "pld [%1, #128] \n" "vld1.u8 {d0}, [%1]! \n" "pld [%2, #128] \n" "vld1.u8 {d1}, [%2]! \n" "vshll.u8 q2, d0, #6 \n" "vorr d3, d2, d2 \n" "vshll.u8 q3, d1, #6 \n" "vorr q9, q2, q2 \n" "vtrn.s8 d2, d3 \n" "vorr q11, q3, q3 \n" "vmlsl.s8 q9, d2, %14 \n" "vorr q8, q2, q2 \n" "vmlsl.s8 q11, d2, %14 \n" "vorr q10, q3, q3 \n" "vmlal.s8 q8, d2, %13 \n" "vmlal.s8 q2, d3, %16 \n" "vmlal.s8 q10, d2, %13 \n" "vmlsl.s8 q9, d3, %15 \n" "vmlal.s8 q3, d3, %16 \n" "vmlsl.s8 q11, d3, %15 \n" "vqshrun.s16 d24, q8, #6 \n" "vqshrun.s16 d26, q2, #6 \n" "vqshrun.s16 d4, q10, #6 \n" "vqshrun.s16 d25, q9, #6 \n" "vqshrun.s16 d6, q3, #6 \n" "vqshrun.s16 d5, q11, #6 \n" "subs %0, #1 \n" "vst3.u8 {d24-d26}, [%4]! \n" "vst3.u8 {d4-d6}, [%5]! \n" "bne 0b \n" : "=r"(nn), // %0 "=r"(yptr0), // %1 "=r"(yptr1), // %2 "=r"(vuptr), // %3 "=r"(rgb0), // %4 "=r"(rgb1) // %5 : "0"(nn), "1"(yptr0), "2"(yptr1), "3"(vuptr), "4"(rgb0), "5"(rgb1), "w"(_v128), // %12 "w"(_v90), // %13 "w"(_v46), // %14 "w"(_v22), // %15 "w"(_v113) // %16 : "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "d26"); }#endif // __aarch64__#endif // __ARM_NEON
#define SATURATE_CAST_UCHAR(X) (unsigned char)::std::min(::std::max((int)(X), 0), 255); for (; remain > 0; remain -= 2) { // R = 1.164 * yy + 1.596 * vv // G = 1.164 * yy - 0.813 * vv - 0.391 * uu // B = 1.164 * yy + 2.018 * uu
// R = Y + (1.370705 * (V-128)) // G = Y - (0.698001 * (V-128)) - (0.337633 * (U-128)) // B = Y + (1.732446 * (U-128))
// R = ((Y << 6) + 87.72512 * (V-128)) >> 6 // G = ((Y << 6) - 44.672064 * (V-128) - 21.608512 * (U-128)) >> 6 // B = ((Y << 6) + 110.876544 * (U-128)) >> 6
// R = ((Y << 6) + 90 * (V-128)) >> 6 // G = ((Y << 6) - 46 * (V-128) - 22 * (U-128)) >> 6 // B = ((Y << 6) + 113 * (U-128)) >> 6
// R = (yy + 90 * vv) >> 6 // G = (yy - 46 * vv - 22 * uu) >> 6 // B = (yy + 113 * uu) >> 6
int v = vuptr[0] - 128; int u = vuptr[1] - 128;
int ruv = 90 * v; int guv = -46 * v + -22 * u; int buv = 113 * u;
int y00 = yptr0[0] << 6; rgb0[0] = SATURATE_CAST_UCHAR((y00 + ruv) >> 6); rgb0[1] = SATURATE_CAST_UCHAR((y00 + guv) >> 6); rgb0[2] = SATURATE_CAST_UCHAR((y00 + buv) >> 6);
int y01 = yptr0[1] << 6; rgb0[3] = SATURATE_CAST_UCHAR((y01 + ruv) >> 6); rgb0[4] = SATURATE_CAST_UCHAR((y01 + guv) >> 6); rgb0[5] = SATURATE_CAST_UCHAR((y01 + buv) >> 6);
int y10 = yptr1[0] << 6; rgb1[0] = SATURATE_CAST_UCHAR((y10 + ruv) >> 6); rgb1[1] = SATURATE_CAST_UCHAR((y10 + guv) >> 6); rgb1[2] = SATURATE_CAST_UCHAR((y10 + buv) >> 6);
int y11 = yptr1[1] << 6; rgb1[3] = SATURATE_CAST_UCHAR((y11 + ruv) >> 6); rgb1[4] = SATURATE_CAST_UCHAR((y11 + guv) >> 6); rgb1[5] = SATURATE_CAST_UCHAR((y11 + buv) >> 6);
yptr0 += 2; yptr1 += 2; vuptr += 2; rgb0 += 6; rgb1 += 6; }#undef SATURATE_CAST_UCHAR
yptr += 2 * w; rgb += 2 * 3 * w; }}

基于G2D图形硬件的YUV转RGB

我们先实现 dmaion buffer 管理器,参考

https://github.com/MYIR-ALLWINNER/framework/blob/develop-yt113-framework/auto/sdk_lib/sdk_memory/DmaIon.cpp

这里贴的代码省略了异常错误处理的逻辑,有个坑是 linux-4.9 和 linux-5.4 用法不一样,米尔电子的这个T113-i系统是linux-5.4,所以不兼容4.9内核的ioctl用法习惯

struct ion_memory{    size_t size;    int fd;    void* virt_addr;    unsigned int phy_addr;};
class ion_allocator{public: ion_allocator(); ~ion_allocator();
int open(); void close();
int alloc(size_t size, struct ion_memory* mem); int free(struct ion_memory* mem);
int flush(struct ion_memory* mem);
public: int ion_fd; int cedar_fd;};
ion_allocator::ion_allocator(){ ion_fd = -1; cedar_fd = -1;}
ion_allocator::~ion_allocator(){ close();}
int ion_allocator::open(){ close();
ion_fd = ::open("/dev/ion", O_RDWR); cedar_fd = ::open("/dev/cedar_dev", O_RDONLY);
ioctl(cedar_fd, IOCTL_ENGINE_REQ, 0);
return 0;}
void ion_allocator::close(){ if (cedar_fd != -1) { ioctl(cedar_fd, IOCTL_ENGINE_REL, 0); ::close(cedar_fd); cedar_fd = -1; }
if (ion_fd != -1) { ::close(ion_fd); ion_fd = -1; }}
int ion_allocator::alloc(size_t size, struct ion_memory* mem){ struct aw_ion_new_alloc_data alloc_data; alloc_data.len = size; alloc_data.heap_id_mask = AW_ION_SYSTEM_HEAP_MASK; alloc_data.flags = AW_ION_CACHED_FLAG | AW_ION_CACHED_NEEDS_SYNC_FLAG; alloc_data.fd = 0; alloc_data.unused = 0; ioctl(ion_fd, AW_ION_IOC_NEW_ALLOC, &alloc_data);
void* virt_addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, alloc_data.fd, 0);
struct aw_user_iommu_param iommu_param; iommu_param.fd = alloc_data.fd; iommu_param.iommu_addr = 0; ioctl(cedar_fd, IOCTL_GET_IOMMU_ADDR, &iommu_param);
mem->size = size; mem->fd = alloc_data.fd; mem->virt_addr = virt_addr; mem->phy_addr = iommu_param.iommu_addr;
return 0;}
int ion_allocator::free(struct ion_memory* mem){ if (mem->fd == -1) return 0;
struct aw_user_iommu_param iommu_param; iommu_param.fd = mem->fd; ioctl(cedar_fd, IOCTL_FREE_IOMMU_ADDR, &iommu_param);
munmap(mem->virt_addr, mem->size);
::close(mem->fd);
mem->size = 0; mem->fd = -1; mem->virt_addr = 0; mem->phy_addr = 0;
return 0;}
int ion_allocator::flush(struct ion_memory* mem){ struct dma_buf_sync sync; sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW; ioctl(mem->fd, DMA_BUF_IOCTL_SYNC, &sync);
return 0;}

然后再实现 G2D图形硬件 YUV转RGB 的转换器

  1. 提前分配好YUV和RGB的dmaion buffer

  2. 将YUV数据拷贝到dmaion buffer,flush cache完成同步

  3. 配置转换参数,ioctl调用G2D_CMD_BITBLT_H完成转换

  4. flush cache完成同步,从dmaion buffer拷贝出RGB数据

  5. 释放dmaion buffer

// 步骤1ion_allocator ion;ion.open();
struct ion_memory yuv_ion;ion.alloc(rgb_size, &rgb_ion);
struct ion_memory rgb_ion;ion.alloc(yuv_size, &yuv_ion);
int g2d_fd = ::open("/dev/g2d", O_RDWR);
// 步骤2memcpy((unsigned char*)yuv_ion.virt_addr, yuv420sp, yuv_size);ion.flush(&yuv_ion);
// 步骤3g2d_blt_h blit;memset(&blit, 0, sizeof(blit));
blit.flag_h = G2D_BLT_NONE_H;
blit.src_image_h.format = G2D_FORMAT_YUV420UVC_V1U1V0U0;blit.src_image_h.width = width;blit.src_image_h.height = height;blit.src_image_h.align[0] = 0;blit.src_image_h.align[1] = 0;blit.src_image_h.clip_rect.x = 0;blit.src_image_h.clip_rect.y = 0;blit.src_image_h.clip_rect.w = width;blit.src_image_h.clip_rect.h = height;blit.src_image_h.gamut = G2D_BT601;blit.src_image_h.bpremul = 0;blit.src_image_h.mode = G2D_PIXEL_ALPHA;blit.src_image_h.use_phy_addr = 0;blit.src_image_h.fd = yuv_ion.fd;
blit.dst_image_h.format = G2D_FORMAT_RGB888;blit.dst_image_h.width = width;blit.dst_image_h.height = height;blit.dst_image_h.align[0] = 0;blit.dst_image_h.clip_rect.x = 0;blit.dst_image_h.clip_rect.y = 0;blit.dst_image_h.clip_rect.w = width;blit.dst_image_h.clip_rect.h = height;blit.dst_image_h.gamut = G2D_BT601;blit.dst_image_h.bpremul = 0;blit.dst_image_h.mode = G2D_PIXEL_ALPHA;blit.dst_image_h.use_phy_addr = 0;blit.dst_image_h.fd = rgb_ion.fd;
ioctl(g2d_fd, G2D_CMD_BITBLT_H, &blit);
// 步骤4ion.flush(&rgb_ion);memcpy(rgb, (const unsigned char*)rgb_ion.virt_addr, rgb_size);
// 步骤5ion.free(&rgb_ion);ion.free(&yuv_ion);ion.close();::close(g2d_fd);

G2D图像硬件YUV转RGB测试

考虑到dmaion buffer分配和释放都比较耗时,我们提前做好,循环调用步骤3的G2D转换,统计耗时,并在top工具中查看CPU占用率

sh-4.4# LD_LIBRARY_PATH=. ./g2dtestINFO   : cedarc : register mjpeg decoder success!this device is not whitelisted for jpeg decoder cvithis device is not whitelisted for jpeg decoder cvithis device is not whitelisted for jpeg decoder cvithis device is not whitelisted for jpeg encoder rkmppINFO   : cedarc : Set log level to 5 from /vendor/etc/cedarc.confERROR  : cedarc : now cedarc log level:5ERROR  : cedarc : now cedarc log level:5yuv420sp2rgb 46.61yuv420sp2rgb 42.04yuv420sp2rgb 41.32yuv420sp2rgb 42.06yuv420sp2rgb 41.69yuv420sp2rgb 42.05yuv420sp2rgb 41.29yuv420sp2rgb 41.30yuv420sp2rgb 42.14yuv420sp2rgb 41.33yuv420sp2rgb_neon 10.57yuv420sp2rgb_neon 7.21yuv420sp2rgb_neon 6.77yuv420sp2rgb_neon 8.31yuv420sp2rgb_neon 7.60yuv420sp2rgb_neon 6.80yuv420sp2rgb_neon 6.77yuv420sp2rgb_neon 7.01yuv420sp2rgb_neon 7.11yuv420sp2rgb_neon 7.06yuv420sp2rgb_g2d 4.32yuv420sp2rgb_g2d 4.69yuv420sp2rgb_g2d 4.56yuv420sp2rgb_g2d 4.57yuv420sp2rgb_g2d 4.52yuv420sp2rgb_g2d 4.54yuv420sp2rgb_g2d 4.52yuv420sp2rgb_g2d 4.58yuv420sp2rgb_g2d 4.60yuv420sp2rgb_g2d 4.67

可以看到 ARM neon 的优化效果非常明显,而使用G2D图形硬件能获得进一步加速,并且能显著降低CPU占用率!


耗时(ms)CPU占用率(%)
C41.3050
neon6.7750
g2d4.3212

转换结果对比和分析

C和neon的转换结果完全一致,但是g2d转换后的图片有明显的色差

G2D图形硬件只支持 G2D_BT601,G2D_BT709,G2D_BT2020 3种YUV系数,而JPG所使用的YUV系数是改版BT601,因此产生了色差

https://github.com/MYIR-ALLWINNER/myir-t1-kernel/blob/develop-yt113-L5.4.61/drivers/char/sunxi_g2d/g2d_bsp_v2.c

从g2d内核驱动中也可以得知,暂时没有方法为g2d设置自定义的YUV系数,g2d不适合用于JPG的编解码,但依然适合摄像头和视频编解码的颜色空间转换

米尔电子最新“明星产品”速报



 米尔电子 
领先的嵌入式处理器模块厂商
关注“米尔MYiR”公众号
不定期分享产品资料及干货
第一时间发布米尔最新资讯

  

长按二维码 关注我们


想要了解更多信息,欢迎联系我们

深圳总部电话:
0755-25622735 17324413392
地址:深圳坂田云里智能园2栋6楼
上海办事处电话:
021-62087019 17324413392
北京办事处电话:
010-84675491 13316862895
技术支持电话:
027-59621648
邮箱:support.cn@myirtech.com

米尔电子嵌入式 米尔-领先的嵌入式处理器模组厂商,专业为您提供CPU模组,NXP、ST、全志、XILINX等核心板开
评论 (0)
  • 在海洋监测领域,基于无人艇能够实现高效、实时、自动化的海洋数据采集,从而为海洋环境保护、资源开发等提供有力支持。其中,无人艇的控制算法训练往往需要大量高质量的数据支持。然而,海洋数据采集也面临数据噪声和误差、数据融合与协同和复杂海洋环境适应等诸多挑战,制约着无人艇技术的发展。针对这些挑战,我们探索并推出一套基于多传感器融合的海洋数据采集系统,能够高效地采集和处理海洋环境中的多维度数据,为无人艇的自主航行和控制算法训练提供高质量的数据支持。一、方案架构无人艇要在复杂海上环境中实现自主导航,尤其是完
    康谋 2025-03-13 09:53 52浏览
  • 引言汽车行业正经历一场巨变。随着电动汽车、高级驾驶辅助系统(ADAS)和自动驾驶技术的普及,电子元件面临的要求从未如此严格。在这些复杂系统的核心,存在着一个看似简单却至关重要的元件——精密电阻。贞光科技代理品牌光颉科技的电阻选型过程,特别是在精度要求高达 0.01% 的薄膜和厚膜技术之间的选择,已成为全球汽车工程师的关键决策点。当几毫欧姆的差异可能影响传感器的灵敏度或控制系统的精确性时,选择正确的电阻不仅仅是满足规格的问题——它关系到车辆在极端条件下的安全性、可靠性和性能。在这份全面指南中,我们
    贞光科技 2025-03-12 17:25 103浏览
  • 本文介绍OpenHarmony4.1系统开发板,出现打不开WiFi和蓝牙的问题排查和解决方法。触觉智能Purple Pi OH鸿蒙开发板演示,搭载了瑞芯微RK3566四核处理器,1TOPS算力NPU;Laval鸿蒙社区推荐并通过了开源鸿蒙XTS认证,成功适配OpenHarmony3.2、4.0、4.1、5.0 Release系统,SDK源码全开放!WiFi打不开缺少WiFi固件在WiFi打不开时我们可以通过使用串口工具查看WiFi打印信息:这条log主要说明了打开固件文件失败,说明了在/vend
    Industio_触觉智能 2025-03-12 14:32 55浏览
  • 文/Leon编辑/cc孙聪颖作为全球AI领域的黑马,DeepSeek成功搅乱了中国AI大模型市场的格局。科技大厂们选择合作,接入其模型疯抢用户;而AI独角兽们则陷入两难境地,上演了“Do Or Die”的抉择。其中,有着“大模型六小虎”之称的六家AI独角兽公司(智谱AI、百川智能、月之暗面、MiniMax、阶跃星辰及零一万物),纷纷开始转型:2025年伊始,李开复的零一万物宣布转型,不再追逐超大模型,而是聚焦AI商业化应用;紧接着,消息称百川智能放弃B端金融市场,聚焦AI医疗;月之暗面开始削减K
    华尔街科技眼 2025-03-12 17:37 171浏览
  • 2025年,科技浪潮汹涌澎湃的当下,智能数字化变革正进行得如火如荼,从去年二季度开始,触觉智能RK3562核心板上市以来,受到了火爆的关注,上百家客户选用了此方案,也获得了众多的好评与认可,为客户的降本增效提供了广阔的空间。随着原厂的更新,功能也迎来了一波重大的更新,无论是商业级(RK3562)还是工业级(RK3562J),都可支持NPU和2×CAN,不再二选一。我们触觉智能做了一个艰难又大胆的决定,为大家带来两大重磅福利,请继续往下看~福利一:RK3562核心板149元特惠再续,支持2×CAN
    Industio_触觉智能 2025-03-12 14:45 30浏览
  • 前言在快速迭代的科技浪潮中,汽车电子技术的飞速发展不仅重塑了行业的面貌,也对测试工具提出了更高的挑战与要求。作为汽车电子测试领域的先锋,TPT软件始终致力于为用户提供高效、精准、可靠的测试解决方案。新思科技出品的TPT软件迎来了又一次重大更新,最新版本TPT 2024.12将进一步满足汽车行业日益增长的测试需求,推动汽车电子技术的持续革新。基于当前汽车客户的实际需求与痛点,结合最新的技术趋势,对TPT软件进行了全面的优化与升级。从模型故障注入测试到服务器函数替代C代码函数,从更准确的需求链接到P
    北汇信息 2025-03-13 14:43 54浏览
  • 在追求更快、更稳的无线通信路上,传统射频架构深陷带宽-功耗-成本的“不可能三角”:带宽每翻倍,系统复杂度与功耗增幅远超线性增长。传统方案通过“分立式功放+多级变频链路+JESD204B 接口”的组合试图平衡性能与成本,却难以满足实时性严苛的超大规模 MIMO 通信等场景需求。在此背景下,AXW49 射频开发板以“直采+异构”重构射频范式:基于 AMD Zynq UltraScale+™ RFSoC Gen3XCZU49DR 芯片的 16 通道 14 位 2.5GSPS ADC 与 16
    ALINX 2025-03-13 09:27 37浏览
  •        随着人工智能算力集群的爆发式增长,以及5.5G/6G通信技术的演进,网络数据传输速率的需求正以每年30%的速度递增。万兆以太网(10G Base-T)作为支撑下一代数据中心、高端交换机的核心组件,其性能直接决定了网络设备的稳定性与效率。然而,万兆网络变压器的技术门槛极高:回波损耗需低于-20dB(比千兆产品严格30%),耐压值需突破1500V(传统产品仅为1000V),且需在高频信号下抑制电磁干扰。全球仅有6家企业具备规模化量产能力,而美信科
    中科领创 2025-03-13 11:24 48浏览
  • 一、行业背景与需求痛点智能电子指纹锁作为智能家居的核心入口,近年来市场规模持续增长,用户对产品的功能性、安全性和设计紧凑性提出更高要求:极致空间利用率:锁体内部PCB空间有限,需高度集成化设计。语音交互需求:操作引导(如指纹识别状态、低电量提醒)、安全告警(防撬、试错报警)等语音反馈。智能化扩展能力:集成传感器以增强安全性(如温度监测、防撬检测)和用户体验。成本与可靠性平衡:在复杂环境下确保低功耗、高稳定性,同时控制硬件成本。WTV380-P(QFN32)语音芯片凭借4mm×4mm超小封装、多传
    广州唯创电子 2025-03-13 09:24 46浏览
  • 文/杜杰编辑/cc孙聪颖‍主打影像功能的小米15 Ultra手机,成为2025开年的第一款旗舰机型。从发布节奏上来看,小米历代Ultra机型,几乎都选择在开年发布,远远早于其他厂商秋季主力机型的发布时间。这毫无疑问会掀起“Ultra旗舰大战”,今年影像手机将再次被卷上新高度。无意臆断小米是否有意“领跑”一场“军备竞赛”,但各种复杂的情绪难以掩盖。岁岁年年机不同,但将2-3年内记忆中那些关于旗舰机的发布会拼凑起来,会发现,包括小米在内,旗舰机的革新点,除了摄影参数的不同,似乎没什么明显变化。贵为旗
    华尔街科技眼 2025-03-13 12:30 73浏览
  • 北京时间3月11日,国内领先的二手消费电子产品交易和服务平台万物新生(爱回收)集团(纽交所股票代码:RERE)发布2024财年第四季度和全年业绩报告。财报显示,2024年第四季度万物新生集团总收入48.5亿元,超出业绩指引,同比增长25.2%。单季non-GAAP经营利润1.3亿元(non-GAAP口径,即经调整口径,均不含员工股权激励费用、无形资产摊销及因收购产生的递延成本,下同),并汇报创历史新高的GAAP净利润7742万元,同比增长近27倍。总览全年,万物新生总收入同比增长25.9%达到1
    华尔街科技眼 2025-03-13 12:23 56浏览
  • DeepSeek自成立之初就散发着大胆创新的气息。明明核心开发团队只有一百多人,却能以惊人的效率实现许多大厂望尘莫及的技术成果,原因不仅在于资金或硬件,而是在于扁平架构携手塑造的蜂窝创新生态。创办人梁文锋多次强调,与其与大厂竞争一时的人才风潮,不如全力培养自家的优质员工,形成不可替代的内部生态。正因这样,他对DeepSeek内部人才体系有着一套别具一格的见解。他十分重视中式教育价值,因而DeepSeek团队几乎清一色都是中国式学霸。许多人来自北大清华,或者在各种数据比赛中多次获奖,可谓百里挑一。
    优思学院 2025-03-13 12:15 56浏览
  • 一、行业背景与用户需求随着健康消费升级,智能眼部按摩仪逐渐成为缓解眼疲劳、改善睡眠的热门产品。用户对这类设备的需求不再局限于基础按摩功能,而是追求更智能化、人性化的体验,例如:语音交互:实时反馈按摩模式、操作提示、安全提醒。环境感知:通过传感器检测佩戴状态、温度、压力等,提升安全性与舒适度。低功耗长续航:适应便携场景,延长设备使用时间。高性价比方案:在控制成本的同时实现功能多样化。针对这些需求,WTV380-8S语音芯片凭借其高性能、多传感器扩展能力及超高性价比,成为眼部按摩仪智能化升级的理想选
    广州唯创电子 2025-03-13 09:26 36浏览
  • 曾经听过一个“隐形经理”的故事:有家公司,新人进来后,会惊讶地发现老板几乎从不在办公室。可大家依旧各司其职,还能在关键时刻自发协作,把项目完成得滴水不漏。新员工起初以为老板是“放羊式”管理,结果去茶水间和老员工聊过才发现,这位看似“隐形”的管理者其实“无处不在”,他提前铺好了企业文化、制度和激励机制,让一切运行自如。我的观点很简单:管理者的最高境界就是——“无为而治”。也就是说,你的存在感不需要每天都凸显,但你的思路、愿景、机制早已渗透到组织血液里。为什么呢?因为真正高明的管理,不在于事必躬亲,
    优思学院 2025-03-12 18:24 84浏览
  • 本文介绍Android系统主板应用配置默认获取管理所有文件权限方法,基于触觉智能SBC3588行业主板演示,搭载了瑞芯微RK3588芯片,八核处理器,6T高算力NPU;音视频接口、通信接口等各类接口一应俱全,支持安卓Android、Linux、开源鸿蒙OpenHarmony、银河麒麟Kylin等操作系统。配置前提在配置前,建议先将应用配置成系统应用,不然配置后系统每次重启后都会弹窗提示是否获取权限。应用配置成系统应用,可参考以下链接方法:瑞芯微开发板/主板Android系统APK签名文件使用方法
    Industio_触觉智能 2025-03-12 14:34 54浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦