日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

RK3576 CPUFreq驅動深度剖析:從原理到實戰(zhàn)

jf_44130326 ? 來源:Linux1024 ? 2026-04-09 17:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

嵌入式Linux性能調優(yōu)核心戰(zhàn)場,從代碼層面徹底吃透DVFS機制

作為嵌入式Linux開發(fā)者,你是否只停留在echo performance > scaling_governor的表層操作?當遇到頻率切換延遲高、電壓調節(jié)失敗、多核異構頻率協(xié)同等問題時,是否束手無策?

今天這篇文章,將逐行剖析RK3576平臺的cpufreq實現(xiàn),從源碼層面拆解Linux內核DVFS(動態(tài)電壓頻率調節(jié))的每一個細節(jié),帶你從會用精通,解決實際開發(fā)中的核心痛點。

一、為什么要深入cpufreq源碼?

嵌入式Linux開發(fā)中,cpufreq是性能與功耗平衡的核心,但這些問題往往讓開發(fā)者卡殼:

?頻率切換延遲過高,如何優(yōu)化?

?電壓調節(jié)失敗,如何定位?

?多核異構場景下,頻率如何協(xié)同?

?自定義調速器,如何接入框架?

只有深入源碼,才能真正掌握DVFS的底層邏輯,而非停留在調參數(shù)的表面操作。

二、整體架構:代碼視角的分層設計

2.1文件組織與模塊依賴

cpufreq驅動的代碼分布清晰,核心文件各司其職:

drivers/cpufreq/├── cpufreq.c        # 核心框架:策略管理、通知鏈、sysfs├── cpufreq-dt.c      # DT 通用驅動:OPP 解析、時鐘操作├── cpufreq-dt.h      # DT 驅動接口定義├── rockchip-cpufreq.c   # RK 平臺驅動:SoC 特性、DVFS 鎖、監(jiān)控├── rockchip-cpufreq.h   # RK 驅動導出接口├── cpufreq_governor.c   # 調速器公共框架├── cpufreq_governor.h   # 調速器數(shù)據(jù)結構├── cpufreq_interactive.c  # Interactive 調速器實現(xiàn)├── cpufreq_ondemand.c   # Ondemand 調速器實現(xiàn)├── freq_table.c      # 頻率表輔助函數(shù)└── cpufreq_stats.c     # 統(tǒng)計信息模塊

2.2核心結構體關系(代碼定義)

cpufreq的核心邏輯圍繞兩個結構體展開,是理解整個框架的關鍵:

// include/linux/cpufreq.hstructcpufreq_policy{ cpumask_var_t     cpus;     // 本策略管理的 CPU 掩碼 cpumask_var_t     related_cpus; // 硬件相關的 CPU(共享時鐘) unsignedint      min;      // 用戶設置的最小頻率 unsignedint      max;      // 用戶設置的最大頻率 unsignedint      cur;      // 當前頻率(kHz) structcpufreq_governor*governor;   // 當前調速器 void          *governor_data;// 調速器私有數(shù)據(jù) structcpufreq_frequency_table*freq_table;// 頻率表 structcpufreq_stats  *stats;    // 統(tǒng)計信息 structkobject     kobj;     // sysfs 對象 void          *driver_data; // 驅動私有數(shù)據(jù) // ... 更多字段};structcpufreq_driver{ char      name[CPUFREQ_NAME_LEN]; unsignedint  flags;
 /* 必須實現(xiàn)的回調 */ int(*target_index)(structcpufreq_policy *policy,unsignedintindex); unsignedint(*get)(unsignedintcpu);
 /* 可選回調 */ int(*init)(structcpufreq_policy *policy); int(*exit)(structcpufreq_policy *policy); int(*online)(structcpufreq_policy *policy); int(*offline)(structcpufreq_policy *policy); // ...};

腦圖:RK3576 CPUFreq核心架構

wKgZPGnRtT2AGcPQAAGnAiZaL38464.png

三、初始化流程:從模塊加載到頻率就緒

RK3576cpufreq初始化是先集群初始化,再注冊驅動的邏輯,核心分為三步:

3.1驅動入口:rockchip_cpufreq_driver_init

這是整個RK平臺cpufreq的入口函數(shù),核心邏輯是遍歷CPU集群、初始化集群信息、注冊通知鏈和平臺設備:

// drivers/cpufreq/rockchip-cpufreq.cstaticint__initrockchip_cpufreq_driver_init(void){ structcluster_info *cluster, *pos; structcpufreq_dt_platform_data pdata = {0}; intcpu, ret; boolis_opp_shared_cpu_bus =false; /* 遍歷所有可能的 CPU,為每個 cluster 初始化 */  for_each_possible_cpu(cpu) {    cluster = rockchip_cluster_info_lookup(cpu);   if(cluster)     continue; // 已初始化過    cluster = kzalloc(sizeof(*cluster), GFP_KERNEL);   if(!cluster) {      ret = -ENOMEM;     gotorelease_cluster_info;    }   /* 核心初始化:解析 OPP、獲取 regulator、設置 SoC 信息 */    ret = rockchip_cpufreq_cluster_init(cpu, cluster);   if(ret) {      pr_err("Failed to initialize dvfs info cpu%dn", cpu);     gotorelease_cluster_info;    }
    list_add(&cluster->list_head, &cluster_info_list);   if(cluster->is_opp_shared_cpu_bus)      is_opp_shared_cpu_bus =true;  } /* 設置平臺數(shù)據(jù) */  pdata.have_governor_per_policy =true;  pdata.suspend = rockchip_cpufreq_suspend; /* 注冊 cpufreq 通知鏈 */  ret = cpufreq_register_notifier(&rockchip_cpufreq_notifier_block,                  CPUFREQ_POLICY_NOTIFIER); if(ret) {    pr_err("failed to register cpufreq notifiern");   gotorelease_cluster_info;  } /* 如果存在 OPP 共享總線,注冊 transition 通知器 */ if(is_opp_shared_cpu_bus) {    ret = cpufreq_register_notifier(&rockchip_cpufreq_transition_notifier_block,                    CPUFREQ_TRANSITION_NOTIFIER);   // ...  } /* 注冊 panic 通知器,用于調試 */  ret = atomic_notifier_chain_register(&panic_notifier_list,                    &rockchip_cpufreq_panic_notifier_block); /* 注冊 platform_device,觸發(fā) cpufreq-dt 驅動 probe */ returnPTR_ERR_OR_ZERO(platform_device_register_data(NULL,"cpufreq-dt",       -1, (void*)&pdata,sizeof(structcpufreq_dt_platform_data)));}module_init(rockchip_cpufreq_driver_init);// drivers/cpufreq/rockchip-cpufreq.cstaticint__initrockchip_cpufreq_driver_init(void){ structcluster_info *cluster, *pos; structcpufreq_dt_platform_data pdata = {0}; intcpu, ret; boolis_opp_shared_cpu_bus =false; /* 遍歷所有可能的 CPU,為每個 cluster 初始化 */  for_each_possible_cpu(cpu) {    cluster = rockchip_cluster_info_lookup(cpu);   if(cluster)     continue; // 已初始化過    cluster = kzalloc(sizeof(*cluster), GFP_KERNEL);   if(!cluster) {      ret = -ENOMEM;     gotorelease_cluster_info;    }   /* 核心初始化:解析 OPP、獲取 regulator、設置 SoC 信息 */    ret = rockchip_cpufreq_cluster_init(cpu, cluster);   if(ret) {      pr_err("Failed to initialize dvfs info cpu%dn", cpu);     gotorelease_cluster_info;    }
    list_add(&cluster->list_head, &cluster_info_list);   if(cluster->is_opp_shared_cpu_bus)      is_opp_shared_cpu_bus =true;  } /* 設置平臺數(shù)據(jù) */  pdata.have_governor_per_policy =true;  pdata.suspend = rockchip_cpufreq_suspend; /* 注冊 cpufreq 通知鏈 */  ret = cpufreq_register_notifier(&rockchip_cpufreq_notifier_block,                  CPUFREQ_POLICY_NOTIFIER); if(ret) {    pr_err("failed to register cpufreq notifiern");   gotorelease_cluster_info;  } /* 如果存在 OPP 共享總線,注冊 transition 通知器 */ if(is_opp_shared_cpu_bus) {    ret = cpufreq_register_notifier(&rockchip_cpufreq_transition_notifier_block,                    CPUFREQ_TRANSITION_NOTIFIER);   // ...  } /* 注冊 panic 通知器,用于調試 */  ret = atomic_notifier_chain_register(&panic_notifier_list,                    &rockchip_cpufreq_panic_notifier_block); /* 注冊 platform_device,觸發(fā) cpufreq-dt 驅動 probe */ returnPTR_ERR_OR_ZERO(platform_device_register_data(NULL,"cpufreq-dt",       -1, (void*)&pdata,sizeof(structcpufreq_dt_platform_data)));}module_init(rockchip_cpufreq_driver_init);

3.2 Cluster初始化:rockchip_cpufreq_cluster_init

每個CPU集群(大核/小核)的初始化核心是解析OPP表、獲取電壓調節(jié)器、讀取SoC特有信息:

Cstaticintrockchip_cpufreq_cluster_init(intcpu,structcluster_info *cluster){  structrockchip_opp_info*opp_info = &cluster->opp_info;  structdevice_node*np;  structdevice*dev;  char*reg_name;  intret =0;  u32 freq =0;  dev =get_cpu_device(cpu);  if(!dev)    return-ENODEV;  /* 從 CPU 節(jié)點獲取 operating-points-v2 phandle */  np =of_parse_phandle(dev->of_node,"operating-points-v2",0);  if(!np) {    dev_warn(dev,"OPP-v2 not supportedn");    return-ENOENT;  }  /* 獲取共享 OPP 的 CPU 掩碼(大核/小核 cluster) */  ret =dev_pm_opp_of_get_sharing_cpus(dev, &cluster->cpus);  if(ret) {    dev_err(dev,"Failed to get sharing cpusn");    of_node_put(np);    returnret;  }  /* 檢查是否共享 DSU/CCI 總線 OPP */ if(of_property_read_bool(np,"rockchip,opp-shared-dsu") ||    of_property_read_bool(np,"rockchip,opp-shared-cci"))    cluster->is_opp_shared_cpu_bus =true;  /* 讀取 CPU 到總線頻率的百分比 */ of_property_read_u32(np,"rockchip,cpu-freq-percent",             &cluster->cpu_freq_percent);  /* 讀取空閑閾值頻率 */ if(!of_property_read_u32(np,"rockchip,idle-threshold-freq", &freq))    cluster->idle_threshold_freq = freq;  of_node_put(np);  /* 確定 regulator 名稱 */ if(of_find_property(dev->of_node,"cpu-supply",NULL))    reg_name ="cpu";  elseif(of_find_property(dev->of_node,"cpu0-supply",NULL))    reg_name ="cpu0";  else   return-ENOENT;  /* 獲取 SoC 特定的 OPP 數(shù)據(jù)處理函數(shù) */ rockchip_get_opp_data(rockchip_cpufreq_of_match, opp_info);  /* 初始化 OPP 信息:讀取 nvmem、設置 supported_hw */  ret =rockchip_init_opp_info(dev, opp_info,NULL, reg_name);  if(ret)    dev_err(dev,"failed to init opp infon");  returnret;}

3.3 RK3576特有的SoC信息讀取

RK3576不同版本(M/J/S)的頻率/電壓支持不同,核心是從nvmem讀取芯片規(guī)格:

staticintrk3576_cpu_get_soc_info(structdevice *dev,structdevice_node *np,                 int*bin,int*process){ intret =0;  u8 spec =0, test_version =0; if(!bin)   return0; /* 從 nvmem 讀取芯片規(guī)格序列號 */ if(of_property_match_string(np,"nvmem-cell-names",                "specification_serial_number") >=0) {    ret = rockchip_nvmem_cell_read_u8(np,                    "specification_serial_number",                     &spec);   if(ret) {      dev_err(dev,"Failed to get specification_serial_numbern");     returnret;    }  } /* 讀取測試版本 */ if(of_property_match_string(np,"nvmem-cell-names","test_version") >=0) {    ret = rockchip_nvmem_cell_read_u8(np,"test_version", &test_version);   if(ret) {      dev_err(dev,"Failed to get test_versionn");     returnret;    }  } /* 根據(jù) spec 值判斷芯片型號 */ if(spec ==0xd) {    *bin =1; /* RK3576M */  }elseif(spec ==0xa) {    *bin =2; /* RK3576J */  }elseif(spec ==0x13) {   if(test_version ==0) {      *bin =3; /* RK3576S */    }else{      *bin =0;      dev_info(dev,"bin=%d (3)n", *bin);     return0;    }  } if(*bin 0)    *bin =0;  dev_info(dev,"bin=%dn", *bin); returnret;}

流程圖:RK3576 CPUFreq初始化流程

st=>start: 模塊加載(rockchip_cpufreq_driver_init)op1=>operation: 遍歷所有CPUop2=>operation: 查找/創(chuàng)建cluster_infoop3=>operation: rockchip_cpufreq_cluster_initop4=>operation: 解析OPP-v2節(jié)點op5=>operation: 獲取共享CPU掩碼/總線信息op6=>operation: 讀取SoC信息(nvmem)op7=>operation: 注冊策略/轉換通知鏈op8=>operation: 注冊cpufreq-dt平臺設備e=>end: 觸發(fā)cpufreq-dt probe,初始化完成st->op1->op2->op3->op4->op5->op6->op7->op8->e

四、頻率調整核心:從Governor到硬件

頻率調整是cpufreq的核心流程,完整鏈路是:調速器決策核心層處理驅動層執(zhí)行→ OPP子系統(tǒng)硬件(時鐘/電壓)

4.1調速器決策:interactive為例

interactive是嵌入式場景最常用的調速器,核心是按需快速升頻,緩慢降頻,關鍵邏輯在負載計算和頻率評估:

// drivers/cpufreq/cpufreq_interactive.c/* 核心數(shù)據(jù)結構 */structinteractive_cpu{ structupdate_util_dataupdate_util;  // 注冊到調度器的鉤子 structinteractive_policy*ipolicy;
 structirq_workirq_work;       // 中斷上下文工作  u64 last_sample_time; boolwork_in_progress;
 /* 負載計算相關 */ spinlock_tload_lock;  u64 time_in_idle;  u64 time_in_idle_timestamp;  u64 cputime_speedadj;         // 加權 CPU 時間
 /* 頻率控制 */ spinlock_ttarget_freq_lock; unsignedinttarget_freq; unsignedintfloor_freq;        // 最低允許頻率  u64 pol_floor_val_time;        // 策略級 floor 時間  u64 loc_floor_val_time;        // CPU 級 floor 時間 // ...};/* 調度器回調:每次 CPU 狀態(tài)更新時調用 */staticvoiddbs_update_util_handler(structupdate_util_data *data, u64 time,                 unsignedintflags){ structinteractive_cpu*icpu =container_of(data,structinteractive_cpu, update_util); structinteractive_policy*ipolicy = icpu->ipolicy; structinteractive_tunables*tunables = ipolicy->tunables;  u64 delta_ns, lst; /* 檢查是否可以更新 */ if(!cpufreq_this_cpu_can_update(ipolicy->policy))   return; /* 避免重復工作 */ if(icpu->work_in_progress)   return; /* 檢查采樣間隔 */  lst =READ_ONCE(icpu->last_sample_time);  delta_ns = time - lst; if((s64)delta_ns < tunables->sampling_rate * NSEC_PER_USEC)   return; /* 提交 irq_work,在中斷上下文執(zhí)行 */  icpu->last_sample_time = time;  icpu->work_in_progress =true; irq_work_queue(&icpu->irq_work);}/* 實際頻率評估函數(shù) */staticvoideval_target_freq(structinteractive_cpu *icpu){ structinteractive_tunables*tunables = icpu->ipolicy->tunables; structcpufreq_policy*policy = icpu->ipolicy->policy;  u64 cputime_speedadj, now, max_fvtime; unsignedintnew_freq, loadadjfreq, delta_time; unsignedlongflags; intcpu_load; /* 計算 CPU 負載 */ spin_lock_irqsave(&icpu->load_lock, flags);  now =update_load(icpu,smp_processor_id());  delta_time = (unsignedint)(now - icpu->cputime_speedadj_timestamp);  cputime_speedadj = icpu->cputime_speedadj; spin_unlock_irqrestore(&icpu->load_lock, flags); if(!delta_time)   return; /* 計算負載百分比 */  cpu_load = (unsignedint)(100* cputime_speedadj / delta_time) / policy->cur; spin_lock_irqsave(&icpu->target_freq_lock, flags); /* 根據(jù)負載選擇目標頻率 */  loadadjfreq = cpu_load * policy->cur;
 if(cpu_load >= tunables->go_hispeed_load) {   /* 高負載:進入 hispeed_freq */   if(policy->cur < tunables->hispeed_freq) {      new_freq = tunables->hispeed_freq;    }else{      new_freq =choose_freq(icpu, loadadjfreq);
     /* 檢查 above_hispeed_delay */     if(now - max_fvtime freq_to_above_hispeed_delay(tunables, new_freq))        new_freq =max(new_freq, tunables->hispeed_freq);    }  }else{   /* 低負載:按比例降頻 */    new_freq =choose_freq(icpu, loadadjfreq);  } /* 應用 floor 約束 */ if(new_freq < icpu->floor_freq) {   if(now - icpu->pol_floor_val_time < tunables->min_sample_time)      new_freq = icpu->floor_freq;  } /* 限制在策略范圍內 */  new_freq =max(new_freq, policy->min);  new_freq =min(new_freq, policy->max); /* 提交頻率變更 */ if(new_freq != policy->cur) {    icpu->target_freq = new_freq;   spin_lock(&speedchange_cpumask_lock);   cpumask_set_cpu(smp_processor_id(), &speedchange_cpumask);   spin_unlock(&speedchange_cpumask_lock);   wake_up_process(speedchange_task); // 喚醒內核線程執(zhí)行變更  } spin_unlock_irqrestore(&icpu->target_freq_lock, flags);}

4.2頻率選擇算法choose_freq

interactive調速器的核心算法,用二分查找思想找到滿足負載的最低頻率:

/** 選擇滿足目標負載的最低頻率* 采用二分查找思想,在頻率表中尋找最優(yōu)解*/staticunsignedintchoose_freq(structinteractive_cpu *icpu,               unsignedintloadadjfreq){ structcpufreq_policy*policy = icpu->ipolicy->policy; structcpufreq_frequency_table*freq_table = policy->freq_table; unsignedintprevfreq, freqmin =0, freqmax = UINT_MAX, tl; unsignedintfreq = policy->cur; intindex; do{    prevfreq = freq;
   /* 獲取當前頻率的目標負載 */    tl =freq_to_targetload(icpu->ipolicy->tunables, freq);   /*    * 查找滿足 loadadjfreq / tl <= freq 的最低頻率    * 即:freq >= loadadjfreq / tl    */    index =cpufreq_frequency_table_target(policy, loadadjfreq / tl,                       CPUFREQ_RELATION_L);    freq = freq_table[index].frequency;   if(freq > prevfreq) {     /* 頻率上升:記錄最小值 */      freqmin = prevfreq;     if(freq >= freqmax) {       /* 超過上限,回退 */        index =cpufreq_frequency_table_target(policy, freqmax -1,                           CPUFREQ_RELATION_H);        freq = freq_table[index].frequency;       if(freq == freqmin)         break;      }    }elseif(freq < prevfreq) {     /* 頻率下降:記錄最大值 */      freqmax = prevfreq;     if(freq <= freqmin) {       /* 低于下限,回退 */        index =cpufreq_frequency_table_target(policy, freqmin +1,                           CPUFREQ_RELATION_L);        freq = freq_table[index].frequency;       if(freq == freqmax)         break;      }    }  }while(freq != prevfreq); returnfreq;}

4.3核心層頻率切換:cpufreq_core

核心層負責頻率切換的同步、通知和狀態(tài)管理,保證線程安全:

// drivers/cpufreq/cpufreq.c/* 開始頻率轉換 */voidcpufreq_freq_transition_begin(structcpufreq_policy *policy,                 structcpufreq_freqs *freqs){ /* 防止重復調用導致死鎖 */ WARN_ON(!(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION)      && current == policy->transition_task);wait: /* 等待前一次轉換完成 */ wait_event(policy->transition_wait, !policy->transition_ongoing); spin_lock(&policy->transition_lock); if(unlikely(policy->transition_ongoing)) {   spin_unlock(&policy->transition_lock);   gotowait;  }  policy->transition_ongoing =true;  policy->transition_task = current; spin_unlock(&policy->transition_lock); /* 發(fā)送 PRECHANGE 通知 */ cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);}/* 頻率轉換通知 */staticvoidcpufreq_notify_transition(structcpufreq_policy *policy,                  structcpufreq_freqs *freqs,                  unsignedintstate){ intcpu;  freqs->policy = policy;  freqs->flags = cpufreq_driver->flags; switch(state) { caseCPUFREQ_PRECHANGE:   /* 同步 old frequency */   if(policy->cur && policy->cur != freqs->old) {      freqs->old = policy->cur;    }   /* 調用 transition notifier 鏈 */   srcu_notifier_call_chain(&cpufreq_transition_notifier_list,                CPUFREQ_PRECHANGE, freqs);   /* 調整 loops_per_jiffy */   adjust_jiffies(CPUFREQ_PRECHANGE, freqs);   break; caseCPUFREQ_POSTCHANGE:   adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);   /* 記錄 tracepoint */    for_each_cpu(cpu, policy->cpus)     trace_cpu_frequency(freqs->new, cpu);   /* 調用 transition notifier 鏈 */   srcu_notifier_call_chain(&cpufreq_transition_notifier_list,                CPUFREQ_POSTCHANGE, freqs);   /* 更新統(tǒng)計 */   cpufreq_stats_record_transition(policy, freqs->new);    policy->cur = freqs->new;  }}/* 結束頻率轉換 */voidcpufreq_freq_transition_end(structcpufreq_policy *policy,                structcpufreq_freqs *freqs,                inttransition_failed){ cpufreq_notify_post_transition(policy, freqs, transition_failed); /* 更新頻率縮放比例(用于調度器) */ arch_set_freq_scale(policy->related_cpus,            policy->cur,            policy->cpuinfo.max_freq); spin_lock(&policy->transition_lock);  policy->transition_ongoing =false;  policy->transition_task =NULL; spin_unlock(&policy->transition_lock); wake_up(&policy->transition_wait);}

4.4驅動層實現(xiàn):cpufreq-dt

DT驅動是通用層,對接核心層和平臺層,核心是頻率/電壓的實際設置:

// drivers/cpufreq/cpufreq-dt.c/* 設置目標頻率 */staticintset_target(structcpufreq_policy *policy,unsignedintindex){ structprivate_data*priv = policy->driver_data; unsignedlongfreq = policy->freq_table[index].frequency;#ifdefCONFIG_ARCH_ROCKCHIP /* RK 平臺使用特殊的 OPP 設置函數(shù) */ returnrockchip_cpufreq_opp_set_rate(priv->cpu_dev, freq *1000);#else returndev_pm_opp_set_rate(priv->cpu_dev, freq *1000);#endif}/* 驅動初始化 */staticintcpufreq_init(structcpufreq_policy *policy){ structprivate_data*priv; structdevice*cpu_dev; structclk*cpu_clk; unsignedinttransition_latency; intret;  priv =cpufreq_dt_find_data(policy->cpu); if(!priv) {   pr_err("failed to find data for cpu%dn", policy->cpu);   return-ENODEV;  }  cpu_dev = priv->cpu_dev; /* 獲取 CPU 時鐘 */  cpu_clk =clk_get(cpu_dev,NULL); if(IS_ERR(cpu_clk)) {    ret =PTR_ERR(cpu_clk);   dev_err(cpu_dev,"%s: failed to get clk: %dn", __func__, ret);   returnret;  } /* 獲取最大轉換延遲 */  transition_latency =dev_pm_opp_get_max_transition_latency(cpu_dev); if(!transition_latency)    transition_latency = CPUFREQ_ETERNAL; /* 填充 policy */ cpumask_copy(policy->cpus, priv->cpus);  policy->driver_data = priv;  policy->clk = cpu_clk;  policy->freq_table = priv->freq_table;  policy->suspend_freq =dev_pm_opp_get_suspend_opp_freq(cpu_dev) /1000;  policy->cpuinfo.transition_latency = transition_latency;  policy->dvfs_possible_from_any_cpu =true; /* 支持 boost 模式 */ if(policy_has_boost_freq(policy)) {    ret =cpufreq_enable_boost_support();   if(ret)     gotoout_clk_put;    cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;  } return0;out_clk_put: clk_put(cpu_clk); returnret;}staticstructcpufreq_driverdt_cpufreq_driver = {  .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |      CPUFREQ_IS_COOLING_DEV,  .verify = cpufreq_generic_frequency_table_verify,  .target_index = set_target,  .get = cpufreq_generic_get,  .init = cpufreq_init,  .exit = cpufreq_exit,  .online = cpufreq_online,  .offline = cpufreq_offline,  .register_em = cpufreq_register_em_with_opp,  .name ="cpufreq-dt",  .attr = cpufreq_dt_attr,  .suspend = cpufreq_generic_suspend,};

4.5 RK平臺特殊處理:rockchip_cpufreq

RK3576的定制化邏輯,包括DVFS鎖、Read Margin、多路電壓調節(jié)器:

// drivers/cpufreq/rockchip-cpufreq.c/* RK 平臺頻率設置入口 */introckchip_cpufreq_opp_set_rate(structdevice *dev,unsignedlongtarget_freq){ structcluster_info*cluster; structdev_pm_opp*opp; structrockchip_opp_info*opp_info; structdev_pm_opp_supplysupplies[2] = {0}; unsignedlongfreq; intret =0;  cluster =rockchip_cluster_info_lookup(dev->id); if(!cluster)   return-EINVAL;  opp_info = &cluster->opp_info; /* 獲取 DVFS 鎖,防止并發(fā)修改 */ rockchip_opp_dvfs_lock(opp_info);
 /* 調用 OPP 子系統(tǒng)設置頻率 */  ret =dev_pm_opp_set_rate(dev, target_freq);
 if(!ret) {    cluster->rate = freq = target_freq;
   /* 查找當前 OPP,獲取電壓信息 */    opp =dev_pm_opp_find_freq_ceil(dev, &freq);   if(!IS_ERR(opp)) {     dev_pm_opp_get_supplies(opp, supplies);      cluster->volt = supplies[0].u_volt;     if(opp_info->regulator_count >1)        cluster->mem_volt = supplies[1].u_volt;     dev_pm_opp_put(opp);    }  }
 rockchip_opp_dvfs_unlock(opp_info); returnret;}EXPORT_SYMBOL_GPL(rockchip_cpufreq_opp_set_rate);/* RK3576 Read Margin 設置 */staticintrk3576_cpu_set_read_margin(structdevice *dev,                  structrockchip_opp_info *opp_info,                   u32 rm){ if(!opp_info->volt_rm_tbl)   return0; if(rm == opp_info->current_rm || rm == UINT_MAX)   return0; dev_dbg(dev,"set rm to %dn", rm);
 /* 通過 GRF 配置 Read Margin */ if(opp_info->grf) {   /* CPU0-3 核心 */   regmap_write(opp_info->grf,0x3c,0x001c0000| (rm <2));   regmap_write(opp_info->grf,0x44,0x001c0000| (rm <2));
   /* 觸發(fā)更新 */   regmap_write(opp_info->grf,0x38,0x00020002);   udelay(1);   regmap_write(opp_info->grf,0x38,0x00020000);  }
 /* CCI 接口 */ if(opp_info->cci_grf)   regmap_write(opp_info->cci_grf,0x54,0x001c0000| (rm <2));  opp_info->current_rm = rm; return0;}/* 多路 regulator 配置 */staticintcpu_opp_config_regulators(structdevice *dev,                  structdev_pm_opp *old_opp,                  structdev_pm_opp *new_opp,                  structregulator **regulators,                  unsignedintcount){ structcluster_info*cluster;  cluster =rockchip_cluster_info_lookup(dev->id); if(!cluster)   return-EINVAL; returnrockchip_opp_config_regulators(dev, old_opp, new_opp, regulators,                     count, &cluster->opp_info);}

流程圖:RK3576頻率調整完整流程

st=>start: 調度器觸發(fā)負載更新op1=>operation: interactive調速器(eval_target_freq)op2=>operation: 計算CPU負載,選擇目標頻率op3=>operation: 核心層(cpufreq_freq_transition_begin)op4=>operation: 發(fā)送PRECHANGE通知op5=>operation: 驅動層(set_target)op6=>operation: RK平臺(rockchip_cpufreq_opp_set_rate)op7=>operation: OPP子系統(tǒng)(dev_pm_opp_set_rate)op8=>operation: 升頻:先升壓后升頻;降頻:先降頻后降壓op9=>operation: 核心層(cpufreq_freq_transition_end)op10=>operation: 發(fā)送POSTCHANGE通知,更新統(tǒng)計e=>end: 頻率切換完成st->op1->op2->op3->op4->op5->op6->op7->op8->op9->op10->e

五、OPP子系統(tǒng):頻率-電壓表的奧秘

OPPOperating Performance Point)是連接軟件和硬件的關鍵,定義了頻率-電壓的映射關系,是DVFS的基礎。

5.1 OPP數(shù)據(jù)結構

// include/linux/pm_opp.hstructdev_pm_opp{ structlist_headnode;
 unsignedlongrate;     // 頻率 (Hz) unsignedlongu_volt;    // 電壓 (uV) unsignedlongu_volt_min;  // 最小電壓 unsignedlongu_volt_max;  // 最大電壓
 structdevice_opp*dev_opp; // 所屬設備
 /* 支持的條件 */ unsignedlongsupported_hw; // 硬件版本掩碼
 /* 供電信息 */ structopp_supply*supplies; unsignedintsupply_count;
 /* 自定義數(shù)據(jù) */ void*priv;};structdevice_opp{ structlist_headnode; structdevice*dev; structsrcu_notifier_headsrcu_head; structlist_headopp_list;
 structclk*clk; structregulator**regulators; unsignedintregulator_count;
 structopp_table*opp_table;};

5.2 Device Tree OPP定義

RK3576OPP表在DTS中定義,不同芯片版本支持不同頻率:

// arch/arm64/boot/dts/rockchip/rk3576.dtsicpu0_opp_table:opp-table-0{  compatible ="operating-points-v2";  opp-shared;
 /* 408 MHz */  opp-408000000{    opp-hz =/bits/64<408000000>;    opp-microvolt = <800000>;    clock-latency-ns = <40000>;  };
 /* 600 MHz */  opp-600000000{    opp-hz =/bits/64<600000000>;    opp-microvolt = <825000>;  };
 /* 816 MHz */  opp-816000000{    opp-hz =/bits/64<816000000>;    opp-microvolt = <850000>;  };
 /* 1.2 GHz */  opp-1200000000{    opp-hz =/bits/64<1200000000>;    opp-microvolt = <925000>;  };
 /* 1.608 GHz - 僅支持特定芯片版本 */  opp-1608000000{    opp-hz =/bits/64<1608000000>;    opp-microvolt = <1100000>;    opp-supported-hw = <0x10x1>; //bin=0, volt_sel=0  };
 /* 1.8 GHz - 更高規(guī)格芯片 */  opp-1800000000{    opp-hz =/bits/64<1800000000>;    opp-microvolt = <1175000>;    opp-supported-hw = <0x10x3>; //bin=0, volt_sel=0,1,2  };};

5.3 OPP查找與設置流程

OPP子系統(tǒng)的核心函數(shù),負責頻率/電壓的實際設置:

// drivers/opp/core.c/*** dev_pm_opp_set_rate() - 設置設備到指定頻率* @dev: 設備* @target_freq: 目標頻率 (Hz)** 1. 查找匹配的 OPP* 2. 設置 regulator 電壓* 3. 設置時鐘頻率*/intdev_pm_opp_set_rate(structdevice *dev,unsignedlongtarget_freq){ structdevice_opp*dev_opp; structdev_pm_opp*opp; structclk*clk; unsignedlongold_freq, new_freq; intret;  dev_opp = _find_device_opp(dev); if(IS_ERR(dev_opp))   returnPTR_ERR(dev_opp);  clk = dev_opp->clk;  old_freq =clk_get_rate(clk); /* 查找目標頻率對應的 OPP */  opp = _find_freq_ceil(dev_opp, &target_freq); if(IS_ERR(opp)) {    ret =PTR_ERR(opp);   gotoput_opp;  }  new_freq = opp->rate; /* 如果頻率相同,只更新電壓 */ if(new_freq == old_freq) {    ret = _set_opp_voltage(dev, dev_opp, opp);   gotoput_opp;  } /* 升頻:先升壓,后升頻 */ if(new_freq > old_freq) {    ret = _set_opp_voltage(dev, dev_opp, opp);   if(ret)     gotoput_opp;
    ret =clk_set_rate(clk, new_freq);   if(ret) {     /* 回滾電壓 */      _set_opp_voltage(dev, dev_opp, _find_freq_floor(dev_opp, &old_freq));    }  }else{   /* 降頻:先降頻,后降壓 */    ret =clk_set_rate(clk, new_freq);   if(ret)     gotoput_opp;
    _set_opp_voltage(dev, dev_opp, opp);  }put_opp: dev_pm_opp_put(opp); returnret;}

流程圖:OPP頻率-電壓設置流程

st=>start: 調用dev_pm_opp_set_rateop1=>operation: 查找設備對應的device_oppop2=>operation: 獲取當前時鐘頻率(old_freq)op3=>operation: 查找目標頻率的OPP(ceil)op4=>operation: 判斷new_freq == old_freq?op5=>operation: 僅更新電壓(_set_opp_voltage)op6=>operation: new_freq > old_freq?op7=>operation: 先升壓,后升頻op8=>operation: 升頻失敗,回滾電壓op9=>operation: 先降頻,后降壓e=>end: 返回設置結果st->op1->op2->op3->op4op4(yes)->op5->eop4(no)->op6op6(yes)->op7->eop7(no)->op8->eop6(no)->op9->e

六、通知鏈機制:頻率變更的廣播系統(tǒng)

cpufreq的通知鏈是事件廣播機制,允許其他子系統(tǒng)(如溫控、功耗管理)監(jiān)聽頻率變更事件,是內核模塊化設計的典型體現(xiàn)。

6.1兩種通知鏈

// drivers/cpufreq/cpufreq.c/* 策略通知鏈:策略創(chuàng)建/銷毀時調用 */staticBLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);/* 轉換通知鏈:頻率變更前后調用 */SRCU_NOTIFIER_HEAD_STATIC(cpufreq_transition_notifier_list);

6.2 RK平臺的通知器注冊

RK3576通過通知鏈實現(xiàn)頻率-空閑狀態(tài)聯(lián)動、總線QoS約束:

// drivers/cpufreq/rockchip-cpufreq.c/* 策略通知器:處理監(jiān)控注冊和總線 QoS */staticintrockchip_cpufreq_notifier(structnotifier_block *nb,                  unsignedlongevent,void*data){ structcpufreq_policy *policy = data; structcluster_info *cluster;  cluster = rockchip_cluster_info_lookup(policy->cpu); if(!cluster)   returnNOTIFY_BAD; switch(event) { caseCPUFREQ_CREATE_POLICY:   /* 注冊系統(tǒng)監(jiān)控 */   if(rockchip_cpufreq_add_monitor(cluster, policy))     returnNOTIFY_BAD;
   /* 添加總線頻率 QoS 約束 */   if(rockchip_cpufreq_add_bus_qos_req(cluster, policy))     returnNOTIFY_BAD;   break; caseCPUFREQ_REMOVE_POLICY:    rockchip_cpufreq_remove_monitor(cluster);    rockchip_cpufreq_remove_bus_qos(cluster);   break;  } returnNOTIFY_OK;}/* 轉換通知器:處理空閑狀態(tài) */staticintrockchip_cpufreq_transition_notifier(structnotifier_block *nb,                        unsignedlongevent,void*data){ structcpufreq_freqs *freqs = data; structcpufreq_policy *policy = freqs->policy; structcluster_info *cluster;  cluster = rockchip_cluster_info_lookup(policy->cpu); if(!cluster)   returnNOTIFY_BAD; switch(event) { caseCPUFREQ_PRECHANGE:   /* 高頻時禁用深層空閑狀態(tài) */   if(cluster->idle_threshold_freq &&      freqs->new>= cluster->idle_threshold_freq &&      !cluster->is_idle_disabled) {      rockchip_cpufreq_idle_state_disable(policy->cpus,1,true);      cluster->is_idle_disabled =true;    }   break; caseCPUFREQ_POSTCHANGE:   /* 低頻時重新啟用空閑狀態(tài) */   if(cluster->idle_threshold_freq &&      freqs->new< cluster->idle_threshold_freq &&      cluster->is_idle_disabled) {      rockchip_cpufreq_idle_state_disable(policy->cpus,1,false);      cluster->is_idle_disabled =false;    }
   /* 更新總線頻率請求 */    rockchip_cpufreq_update_bus_req(cluster, freqs->new);   break;  } returnNOTIFY_OK;}

6.3使用場景示例

溫控驅動通過通知鏈監(jiān)聽頻率變更,更新熱模型:

/* 溫度管理驅動注冊通知器 */staticintthermal_cpufreq_notifier(structnotifier_block *nb,                  unsignedlongevent,void*data){ structcpufreq_freqs *freqs = data;
 if(event== CPUFREQ_POSTCHANGE) {   /* 頻率變更后更新熱模型 */    update_thermal_model(freqs->new);  }
 returnNOTIFY_OK;}staticstructnotifier_block thermal_nb = {  .notifier_call = thermal_cpufreq_notifier,};/* 注冊 */cpufreq_register_notifier(&thermal_nb, CPUFREQ_TRANSITION_NOTIFIER);

七、統(tǒng)計與調試:洞察系統(tǒng)行為

掌握調試技巧,才能快速定位頻率調節(jié)的問題,cpufreq提供了豐富的統(tǒng)計和調試接口。

7.1統(tǒng)計模塊實現(xiàn)

// drivers/cpufreq/cpufreq_stats.cstructcpufreq_stats{ unsignedinttotal_trans;     // 總切換次數(shù) unsignedlonglonglast_time;   // 上次更新時間 unsignedintmax_state;      // 最大狀態(tài)數(shù) unsignedintstate_num;      // 實際狀態(tài)數(shù) unsignedintlast_index;      // 當前狀態(tài)索引  u64 *time_in_state;        // 各頻率駐留時間 unsignedint*freq_table;     // 頻率表 unsignedint*trans_table;     // 切換矩陣};/* 記錄一次頻率切換 */voidcpufreq_stats_record_transition(structcpufreq_policy *policy,                  unsignedintnew_freq){ structcpufreq_stats*stats = policy->stats; intold_index, new_index; if(!stats)   return;  old_index = stats->last_index;  new_index =freq_table_get_index(stats, new_freq); if(old_index ==-1|| new_index ==-1|| old_index == new_index)   return; /* 更新駐留時間 */ cpufreq_stats_update(stats, stats->last_time);  stats->last_index = new_index;  stats->trans_table[old_index * stats->max_state + new_index]++;  stats->total_trans++;}

7.2調試技巧

# 1. 查看當前頻率和策略cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freqcat/sys/devices/system/cpu/cpu0/cpufreq/scaling_governorcat/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freqcat/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq# 2. 查看頻率駐留時間統(tǒng)計cat/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state# 輸出格式: 頻率(Hz) 時間(時鐘周期)# 408000 1234567# 600000 2345678# ...# 3. 查看頻率切換矩陣cat/sys/devices/system/cpu/cpu0/cpufreq/stats/trans_table# 顯示從每個頻率切換到其他頻率的次數(shù)# 4. 查看可用頻率和調速器cat/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequenciescat/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors# 5. 動態(tài)切換調速器echouserspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governorecho1200000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed# 6. 內核日志調試dmesg | grep -i cpufreqdmesg | grep -i"rk3576|rockchip"# 7. 使用 tracepointcd/sys/kernel/debug/tracingecho1 > events/cpufreq/enablecattrace

八、實戰(zhàn):自定義調速器開發(fā)

掌握自定義調速器的開發(fā),才能適配特定場景的性能/功耗需求。

8.1最小調速器框架

#include#includestaticintmygov_target(structcpufreq_policy *policy,unsignedinttarget_freq,           unsignedintrelation){ /* 簡單的頻率設置 */ return__cpufreq_driver_target(policy, target_freq, relation);}staticintmygov_init(structcpufreq_policy *policy){ /* 初始化 */ return0;}staticvoidmygov_exit(structcpufreq_policy *policy){ /* 清理 */}staticstructcpufreq_governormy_governor = {  .name ="mygov",  .target = mygov_target,  .init = mygov_init,  .exit = mygov_exit,  .owner = THIS_MODULE,};staticint__initmygov_init_module(void){ returncpufreq_register_governor(&my_governor);}staticvoid__exitmygov_exit_module(void){ cpufreq_unregister_governor(&my_governor);}module_init(mygov_init_module);module_exit(mygov_exit_module);MODULE_LICENSE("GPL");

8.2基于負載的調速器

staticvoidmygov_update(structcpufreq_policy *policy){ unsignedintload =calculate_cpu_load(policy); unsignedintnew_freq; if(load >80) {   /* 高負載:升頻到最大 */    new_freq = policy->max;  }elseif(load 20) {   /* 低負載:降頻到最小 */    new_freq = policy->min;  }else{   /* 中等負載:線性插值 */    new_freq = policy->min + load * (policy->max - policy->min) /100;  }  __cpufreq_driver_target(policy, new_freq, CPUFREQ_RELATION_H);}

腦圖:自定義調速器開發(fā)

wKgZPGnRtT2AIFMJAAHLeSBcols237.png

九、性能優(yōu)化實戰(zhàn)

針對實際開發(fā)中的痛點,優(yōu)化頻率切換延遲、負載計算精度。

9.1減少頻率切換延遲

/* 1. 使用 fast frequency switching */staticstructcpufreq_drivermy_driver={  .flags=CPUFREQ_FAST_SWITCHING,  .fast_switch=my_fast_switch, // 原子上下文切換};/* 2. 減少 transition latency */// 在 OPP 表中設置較小的 clock-latency-nsopp-1200000000{  opp-hz=/bits/64<1200000000>;  clock-latency-ns=<10000>; // 10us,而不是 40us};

9.2優(yōu)化負載計算

/* 使用 PELT 信號代替 idle time */#includestaticunsignedintget_pelt_load(structcpufreq_policy *policy){ unsignedintcpu = policy->cpu; structrq*rq =cpu_rq(cpu);
 /* PELT (Per-Entity Load Tracking) 是調度器內部的負載跟蹤機制 */ returnrq->cfs.avg.util_avg; // 0 ~ 1024}

腦圖:性能優(yōu)化實戰(zhàn)

wKgZPGnRtT2ATjvXAAHk74WONG8190.png

十、總結與延伸

10.1核心要點回顧

1.分層架構governor → core → driver → OPP → clk/regulator

2.線程安全transition_lock、DVFS locknotifier chain

3.硬件抽象OPP表統(tǒng)一頻率-電壓關系

4.平臺特性RK3576Read Margin、多路regulator

10.2延伸閱讀

?Documentation/cpu-freq/-內核文檔

?drivers/opp/- OPP子系統(tǒng)實現(xiàn)

?drivers/cpufreq/cpufreq_schedutil.c-最新schedutil調速器

?include/linux/cpufreq.h-完整API定義

10.3調試checklist

dmesg | grep cpufreq查看初始化日志

cat scaling_available_frequencies確認頻率表

cat time_in_state確認頻率切換正常

trace-cmd record -e cpufreq抓取切換事件

檢查regulator是否支持動態(tài)電壓調節(jié)

寫在最后

cpufreqLinux內核中最接近硬件的子系統(tǒng)之一,理解它不僅能幫你優(yōu)化系統(tǒng)性能,更能深入理解內核的設備模型、電源管理和并發(fā)控制機制。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5210

    文章

    20679

    瀏覽量

    337347
  • Linux
    +關注

    關注

    88

    文章

    11821

    瀏覽量

    219600
  • rk3576
    +關注

    關注

    1

    文章

    304

    瀏覽量

    1685
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    基于RK3576開發(fā)板的PWN使用說明

    RK3576開發(fā)板使用PWN教程及Demo
    的頭像 發(fā)表于 05-07 14:07 ?2525次閱讀
    基于<b class='flag-5'>RK3576</b>開發(fā)板的PWN使用說明

    【米爾RK3576開發(fā)板評測】+項目名稱【米爾RK3576開發(fā)板評測】一個視頻和你共同認識一下米爾RK3576開發(fā)板

    TOPS超強算力,8核CPU賦能AI 瑞芯微RK3576搭載了四核A72與四核A53處理器,主頻高達2.2GHz,確保了系統(tǒng)的高效運行和強大的計算能力。RK3576集成了6TOPS的NPU,支持多種深度
    發(fā)表于 12-18 20:50

    米爾RK3576RK3588怎么選?-看這篇就夠了

    在中國半導體產業(yè)的版圖中,瑞芯微作為國內SoC芯片領跑者,憑借其在處理器芯片設計領域的深厚積累和持續(xù)創(chuàng)新,推出很多智能應用處理器芯片,在嵌入式系統(tǒng)領域得到大規(guī)模的應用。RK3588和RK3576系列
    發(fā)表于 12-27 11:44

    性能到成本,深度剖析 RK3588 與 RK3576 怎么選

    在中國半導體產業(yè)的版圖中,瑞芯微作為國內SoC芯片領跑者,憑借其在處理器芯片設計領域的深厚積累和持續(xù)創(chuàng)新,推出很多智能應用處理器芯片,在嵌入式系統(tǒng)領域得到大規(guī)模的應用。RK3588和RK3576系列
    發(fā)表于 02-09 09:10

    RK3576 vs RK3588:為何越來越多的開發(fā)者轉向RK3576

    的成本結構以及針對特定場景的深度優(yōu)化,正在成為中高端市場的熱門選擇。那么,RK3576 究竟有哪些優(yōu)勢?它是否真的能替代 RK3588?我們來做一個全面對比。 1. 核心性能對比:夠用且高效[td
    發(fā)表于 05-30 08:46

    Mpp支持RK3576

    想問下,https://github.com/rockchip-linux/mpp這里面支持RK3576么,看介紹沒有提到說支持RK3576 目前是買了個rk3576的機頂盒,搭載了安卓14,想做安卓視頻硬解。
    發(fā)表于 06-13 15:35

    【作品合集】米爾RK3576開發(fā)板測評

    米爾RK3576開發(fā)板測評作品合集 產品介紹: RK3576 是瑞芯微一款面向AI市場推出的高性能處理器,它配備了四核Cortex-A72和四 核Cortex-A53 的 CPU,集成了6TOPS
    發(fā)表于 09-11 10:19

    新品體驗 | RK3576開發(fā)板

    前言:RK3576作為瑞芯微第二代8nm高性能AIOT平臺,一經(jīng)推出便獲得了極大的關注。廣州眺望電子科技有限公司是一家專注于嵌入式處理器模組研發(fā)與應用的國家高新技術企業(yè),目前公司已推出的相關型號有
    的頭像 發(fā)表于 11-01 08:08 ?3435次閱讀
    新品體驗 | <b class='flag-5'>RK3576</b>開發(fā)板

    RK3576單板發(fā)布倒計時:RK3399與RK3576對比

    好多人說RK3576RK3399的升級版,某種程度上也可以這么說,RK3576在強大的多媒體功能的基礎上,性能和接口都進行了升級 一、工藝 性能 rk3576采用 Rockchip
    的頭像 發(fā)表于 12-03 16:59 ?2798次閱讀
    <b class='flag-5'>RK3576</b>單板發(fā)布倒計時:<b class='flag-5'>RK</b>3399與<b class='flag-5'>RK3576</b>對比

    RK3588與RK3576區(qū)別解析

    以下是RK3576RK3588對比: 電魚電子SBC-RK3576單板 核心性能:RK3576為四核A72@2.2GHz + 四核A53@1.8GHz + M0協(xié)處理器,算力 58K
    的頭像 發(fā)表于 12-17 14:03 ?4468次閱讀
    <b class='flag-5'>RK</b>3588與<b class='flag-5'>RK3576</b>區(qū)別解析

    想學人工智能AI?我建議RK3576!

    RK3576擁有強大的計算性能,輕松應對深度學習、圖像處理等高負載任務! 高效能低功耗:無論是訓練模型還是推理應用,都能保持高效穩(wěn)定,續(xù)航更持久! 豐富接口:支持多種外設連接,滿足你的多樣化開發(fā)需求! 性價比超高:相比同類產品,RK3
    的頭像 發(fā)表于 02-25 07:44 ?2058次閱讀
    想學人工智能AI?我建議<b class='flag-5'>RK3576</b>!

    瑞芯微RK3576RK3576S有什么區(qū)別,性能參數(shù)配置與型號差異解析

    瑞芯微第二代8nm高性能AIOT平臺RK3576家族再添新成員-RK3576S,先說結論:相較主型號的RK3576/RK3576J,性能略有縮減,而功耗有所降低。主要應用于商顯終端、智
    的頭像 發(fā)表于 08-14 23:57 ?2757次閱讀
    瑞芯微<b class='flag-5'>RK3576</b>與<b class='flag-5'>RK3576</b>S有什么區(qū)別,性能參數(shù)配置與型號差異解析

    一文打通Rockchip DP調試:理到實戰(zhàn),覆蓋RK3399/RK3576/RK3588全平臺

    嵌入式開發(fā)中,DisplayPort(DP)接口的調試常讓工程師頭疼 —— 不同芯片特性差異大、Type-C 與標準口配置不同、高分辨率輸出異常、MST 多屏適配難… 尤其是 Rockchip RK3399、RK3576、RK3
    的頭像 發(fā)表于 02-04 16:14 ?1027次閱讀
    一文打通Rockchip DP調試:<b class='flag-5'>從</b>原<b class='flag-5'>理到</b><b class='flag-5'>實戰(zhàn)</b>,覆蓋<b class='flag-5'>RK</b>3399/<b class='flag-5'>RK3576</b>/<b class='flag-5'>RK</b>3588全平臺

    迅為如何在RK3576上部署YOLOv5;基于RK3576構建智能門禁系統(tǒng)

    迅為如何在RK3576開發(fā)板上部署YOLOv5;基于RK3576構建智能門禁系統(tǒng)
    的頭像 發(fā)表于 11-25 14:06 ?1996次閱讀
    迅為如何在<b class='flag-5'>RK3576</b>上部署YOLOv5;基于<b class='flag-5'>RK3576</b>構建智能門禁系統(tǒng)

    硬核進階:RK3576 Android15?驅動與系統(tǒng)開發(fā)實戰(zhàn)指南

    RK3576 探索之旅】系列文章導航及功能全景介紹(基于android14) 之前有出過系列的文章,但這是自己公司定制項目,暫時沒有相關硬件,有需求可以私信我,這個系列主要還是驅動的開發(fā),接下來
    的頭像 發(fā)表于 01-26 22:29 ?839次閱讀
    硬核進階:<b class='flag-5'>RK3576</b> Android15?<b class='flag-5'>驅動</b>與系統(tǒng)開發(fā)<b class='flag-5'>實戰(zhàn)</b>指南
    湖州市| 安徽省| 哈巴河县| 雷山县| 黎城县| 府谷县| 祁门县| 阳曲县| 蓝田县| 阿勒泰市| 赣州市| 温州市| 新津县| 汝州市| 济阳县| 基隆市| 天水市| 阜南县| 茌平县| 凤冈县| 兴文县| 军事| 六安市| 定州市| 三都| 景洪市| 扶沟县| 灵台县| 金山区| 靖远县| 锡林浩特市| 克拉玛依市| 卢湾区| 田阳县| 呼伦贝尔市| 衢州市| 石城县| 油尖旺区| 闻喜县| 墨江| 威海市|