當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式微處理器
[導(dǎo)讀]之前做過(guò)一次 uboot的升級(jí),當(dāng)時(shí)留下了一些記錄,本文摘錄其中比較有意思的兩個(gè)問(wèn)題。

背景

之前做過(guò)一次 uboot的升級(jí),當(dāng)時(shí)留下了一些記錄,本文摘錄其中比較有意思的兩個(gè)問(wèn)題。

啟動(dòng)失敗問(wèn)題

問(wèn)題簡(jiǎn)述

uboot代碼中用到了一個(gè)庫(kù),考慮到庫(kù)本身跟 uboot版本沒(méi)什么關(guān)系,就直接把舊的庫(kù)文件拷貝過(guò)來(lái)使用。結(jié)果編譯鏈接是沒(méi)問(wèn)題,啟動(dòng)卻會(huì)卡住。

消失的打印

為了明確卡住的位置,就去修改了庫(kù)的源碼,添加一些打?。ù藭r(shí)還是在舊版本 uboot下編譯的),結(jié)果發(fā)現(xiàn)卡住的位置或隨著添加打印的變化而變化,且有些打印語(yǔ)句,添加后未打印出來(lái)。
我決定先從這些神秘消失的打印入手。
分析下 uboot中的 printf實(shí)現(xiàn),最底層就是寫(xiě)寄存器,是一個(gè)同步的函數(shù),也沒(méi)什么可疑的地方。
為了確認(rèn)打印不出來(lái)的時(shí)候,到底有沒(méi)有調(diào)用到 printf,我決定給 printf增加一個(gè)計(jì)數(shù)器,在 gd結(jié)構(gòu)體中,增加一個(gè) printf_count字段,初始化為 0,每次打印時(shí)執(zhí)行 printf_count++并打印出值。
設(shè)計(jì)這個(gè)試驗(yàn),本意是確認(rèn)未打印出來(lái)時(shí)是否確實(shí)也調(diào)用到了 printf,但卻有了別的發(fā)現(xiàn),實(shí)驗(yàn)結(jié)果中 printf_count值會(huì)異常變化,不是按打印順序遞增,而是會(huì)突變成很大的異常值。
printf_countgd結(jié)構(gòu)體的成員,那就是 gd的問(wèn)題了。進(jìn)一步將 uboot全局結(jié)構(gòu)體 gd的地址打印出來(lái)。確認(rèn)了原因是 gd結(jié)構(gòu)體的指針變化了。
這也可以解釋部分打印消失的現(xiàn)象,原因是我們?cè)? gd中有另一個(gè)字段,用于控制打印等級(jí)。當(dāng) gd被改動(dòng)了, printf就可能解析出錯(cuò),誤以為打印等級(jí)為 0而提前返回。

gd的實(shí)現(xiàn)

那么好端端的, gd為什么會(huì)被改了呢?這就要先看看 gd到底是怎么實(shí)現(xiàn)的了。
uboot中維護(hù)了一個(gè)全局的結(jié)構(gòu)體 gd。在代碼中加入

    
DECLARE_GLOBAL_DATA_PTR;
即可使用 gd指針訪問(wèn)這個(gè)全局結(jié)構(gòu)體,許多地方都會(huì)借助 gd來(lái)保存?zhèn)鬟f信息。
進(jìn)一步看看這個(gè)宏的定義

    
舊版本uboot:
#define?DECLARE_GLOBAL_DATA_PTR????????register?volatile?gd_t?*gd?asm?("r8")

新版本uboot:
#define?DECLARE_GLOBAL_DATA_PTR????????register?volatile?gd_t?*gd?asm?("r9")
居然不一樣,一個(gè)是將 gd的值放到 r8寄存器,一個(gè)是放在 r9寄存器。
那么就可以猜測(cè)到,庫(kù)是在舊版本 uboot中編譯出來(lái)的,可能使用了 r9,那么放到新版本 uboot中去,就會(huì)破壞 r9寄存器中保存的 gd值,導(dǎo)致一系列依賴 gd的代碼不能正常工作。

驗(yàn)證改動(dòng)

為了求證,將庫(kù)反匯編出來(lái),發(fā)現(xiàn)確實(shí)避開(kāi)了 r8寄存器,但使用了 r9寄存器。
說(shuō)明 uboot在指定 gd寄存器的同時(shí),還有某種方法讓其他代碼不使用這個(gè)寄存器。
那是不是把舊 uboot中的這個(gè) r8改成 r9,重新編譯庫(kù)就可以了呢?試一下,還是不行。
那么禁止其他代碼使用 r8寄存器肯定就是通過(guò)別的方式實(shí)現(xiàn)的了。簡(jiǎn)單粗暴地在舊版本 uboot下搜索 r8,去掉 .c .h等類型后,很容易發(fā)現(xiàn)了

    
./arch/arm/cpu/armv7/config.mk:24:PLATFORM_RELFLAGS?+=?-fno-common?-ffixed-r8?-msoft-floa
-ffixed-r8修改為 -ffixed-r9,重新編譯出庫(kù),這回就可以正常工作了,打印正常,啟動(dòng)正常。反匯編出來(lái)也可以看到,新編譯出來(lái)的庫(kù)用了 r8沒(méi)有用 r9
當(dāng)然更好的改法,是直接在新版本的 uboot中編譯,這是最可靠的。

追本溯源

話說(shuō)回來(lái),為什么兩個(gè)版本的 uboot,會(huì)使用不同的寄存器呢?難道有什么坑?
這就得去翻一下 git記錄了。

    
commit?fe1378a961e508b31b1f29a2bb08ba1dac063155
Author:?Jeroen?Hofstee?
Date:???Sat?Sep?21?14:04:41?2013?+0200

????ARM:?use?r9? for?gd
????
????To?be?more?EABI?compliant?and?as?a?preparation? for?building
????with?clang,?use?the?platform-specific?r9?register? for?gd
????instead?of?r8.
????
????note:?The?FIQ?is?not?updated?since?it?is?not?used? in?u-boot,
????and?under?discussion? for?the?time?being.
????
????The?following?checkpatch?warning?is?ignored:
????WARNING:?Use?of?volatile?is?usually?wrong:?see
????Documentation/volatile-considered-harmful.txt
????
????Signed-off-by:?Jeroen?Hofstee?
????cc:?Albert?ARIBAUD?
git記錄中,也可以確認(rèn)完整地將 r8切換到 r9,都需要做哪些修改

    
diff?--git?a/arch/arm/config.mk?b/arch/arm/config.mk
index? 16c2e3d1e0..d0cf43ff41? 100644
---?a/arch/arm/config.mk
+++?b/arch/arm/config.mk
@@? -17, 7?+ 17, 7?@@?endif
?
?LDFLAGS_FINAL?+=?--gc-sections
?PLATFORM_RELFLAGS?+=?-ffunction-sections?-fdata-sections?\
-?????????????????????-fno-common?-ffixed-r8?-msoft- float
+?????????????????????-fno-common?-ffixed-r9?-msoft- float
?
?#?Support?generic?board?on?ARM
?__HAVE_ARCH_GENERIC_BOARD?:=?y
diff?--git?a/arch/arm/cpu/armv7/lowlevel_init.S?b/arch/arm/cpu/armv7/lowlevel_init.S
index? 82b2b86520. .69e3053a42? 100644
---?a/arch/arm/cpu/armv7/lowlevel_init.S
+++?b/arch/arm/cpu/armv7/lowlevel_init.S
@@? -22, 11?+ 22, 11?@@?ENTRY(lowlevel_init)
????????ldr?????sp,?=CONFIG_SYS_INIT_SP_ADDR
????????bic?????sp,?sp,?# 7? /*?8-byte?alignment?for?ABI?compliance?*/
?#ifdef?CONFIG_SPL_BUILD
-???????ldr?????r8,?=gdata
+???????ldr?????r9,?=gdata
?# else
????????sub?????sp,?#GD_SIZE
????????bic?????sp,?sp,?# 7
-???????mov?????r8,?sp
+???????mov?????r9,?sp
?#endif
???????? /*
?????????*?Save?the?old?lr(passed?in?ip)?and?the?current?lr?to?stack
diff?--git?a/arch/arm/include/asm/global_data.h?b/arch/arm/include/asm/global_data.h
index?79a9597419..e126436093?100644
---?a/arch/arm/include/asm/global_data.h
+++?b/arch/arm/include/asm/global_data.h
@@?-47,6?+47,6?@@?struct?arch_global_data?{
?
?#include?
?
-#define?DECLARE_GLOBAL_DATA_PTR?????register?volatile?gd_t?*gd?asm?("r8")
+#define?DECLARE_GLOBAL_DATA_PTR?????register?volatile?gd_t?*gd?asm?("r9")
?
?#endif?/*?__ASM_GBL_DATA_H?*/

diff?--git?a/arch/arm/lib/crt0.S?b/arch/arm/lib/crt0.S
index? 960d12e732..ac54b9359a? 100644
---?a/arch/arm/lib/crt0.S
+++?b/arch/arm/lib/crt0.S
@@? -69, 7?+ 69, 7?@@?ENTRY(_main)
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
????????sub?????sp,?#GD_SIZE???? /*?allocate?one?GD?above?SP?*/
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
-???????mov?????r8,?sp?????????? /*?GD?is?above?SP?*/
+???????mov?????r9,?sp?????????? /*?GD?is?above?SP?*/
????????mov?????r0,?# 0
????????bl??????board_init_f
?
@@? -81, 15?+ 81, 15?@@?ENTRY(_main)
??*? 'here'?but?relocated.
??*/
?
-???????ldr?????sp,?[r8,?#GD_START_ADDR_SP]????? /*?sp?=?gd->start_addr_sp?*/
+???????ldr?????sp,?[r9,?#GD_START_ADDR_SP]????? /*?sp?=?gd->start_addr_sp?*/
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
-???????ldr?????r8,?[r8,?#GD_BD]???????????????? /*?r8?=?gd->bd?*/
-???????sub?????r8,?r8,?#GD_SIZE???????????????? /*?new?GD?is?below?bd?*/
+???????ldr?????r9,?[r9,?#GD_BD]???????????????? /*?r9?=?gd->bd?*/
+???????sub?????r9,?r9,?#GD_SIZE???????????????? /*?new?GD?is?below?bd?*/
?
????????adr?????lr,?here
-???????ldr?????r0,?[r8,?#GD_RELOC_OFF]????????? /*?r0?=?gd->reloc_off?*/
+???????ldr?????r0,?[r9,?#GD_RELOC_OFF]????????? /*?r0?=?gd->reloc_off?*/
????????add?????lr,?lr,?r0
-???????ldr?????r0,?[r8,?#GD_RELOCADDR]????????? /*?r0?=?gd->relocaddr?*/
+???????ldr?????r0,?[r9,?#GD_RELOCADDR]????????? /*?r0?=?gd->relocaddr?*/
????????b???????relocate_code
?here:
?
@@? -111, 8?+ 111, 8?@@?clbss_l:cmp?r0,?r1?????????????????? /*?while?not?at?end?of?BSS?*/
????????bl?red_led_on
?
???????? /*?call?board_init_r(gd_t?*id,?ulong?dest_addr)?*/
-???????mov?????r0,?r8?????????????????? /*?gd_t?*/
-???????ldr?????r1,?[r8,?#GD_RELOCADDR]? /*?dest_addr?*/
+???????mov?????r0,?r9?????????????????? /*?gd_t?*/
+???????ldr?????r1,?[r9,?#GD_RELOCADDR]? /*?dest_addr?*/
???????? /*?call?board_init_r?*/
????????ldr?????pc,?=board_init_r??????? /*?this?is?auto-relocated!?*/

啟動(dòng)慢問(wèn)題

問(wèn)題簡(jiǎn)述

填了幾個(gè)坑之后,新的 uboot可以啟動(dòng)到內(nèi)核了,但發(fā)現(xiàn)啟動(dòng)速度非常慢,內(nèi)核啟動(dòng)速度慢了接近 10倍!明明是同一個(gè)內(nèi)核,為什么差異這么大。

排查寄存器

初步排查了下設(shè)備樹(shù)配置,以及 uboot跳轉(zhuǎn)內(nèi)核前的一些關(guān)鍵寄存器,確實(shí)在兩個(gè)版本的 uboot中有所不同,但具體去看這些不同,發(fā)現(xiàn)都不會(huì)影響速度,將一些驅(qū)動(dòng)對(duì)齊之后寄存器差異基本就消失了。

差異的分界

那再細(xì)看, kernel的速度有差異, uboot呢?在哪個(gè)時(shí)間點(diǎn)之后,速度開(kāi)始產(chǎn)生差異?
嘗試在兩個(gè)版本的 uboot中插入一些操作,對(duì)比時(shí)間戳,發(fā)現(xiàn)兩個(gè) uboot在某個(gè)節(jié)點(diǎn)之后的速度確實(shí)有區(qū)別。
進(jìn)一步排查,原來(lái)是在打開(kāi) cache操作之后,舊 uboot的速度就會(huì)比新 uboot快。嘗試將舊 ubootcache關(guān)掉,則二者基本一致。嘗試將舊 uboot操作 cache的代碼,移植到新 uboot,未發(fā)生改變。
此時(shí)可確認(rèn)新 uboot的開(kāi) cache有問(wèn)題。但覺(jué)得這個(gè)跟 kernel啟動(dòng)慢沒(méi)關(guān)系。因?yàn)? uboot進(jìn)入 kernel之前都會(huì)關(guān) cache,由 kernel自己去重新打開(kāi)。
也就是不管是用哪份 uboot,也不管 uboot中是否開(kāi)了 cache,對(duì) kernel階段都應(yīng)該沒(méi)有影響才對(duì)。
于是記錄下來(lái) uboot的這個(gè)問(wèn)題,待后續(xù)修復(fù)。先繼續(xù)找 kernel啟動(dòng)慢的原因。(注:現(xiàn)在看來(lái)當(dāng)時(shí)的做法是有問(wèn)題的,這里的異常這么明顯,應(yīng)該設(shè)法追蹤下去找出原因才對(duì))

鎖定uboot

uboot的嫌疑非常大,但還不能完全確認(rèn),因?yàn)? uboot之前還有一級(jí) spl。是否會(huì)是 spl的問(wèn)題呢?
嘗試改用 新spl+舊uboot,啟動(dòng)速度正常。而新 spl+新uboot的啟動(dòng)速度則很慢,其他因素都不變,說(shuō)明問(wèn)題確實(shí)出在 uboot階段。

多做or少做

當(dāng)時(shí)到這一步就卡住了,直接比較兩份 uboot的代碼不太現(xiàn)實(shí),差異太大了。
后來(lái)我就給自己提了個(gè)問(wèn)題,到底新 uboot是多做了某件事情,還是少做了某件事情?
換個(gè)說(shuō)法,目前已知

    
spl?-->?舊uboot?-->?kernel(速度快)
spl?-->?新uboot?-->?kernel(速度快)
但到底是以下的情況 A還是情況 B呢?

    
A:?spl(速度慢)?-->?舊uboot(做了某個(gè)會(huì)提升速度的操作)?-->?kernel(速度快)
???spl(速度慢)?-->?新uboot(少做了某個(gè)會(huì)提升速度的操作)?-->?kernel(速度慢)

B:?spl(速度快)?-->?舊uboot(沒(méi)做特殊操作)?-->?kernel(速度快)
???spl(速度快)?-->?新uboot(多做了某個(gè)會(huì)限制速度的操作)?-->?kernel(速度慢)
為了驗(yàn)證,我決定讓 spl直接啟動(dòng)內(nèi)核,看看內(nèi)核到底是快是慢。
支持過(guò)程碰到了一些小問(wèn)題
1. spl沒(méi)有能力加載這么大的 kernel
解決:此時(shí)不需要 kernel能完全啟動(dòng),只需要能加載啟動(dòng)一段,足以體現(xiàn)出啟動(dòng)速度是否正常即可,于是裁剪出一個(gè)非常小 kernel來(lái)輔助實(shí)驗(yàn)。
2. kernel需要 dtb
解決:內(nèi)核有一個(gè) CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE選項(xiàng)。選上重新編譯。編譯后再用 ddkerneldtb拼接到一起,作為新的 kernel。這樣, spl就只需要加載一個(gè)文件并跳轉(zhuǎn)過(guò)去即可。
試驗(yàn)結(jié)果, spl啟動(dòng)的 kernel和使用新 uboot啟動(dòng)的 kernel速度一致,均比舊 uboot啟動(dòng)的 kernel慢。
說(shuō)明,舊 uboot中做了某個(gè)關(guān)鍵操作,而新 uboot沒(méi)做。

找出關(guān)鍵操作

那接下來(lái)的任務(wù)就是,找出舊 uboot中的這個(gè)關(guān)鍵操作了。
怎么找呢?有了上一步的成果,我們可以使用以下方法來(lái)排查
  1. spl加載kernel和舊uboot

  2. spl跳轉(zhuǎn)到舊uboot,此時(shí)kernel其實(shí)已經(jīng)在dram中準(zhǔn)備好了,隨時(shí)可以啟動(dòng)

  3. 在舊uboot的啟動(dòng)流程各個(gè)階段,嘗試直接跳轉(zhuǎn)到kernel,觀察啟動(dòng)速度

  4. 如果在舊ubootA點(diǎn)跳轉(zhuǎn)kernel啟動(dòng)慢,B點(diǎn)跳轉(zhuǎn)啟動(dòng)快,則說(shuō)明關(guān)鍵操作位于AB點(diǎn)之間。

方法有了,很快就鎖定到 start.S,進(jìn)一步在 start.S中揪出了這段代碼

    
#if?defined(CONFIG_ARM_A7)
@ set?SMP?bit
????mrc?????p15,? 0,?r0,?c1,?c0,? 1
????orr????????r0,?r0,?#( 1<< 6)
????mcr????????p15,? 0,?r0,?c1,?c0,? 1
#endif
ubootstart.S中沒(méi)有這段代碼,嘗試在新 ubootstart.S中添加此操作,速度立馬恢復(fù)正常了。
再全局搜索下,原來(lái)這個(gè)新版本 uboot中,套路是在 board_init中進(jìn)行此項(xiàng)設(shè)置的,而這個(gè)平臺(tái)從舊版本移植過(guò)來(lái),就沒(méi)有設(shè)置 SMP bit, 補(bǔ)上即可。

SMP bit是什么

SMP 是指對(duì)稱多處理器,看起來(lái)這個(gè) bit 會(huì)影響多核的 cache一致性,此處沒(méi)有再深入研究。
但可以知道,對(duì)于單處理器的情況,也需要設(shè)置這個(gè) bit才能正常使用 cache
貼下 arm的圖和描述:

    
[6]?SMP?

Signals? if?the?Cortex-A9?processor?is?taking?part? in?coherency?or?not.

In?uniprocessor?configurations,? if?this?bit?is? set,? then?Inner?Cacheable?Shared?is?treated?as?Cacheable.?The?reset?value?is?zero.
搜下 kernel的代碼,發(fā)現(xiàn)也是有地方調(diào)用了的。不過(guò)這個(gè)芯片是單核的,根本就沒(méi)配置 CONFIG_SMP

    
#ifdef?CONFIG_SMP
?ALT_SMP(mrc?p15,? 0,?r0,?c1,?c0,? 1)
?ALT_UP(mov?r0,?#( 1?<6))??@?fake?it? for?UP
?tst?r0,?#( 1?<6)???@?SMP/nAMP?mode?enabled?
?orreq?r0,?r0,?#( 1?<6)??@?Enable?SMP/nAMP?mode
?orreq?r0,?r0,?r10???@?Enable?CPU-specific?SMP?bits
?mcreq?p15,? 0,?r0,?c1,?c0,? 1
#endif

總結(jié)

整理出來(lái)一方面是記錄這兩個(gè) bug,另一方面也是想記錄下當(dāng)時(shí)的一些操作。
畢竟同樣的 bug可能以后都不會(huì)碰到了,但解 bug的方法和思路卻是可以積累復(fù)用的。

-END-


本文授權(quán)轉(zhuǎn)載自qb雜貨鋪,作者:瞎折騰的zqb




推薦閱讀



【01】C語(yǔ)言內(nèi)存泄露很嚴(yán)重,如何應(yīng)對(duì)?
【02】編譯C語(yǔ)言程序,使用 gcc 指令,而C++程序則推薦使用 g++指令!
【03】C語(yǔ)言:優(yōu)雅的字符串函數(shù)庫(kù)
【04】在C 語(yǔ)言中,請(qǐng)一定記得初始化局部變量!
【05】嵌入式編程是否應(yīng)該用C++替代C語(yǔ)言


免責(zé)聲明:整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有,如有侵權(quán),請(qǐng)聯(lián)系刪除

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉