riscv在rt-smart中的板级初始化

RTThread物联网操作系统 2023-02-07 21:07

本文章的代码来自于rt-smart中针对qemu-virt-riscv的bsp

仓库地址 https://gitee.com/rtthread/rt-thread/tree/rt-smart/

commit ID:d28249c08a152bcf0e1a076cf5b4b082c0a84add

qemu-virt-riscv介绍

简介

Virt板不对应于任何真实硬件的平台;它是为虚拟机设计的。如果你只是想运行Linux等客户机,而不关心重现真实世界硬件的特殊性和局限性,那么它是推荐的板卡类型。(摘自https://www.qemu.org/docs/master/system/riscv/virt.html)

内存空间布局(包括外设地址)

static const MemMapEntry virt_memmap[] = {
    [VIRT_DEBUG] =       {        0x0,         0x100 },
    [VIRT_MROM] =        {     0x1000,        0xf000 },
    [VIRT_TEST] =        {   0x100000,        0x1000 },
    [VIRT_RTC] =         {   0x101000,        0x1000 },
    [VIRT_CLINT] =       {  0x2000000,       0x10000 },
    [VIRT_ACLINT_SSWI] = {  0x2F00000,        0x4000 },
    [VIRT_PCIE_PIO] =    {  0x3000000,       0x10000 },
    [VIRT_PLIC] =        {  0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, 
    [VIRT_APLIC_M] =     {  0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) },
    [VIRT_APLIC_S] =     {  0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) },
    [VIRT_UART0] =       { 0x10000000,         0x100 }, /*串口设备*/
    [VIRT_VIRTIO] =      { 0x10001000,        0x1000 },
    [VIRT_FW_CFG] =      { 0x10100000,          0x18 },
    [VIRT_FLASH] =       { 0x20000000,     0x4000000 },
    [VIRT_IMSIC_M] =     { 0x24000000, VIRT_IMSIC_MAX_SIZE },
    [VIRT_IMSIC_S] =     { 0x28000000, VIRT_IMSIC_MAX_SIZE },
    [VIRT_PCIE_ECAM] =   { 0x30000000,    0x10000000 },
    [VIRT_PCIE_MMIO] =   { 0x40000000,    0x40000000 },
    [VIRT_DRAM] =        { 0x80000000,           0x0 }, /*DDR空间*/
};

rt-smart针对virt board的ddr空间规划

参考链接脚本

bsp\qemu-virt64-riscv\link.lds

以及board.h中的相关定义

bsp\qemu-virt64-riscv\driver\board.h

得到ddr的空间规划如下

内容地址空间
代码段数据段栈空间以及bss段0x80200000 ~ __bss_end
堆空间__bss_end ~ __bss_end + 100M
页分配空间__bss_end + 100M ~ __bss_end + 200M

rt-smart针对virt board的初始化

整体初始化

rt_hw_board_init定义了与qemu-virt-riscv相关的板级初始化的全部内容,包括内存系统,plic中断子系统,定时器系统以及串口设备等。它由rtthread_startup调用,完整的调用路径如下。

(libcpu\risc-v\virt64\startup_gcc.S)_start->primary_cpu_entry->entry->rtthread_startup->rt_hw_board_init

源码如下

void rt_hw_board_init(void)
{
#ifdef RT_USING_USERSPACE
    rt_page_init(init_page_region);
    /* init mmu_info structure */
    rt_hw_mmu_map_init(&mmu_info, (void *)(USER_VADDR_START - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, 0);
    // this API is reserved currently since PLIC etc had not been porting completely to MMU version
    rt_hw_mmu_kernel_map_init(&mmu_info, 0x00000000UL, 0x80000000);
    /* setup region, and enable MMU */
    rt_hw_mmu_setup(&mmu_info, platform_mem_desc, NUM_MEM_DESC);

#endif

#ifdef RT_USING_HEAP
    /* initialize memory system */
    rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
#endif

    plic_init();

    rt_hw_interrupt_init();

    rt_hw_uart_init();

#ifdef RT_USING_CONSOLE
    /* set console device */
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif /* RT_USING_CONSOLE */

    rt_hw_tick_init();

#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#ifdef RT_USING_HEAP
    rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t)RT_HW_HEAP_BEGIN, (rt_ubase_t)RT_HW_HEAP_END);
#endif /* RT_USING_HEAP */
}

rt_page_init

rt-smart中使用了buddy算法管理了一部分内存区域,系统使用page_alloc来向buddy管理的内存区域申请内存资源,像linux一样每个page是4k的大小。rt-smart采用buddy算法将系统中部分可用的物理内存页面按照每1个页面、2个页面、4个页面等等划分为了不同的单元。详情可参考这篇文章https://club.rt-thread.org/ask/article/3e3a9a0b6d3e2105.html

void rt_page_init(rt_region_t reg)
{
    int i;

    LOG_D("split 0x%08x 0x%08x\n", reg.start, reg.end);

    reg.start += ARCH_PAGE_MASK;
    reg.start &= ~ARCH_PAGE_MASK;

    reg.end &= ~ARCH_PAGE_MASK;

    {
        int nr = ARCH_PAGE_SIZE / sizeof(struct page);
        int total = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
        int mnr = (total + nr) / (nr + 1);

        LOG_D("nr = 0x%08x\n", nr);
        LOG_D("total = 0x%08x\n", total);
        LOG_D("mnr = 0x%08x\n", mnr);

        RT_ASSERT(mnr < total);

        page_start = (struct page*)reg.start;
        reg.start += (mnr << ARCH_PAGE_SHIFT);
        page_addr = (void*)reg.start;
        page_nr = (reg.end - reg.start) >> ARCH_PAGE_SHIFT;
    }

这里rt-smart直接将一部分页表空间分配给struct page去使用,有可能会造成页面的浪费。例如当total=7, nr=5时,mnr=2,也就是俩个页表用于存储page,五个页表是真正可以被alloc_page申请的。但实际上五个页表只需要一个页表的空间就可以存放page结构体了,相当于浪费了一个页表。

rt_hw_mmu_map_init

#define USER_VADDR_START    0x100000000UL
#define IOREMAP_SIZE        (1ul << 30)
int rt_hw_mmu_map_init(rt_mmu_info *mmu_info, void *v_address, rt_size_t size, rt_size_t *vtable, rt_size_t pv_off)
{
   /*代码省略*/
    mmu_info->vtable = vtable;
    mmu_info->vstart = va_s;
    mmu_info->vend = va_e;
    mmu_info->pv_off = pv_off;

    return 0;
}

mmu_info是一个全局变量,在调用rt_hw_mmu_map_init后,(USER_VADDR_START - IOREMAP_SIZE) ~ USER_VADDR_START 这片虚拟地址空间将来专门提供给ioremap来使用。也就是ioremap返回的虚拟地址区间就是 0xc0000000 ~ 0xFFFFFFFF

rt_hw_mmu_kernel_map_init

void rt_hw_mmu_kernel_map_init(rt_mmu_info *mmu_info, rt_size_t vaddr_start, rt_size_t size)
{
    rt_size_t paddr_start = __UMASKVALUE(VPN_TO_PPN(vaddr_start, mmu_info->pv_off), PAGE_OFFSET_MASK);
    rt_size_t va_s = GET_L1(vaddr_start);
    rt_size_t va_e = GET_L1(vaddr_start + size - 1);
    rt_size_t i;

    for (i = va_s; i <= va_e; i++)
    {
        mmu_info->vtable[i] = COMBINEPTE(paddr_start, PAGE_ATTR_RWX | PTE_G | PTE_V);
        paddr_start += L1_PAGE_SIZE;
    }

    rt_hw_cpu_tlb_invalidate();
}

这里将0x0 ~ 0x80000000的物理地址空间做了offset为0的一比一映射,且只使用了一级页表。之后0x80000000之下的地址CPU都可以直接访问了。从页表的属性配置上看,这片区域是nocache的。

rt_hw_mmu_setup

#define KERNEL_VADDR_START 0x80000000
#define PV_OFFSET 0

struct mem_desc platform_mem_desc[] = {
    {KERNEL_VADDR_START, KERNEL_VADDR_START + 0x10000000 - 1, KERNEL_VADDR_START + PV_OFFSET, NORMAL_MEM},
};

void rt_hw_mmu_setup(rt_mmu_info *mmu_info, struct mem_desc *mdesc, int desc_nr)
{
 void *err;
    for (size_t i = 0; i < desc_nr; i++)
    {
        size_t attr;
        switch (mdesc->attr)
        {
            case NORMAL_MEM:
                attr = MMU_MAP_K_RWCB;
                break;
            case NORMAL_NOCACHE_MEM:
                attr = MMU_MAP_K_RWCB;
                break;
            case DEVICE_MEM:
                attr = MMU_MAP_K_DEVICE;
                break;
            default:
                attr = MMU_MAP_K_DEVICE;
        }
        rt_kprintf("vaddr start:%lx paddr_start:%lx\n", mdesc->vaddr_start, mdesc->paddr_start);
        err = _rt_hw_mmu_map(mmu_info, (void *)mdesc->vaddr_start, (void *)mdesc->paddr_start,
            mdesc->vaddr_end - mdesc->vaddr_start + 1, attr);
        mdesc++;
    }
    rt_hw_mmu_switch((void *)MMUTable);
}

这里首先将0x80000000 ~ 0x90000000这片区域做了offset为0的线性映射,映射使用的是三级页表一页一页映射的,相当于page的区域也被映射好了。之后调用rt_hw_mmu_switch配置SATP配置MMU的地址翻译模式为SV39。STAP的mode被配置后,MMU就相当于开启了。

将rtconfig.h中的PV_OFFSET改为非0值后系统无法启动,对比bsp/qemu-vexpress-a9中board.c里关于页表的配置这块儿应该还是有问题的。

rt_hw_tick_init

int rt_hw_tick_init(void)
{
    /* Read core id */
    // unsigned long core_id = current_coreid();
    unsigned long interval = 1000/RT_TICK_PER_SECOND;

    /* Clear the Supervisor-Timer bit in SIE */
    clear_csr(sie, SIP_STIP);

    /* calculate the tick cycles */
    // tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
    tick_cycles = 40000;
    /* Set timer */
    sbi_set_timer(get_ticks() + tick_cycles);

    /* Enable the Supervisor-Timer bit in SIE */
    set_csr(sie, SIP_STIP);

    return 0;
}

这里使用的是riscv中的mtime。mtime是riscv中定义的一个64位的系统计时器,它被要求工作在常开的时钟域下。内核中使用以下指令可以读取mtime的值

static uint64_t get_ticks()
{
    __asm__ __volatile__(
        "rdtime %0"
        : "=r"(time_elapsed));
    return time_elapsed;
}

补充知识,在qemu中这个时钟的获取来源如下

static inline int64_t get_clock_realtime(void)
{
    struct timeval tv;

    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
}

sbi_set_timer并不是设置timer本身的值,而是设置机器模式计时器比较值寄存器MTIMECMPH, MTIMECMPL的值, 当系统计时器的值小于等于 {M/STIMECMPH[31:0],M/STIMECMPL[31:0]}的值时不产生中断;当系统计时器的值大于 {M/STIMECMPH[31:0],M/STIMECMPL[31:0]} 的值时 CLINT产生对应的计时器中断。它的配置过程为 rt-smart将比较寄存器的配置按规则组织为sbi_call的指令,将指令类型指令参数等放入cpu的a0~a7的寄存器,然后调用ecall指令使cpu陷入M态。

sbi_set_timer->SBI_CALL1(SBI_SET_TIMER, 0, val)->sbi_call

static __inline struct sbi_ret
sbi_call(uint64_t arg7, uint64_t arg6, uint64_t arg0, uint64_t arg1,
         uint64_t arg2, uint64_t arg3, uint64_t arg4)

{
    struct sbi_ret ret;

    register uintptr_t a0 __asm("a0") = (uintptr_t)(arg0);
    register uintptr_t a1 __asm("a1") = (uintptr_t)(arg1);
    register uintptr_t a2 __asm("a2") = (uintptr_t)(arg2);
    register uintptr_t a3 __asm("a3") = (uintptr_t)(arg3);
    register uintptr_t a4 __asm("a4") = (uintptr_t)(arg4);
    register uintptr_t a6 __asm("a6") = (uintptr_t)(arg6);
    register uintptr_t a7 __asm("a7") = (uintptr_t)(arg7);

    __asm __volatile(\
                     "ecall"                                        \
                     : "+r"(a0), "+r"(a1)                           \
                     : "r"(a2), "r"(a3), "r"(a4), "r"(a6), "r"(a7)  \
                     : "memory");

    ret.error = a0;
    ret.value = a1;
    return (ret);
}

CPU陷入M态后,opensbi会处理这个ecall产生的异常。获取内核放到寄存器中参数,把新的值赋值给比较值寄存器,并清除计时器中断

void sbi_timer_event_start(u64 next_event)
{
 if (timer_dev && timer_dev->timer_event_start)
  timer_dev->timer_event_start(next_event);
 csr_clear(CSR_MIP, MIP_STIP);
 csr_set(CSR_MIE, MIP_MTIP);
}

其他

之后的初始化都是原先rt-thread中的内容了,感兴趣的读者可以自行查阅rt-thread官方的《RT-THREAD 编程指南》手册来学习。另外需要注意的点在plic_init中,plic的寄存器的基地址没有使用ioremap就直接使用了,这是因为上面描述的0x0 ~ 0x80000000的物理地址空间被做了offset为0的一比一映射。

rt-smart的ioremap实现

void *rt_ioremap(void *paddr, size_t size)
{
    return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY);
}

void *rt_ioremap_nocache(void *paddr, size_t size)
{
    return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY);
}

void *rt_ioremap_cached(void *paddr, size_t size)
{
    return _ioremap_type(paddr, size, MM_AREA_TYPE_PHY_CACHED);
}

rt-smart中的ioremap实际上只分了俩种映射方式,分别是cache和nocache。在当前的qemu-virt64-riscv里,cache的属性没有配置到页表中,我也没有查qemu的页表支不支持配置cache,感兴趣的读者请参考C906的相关代码 libcpu/risc-v/t-head/c906/riscv_mmu.h

/* C-SKY extend */
#define PTE_SEC   (1UL << 59)   /* Security */
#define PTE_SHARE (1UL << 60)   /* Shareable */
#define PTE_BUF   (1UL << 61)   /* Bufferable */
#define PTE_CACHE (1UL << 62)   /* Cacheable */
#define PTE_SO    (1UL << 63)   /* Strong Order */
#define MMU_MAP_K_DEVICE (PAGE_ATTR_RWX | PTE_V | PTE_G | PTE_SO | PTE_BUF | PTE_A | PTE_D)
#define MMU_MAP_K_RWCB (PAGE_ATTR_RWX | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D)
static void *_ioremap_type(void *paddr, size_t size, int type)
{
    void *v_addr = NULL;
    size_t attr;

    switch (type)
    {
    case MM_AREA_TYPE_PHY:
        attr = MMU_MAP_K_DEVICE;
        break;
    case MM_AREA_TYPE_PHY_CACHED:
        attr = MMU_MAP_K_RWCB;
        break;
    default:
        return v_addr;
    }

    rt_mm_lock();
    v_addr = rt_hw_mmu_map(&mmu_info, 0, paddr, size, attr);
    if (v_addr)
    {
        int ret = lwp_map_area_insert(&k_map_area, (size_t)v_addr, size, type);
        if (ret != 0)
        {
            _iounmap_range(v_addr, size);
            v_addr = NULL;
        }
    }
    rt_mm_unlock();
    return v_addr;
}

__ioremap_type中会记录页表要配置的属性然后调用rt_hw_mmu_map进行映射。之后会将映射得到的虚拟地址插入到k_map_area中。

void *_rt_hw_mmu_map(rt_mmu_info *mmu_info, void *v_addr, void *p_addr, rt_size_t size, rt_size_t attr)
{
    /*代码省略*/
    if (v_addr)
    {
        /*代码省略*/
    }
    else
    {
        vaddr = find_vaddr(mmu_info, pages);
    }

    if (vaddr)
    {
        ret = __rt_hw_mmu_map(mmu_info, (void *)vaddr, p_addr, pages, attr);

        if (ret == 0)
        {
            rt_hw_cpu_tlb_invalidate();
            return (void *)(vaddr | GET_PF_OFFSET((rt_size_t)p_addr));
        }
    }
    return 0;
}

ioremap传入的虚拟地址是0,所以这里先需要调用find_vaddr得到一个可用的虚拟地址。另一个传入find_vaddr的参数pages代表要要映射的物理内存区域需要多少个page(4K).

static size_t find_vaddr(rt_mmu_info *mmu_info, int pages)
{
    size_t loop_pages;
    size_t va;
    size_t find_va = 0;
    int n = 0;
    size_t i;
    
    loop_pages = (mmu_info->vend - mmu_info->vstart) ? (mmu_info->vend - mmu_info->vstart) : 1;
    loop_pages <<= (ARCH_INDEX_WIDTH * 2);
    va = mmu_info->vstart;
    va <<= (ARCH_PAGE_SHIFT + ARCH_INDEX_WIDTH * 2);
    for (i = 0; i < loop_pages; i++, va += ARCH_PAGE_SIZE) {
        if (_rt_hw_mmu_v2p(mmu_info, (void *)va)) {
            n = 0;
            find_va = 0;
            continue;
        }
        if (!find_va) {
            find_va = va;
        }
        n++;
        if (n >= pages) {
            return find_va;
        }
    }
    return 0;
}

这里会从mmu_info->vstart的虚拟地址开始找,这个地址就是最前面提到的0xC0000000。从0XC0000000开始一个page一个page的去找,看对应的虚拟地址有没有被映射。如果没有,那么将va赋值给find_va。之后会继续往后查找看能不能找到连续的虚拟内存空间大小可以满足ioremap需要的大小。如果满足大小最终就返回找到的虚拟地址。总结这个过程就是寻找一块连续的没有被映射的大小满足的虚拟地址空间。


———————End———————


你可以添加微信:rtthread2020 为好友,注明:公司+姓名,拉进RT-Thread官方微信交流群!



爱我就给我点在看

👇点击阅读原文进入官网

RTThread物联网操作系统 帮助您了解RT-Thread相关的资讯.
评论 (0)
  • HDMI从2.1版本开始采用FRL传输模式,和2.0及之前的版本不同。两者在物理层信号上有所区别,这就需要在一些2.1版本的电路设计上增加匹配电路,使得2.1版本的电路能够向下兼容2.0及之前版本。2.1版本的信号特性下面截取自2.1版本规范定义,可以看到2.1版本支持直流耦合和交流耦合,其共模电压和AVCC相关,信号摆幅在400mV-1200mV2.0及之前版本的信号特性HDMI2.0及之前版本采用TMDS信号物理层,其结构和参数如下:兼容设计根据以上规范定义,可以看出TMDS信号的共模电压范
    durid 2025-04-08 19:01 172浏览
  •   物质扩散与污染物监测系统:环境守护的关键拼图   一、物质扩散原理剖析   物质扩散,本质上是物质在浓度梯度、温度梯度或者压力梯度等驱动力的作用下,从高浓度区域向低浓度区域迁移的过程。在环境科学范畴,物质扩散作为污染物在大气、水体以及土壤中迁移的关键机制,对污染物的分布态势、浓度动态变化以及环境风险程度有着直接且重大的影响。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这些成功案例为物质
    华盛恒辉l58ll334744 2025-04-09 11:24 57浏览
  •   物质扩散与污染物监测系统软件:多领域环境守护的智能中枢   北京华盛恒辉物质扩散与污染物监测系统软件,作为一款融合了物质扩散模拟、污染物监测、数据分析以及可视化等多元功能的综合性工具,致力于为环境科学、公共安全、工业生产等诸多领域给予强有力的技术支撑。接下来,将从功能特性、应用场景、技术实现途径、未来发展趋势等多个维度对这类软件展开详尽介绍。   应用案例   目前,已有多个物质扩散与污染物监测系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润物质扩散与污染物监测系统。这
    华盛恒辉l58ll334744 2025-04-09 14:54 114浏览
  • 文/郭楚妤编辑/cc孙聪颖‍伴随贸易全球化的持续深入,跨境电商迎来蓬勃发展期,物流行业 “出海” 成为不可阻挡的必然趋势。加之国内快递市场渐趋饱和,存量竞争愈发激烈。在此背景下,国内头部快递企业为突破发展瓶颈,寻求新的增长曲线,纷纷将战略目光投向海外市场。2024 年,堪称中国物流企业出海进程中的关键节点,众多企业纷纷扬帆起航,开启海外拓展之旅。然而,在一片向好的行业发展表象下,部分跨境物流企业的经营状况却不容乐观。它们受困于激烈的市场竞争、不断攀升的运营成本,以及复杂的国际物流环境,陷入了微利
    华尔街科技眼 2025-04-09 15:15 93浏览
  •   工业自动化领域电磁兼容与接地系统深度剖析   一、电磁兼容(EMC)基础认知   定义及关键意义   电磁兼容性(EMC),指的是设备或者系统在既定的电磁环境里,不但能按预期功能正常运转,而且不会对周边其他设备或系统造成难以承受的电磁干扰。在工业自动化不断发展的当下,大功率电机、变频器等设备被大量应用,现场总线、工业网络等技术也日益普及,致使工业自动化系统所处的电磁环境变得愈发复杂,电磁兼容(EMC)问题也越发严峻。   ​电磁兼容三大核心要素   屏蔽:屏蔽旨在切断电磁波的传播路
    北京华盛恒辉软件开发 2025-04-07 22:55 247浏览
  •     根据 IEC术语,瞬态过电压是指持续时间几个毫秒及以下的过高电压,通常是以高阻尼(快速衰减)形式出现,波形可以是振荡的,也可以是非振荡的。    瞬态过电压的成因和机理,IEC 60664-1给出了以下四种:    1. 自然放电,最典型的例子是雷击,感应到电力线路上,并通过电网配电系统传输,抵达用户端;        2. 电网中非特定感性负载通断。例如热处理工厂、机加工工厂对
    电子知识打边炉 2025-04-07 22:59 157浏览
  •     在研究Corona现象时发现:临界电压与介电材料表面的清洁程度有关。表面越清洁的介电材料,临界电压越高;表面污染物越多的地方,越容易“爬电”。关于Corona现象,另见基础理论第007篇。    这里说的“污染物”,定义为——可能影响介电强度或表面电阻率的固体、液体或气体(电离气体)的任何情况。    IEC 60664-1 (对应GB/T 16935.1-2023) 定义了 Pollution Degree,中文术语是“污染等
    电子知识打边炉 2025-04-07 22:06 112浏览
  •   卫星图像智能测绘系统全面解析   一、系统概述   卫星图像智能测绘系统是基于卫星遥感技术、图像处理算法与人工智能(AI)技术的综合应用平台,旨在实现高精度、高效率的地理空间数据获取、处理与分析。该系统通过融合多源卫星数据(如光学、雷达、高光谱等),结合AI驱动的智能算法,实现自动化、智能化的测绘流程,广泛应用于城市规划、自然资源调查、灾害监测等领域。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润卫星图像智能测绘系统
    华盛恒辉l58ll334744 2025-04-08 15:04 99浏览
  • 文/Leon编辑/侯煜‍就在小米SU7因高速交通事故、智驾性能受到质疑的时候,另一家中国领先的智驾解决方案供应商华为,低调地进行了一场重大人事变动。(详情见:雷军熬过黑夜,寄望小米SU7成为及时雨)4月4日上午,有网友发现余承东的职务发生了变化,华为官网、其个人微博认证信息为“常务董事,终端BG董事长”,不再包括“智能汽车解决方案BU董事长”。余承东的确不再兼任华为车BU董事长,但并非完全脱离华为的汽车业务,而是聚焦鸿蒙智行。据悉,华为方面寻求将车BU独立出去,但鸿蒙智行仍留在华为终端BG部门。
    华尔街科技眼 2025-04-09 15:28 93浏览
  •   卫星图像智能测绘系统:地理空间数据处理的创新引擎   卫星图像智能测绘系统作为融合卫星遥感、地理信息系统(GIS)、人工智能(AI)以及大数据分析等前沿技术的综合性平台,致力于达成高精度、高效率的地理空间数据采集、处理与应用目标。借助自动化、智能化的技术路径,该系统为国土资源管理、城市规划、灾害监测、环境保护等诸多领域输送关键数据支撑。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉北京五木恒润卫星图像智能测绘系统。这些成功案例为卫星
    华盛恒辉l58ll334744 2025-04-08 16:19 86浏览
  • ## DL/T645-2007* 帧格式:* 帧起始字符:68H* 地址域:A0 A1 A2 A3 A4 A5* 帧起始字符:68H* 控制码:1字节* 主站:* 13H:请求读电能表通信地址* 11H:请求读电能表数据* 1CH:请求跳闸、合闸* 从站:* 91H:正常应答读电能表* 9CH:正常应答跳闸、合闸* 数据域长度:1字节* 数据域:DI0 DI1 DI2 DI3* 发送方:每字节+33H* 接收方:每字节-33H* 数据标识:* 电能量* 最大需量及发生时间* 变量* 事件记录*
    四毛打印店 2025-04-09 10:53 59浏览
  • 在人工智能技术飞速发展的今天,语音交互正以颠覆性的方式重塑我们的生活体验。WTK6900系列语音识别芯片凭借其离线高性能、抗噪远场识别、毫秒级响应的核心优势,为智能家居领域注入全新活力。以智能风扇为起点,我们开启一场“解放双手”的科技革命,让每一缕凉风都随“声”而至。一、核心技术:精准识别,无惧环境挑战自适应降噪,听懂你的每一句话WTK6900系列芯片搭载前沿信号处理技术,通过自适应降噪算法,可智能过滤环境噪声干扰。无论是家中电视声、户外虫鸣声,还是厨房烹饪的嘈杂声,芯片均能精准提取有效指令,识
    广州唯创电子 2025-04-08 08:40 192浏览
  • 曾几何时,汽车之家可是汽车资讯平台领域响当当的“扛把子”。2005 年成立之初,它就像一位贴心的汽车小助手,一下子就抓住了大家的心。它不仅吸引了海量用户,更是成为汽车厂商和经销商眼中的“香饽饽”,广告投放、合作推广不断,营收和利润一路高歌猛进,2013年成功在纽交所上市,风光无限。2021年更是在香港二次上市,达到了发展的巅峰,当年3月15日上市首日,港股股价一度高达184.6港元,市值可观。然而,如今的汽车之家却陷入了困境,业务下滑明显。业务增长瓶颈从近年来汽车之家公布的财报数据来看,情况不容
    用户1742991715177 2025-04-07 21:48 117浏览
  • 在万物互联时代,智能化安防需求持续升级,传统报警系统已难以满足实时性、可靠性与安全性并重的要求。WT2003H-16S低功耗语音芯片方案,以4G实时音频传输、超低功耗设计、端云加密交互为核心,重新定义智能报警设备的性能边界,为家庭、工业、公共安防等领域提供高效、稳定的安全守护。一、技术内核:五大核心突破,构建全场景安防基座1. 双模音频传输,灵活应对复杂场景实时音频流传输:内置高灵敏度MIC,支持环境音实时采集,通过4G模块直接上传至云端服务器,响应速度低至毫秒级,适用于火灾警报、紧急呼救等需即
    广州唯创电子 2025-04-08 08:59 156浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦