當前位置:首頁 > 公眾號精選 > 嵌入式大雜燴
[導讀]關注「嵌入式大雜燴」,星標公眾號,一起進步!來源:裸機思維【說在前面的話】相信很多人都遇到過這樣的情況:在一個Cortex-M嵌入式應用中要實現(xiàn)一個精確的毫秒級延時并不困難——如果你有RTOS,在任務中使用諸如os_sleep()之類的函數(shù)就可以輕松實現(xiàn);如果你是裸機,也可以使用...

關注「嵌入式大雜燴」,星標公眾號,一起進步!

來源:裸機思維


【說在前面的話】

相信很多人都遇到過這樣的情況:在一個Cortex-M嵌入式應用中要實現(xiàn)一個精確的毫秒級延時并不困難——如果你有RTOS,在任務中使用諸如 os_sleep(<休眠時間>) 之類的函數(shù)就可以輕松實現(xiàn);如果你是裸機,也可以使用每個Cortex-M芯片都默認攜帶的SysTick來實現(xiàn)一個,甚至Arm官方的CMSIS都提供了現(xiàn)成的API,即SysTick_Config(<中斷間隔的時鐘周期數(shù)>)
static volatile uint32_t s_wMSCounter = 0;
extern?uint32_t?SystemCoreClock;/*! \brief initialise platform before main() */__attribute__((constructor(101)))void platform_init(void){ SystemCoreClockUpdate(); /* Generate interrupt each 1 ms */ SysTick_Config(SystemCoreClock / 1000); }
__attribute__((weak))void systimer_1ms_handler(void){????/*?default?systimer?1ms?hander??????*?you?can?override?it?by?implement?a?non-weak version?????*/}
void SysTick_Handler (void) { if (s_wMSCounter) { s_wMSCounter--; }
systimer_1ms_handler();}
void delay_ms(uint32_t wMillisecond){ s_wMSCounter = wMillisecond; while( s_wMSCounter > 0 );}上述代碼非常典型,唯一需要強調(diào)的是SystemCoreClock是一個定義在啟動文件system_<芯片型號>.c 里的全局變量,負責保存當前處理器的工作頻率——上面的平臺初始化函數(shù) platform_init()?就是借助這一變量把 SysTick 初始化為以“1ms為間隔產(chǎn)生中斷”的。

如果要實現(xiàn)一個微秒級延時卻并不那么一帆風順。首先,不同人關于實現(xiàn)方案就有不同的想法,比如:
  • 有的人習慣于直接用軟件方法堆積NOP()來實現(xiàn)——這種方法所產(chǎn)生的延時效果“可能”容易受到編譯器優(yōu)化等級的影響——據(jù)說這也是很多人懼怕開啟編譯器的原因之一,因為一開優(yōu)化,很多對時間敏感的硬件時序就因為延時函數(shù)的不穩(wěn)定而一起變得不可捉摸;

extern?uint32_t?SystemCoreClock;
#ifndef DELAY_US_CALIBRATION/*!?\brief?不要問我為啥是?8, 我也不知道,但在當前這個工程下,8貌似最準?*!????????你如果不服,就自己測一個,然后定義這個宏……?*!????????如果你頭鐵改了工程的優(yōu)化等級,請也無比親自測一下……具體怎么?*! ???????測,我也不知道。如果你也怕麻煩,就不要改優(yōu)化等級。 */# define DELAY_US_CALIBRATION 8#endif
void?delay_us(uint32_t?wUS){????//!?calcluate?how?many?cycles?required?for?1us????uint32_t?wCyclesPerUS?=?SystemCoreClock?/?1000000ul;????????/*!?subtract some cycles from wCyclesPerUS based on the ?????*!?experience?or?actual?measurement?in?current?optimisation?????*/????wCyclesPerUS?-=?DELAY_US_CALIBRATION;
????for?(int?i?=?0;?i?????????for?(j?=?0;?j?< wCyclesPerUS; j ) {???????? __NOP();????????}????}}
  • 有的人提倡使用定時器來實現(xiàn)精確延時,這一方案顯然不太懼怕編譯器優(yōu)化的“血腥巨斧”。想法是沒錯的,但如果要保證這樣寫出來的延時庫有一定的可移植性,就需要保證 delay_us() 函數(shù)實現(xiàn)所依賴的硬件定時器是“通用的”和“普遍存在”的——符合這一要求的第一選擇是SysTick——然而既然SysTick已經(jīng)被 delay_ms() 占用了,又如何能抽的開身呢?


既然 SysTick 被占用了,那有沒有別的符合要求的硬件呢?如果不算Cortex-M0/M0 的話,從某種程度上說還真有——DWT。這是一個系統(tǒng)外設,專門用來為Cortex-M3及其以上芯片提供調(diào)試和追蹤的硬件輔助功能。在【裸機思維】往期轉載的文章中,就有使用DWT實現(xiàn)延時的內(nèi)容。這個方法好是好,但缺點也是非常突出的:
  • DWT 根本就不是設計給用戶用的,它是Cortex-M處理器預留給上位機調(diào)試軟件(例如MDK)進行調(diào)試和追蹤的。換句話說,上位機調(diào)試軟件覺得這是自己的私人財產(chǎn),從來沒想過用戶會去使用它——這就導致調(diào)試過程中,IDE會按照自己的意思隨意修改它的配置——啥時候會改呢?這要看IDE的心情。如果你的程序依賴了DWT進行延時,那么調(diào)試的時候,IDE的一個無心之舉可能就會毀了你的時序——這一知識點非常容易忽略掉,從而導致很多人遇到調(diào)試的時候,系統(tǒng)隨機性的功能不正常的坑,從而浪費大把的時間,往往還想不到是DWT導致的——說這一方法是天坑可能一點也不為過。

  • DWT 不是所有 Cortex-M 芯片都有……(Cortex-M0/M0 就沒有)


既然 SysTick 被占用、DWT?又是天坑,是不是意味著我們就只能使用芯片的普通定時器了?——這每個廠家都不一樣……每個應用對定時器的使用情況也都不同,那我還怎么做通用的延時庫啊?

別急,今天我們就來介紹一種在完全不影響 SysTick 已有功能的前提下,繼續(xù)把它榨干——提供更多功能的方法。為了避免誤解,我把這種方法的目標需求列舉如下:
  • 提供一個精確的 delay_us() 函數(shù);

  • 提供一個精確測量任意代碼塊所實際占用系統(tǒng)周期數(shù)的方法;

  • 實現(xiàn)一個記錄從進入 main() 函數(shù)以來總共經(jīng)歷了多少個時鐘周期(且在合理的時間范圍內(nèi)不會溢出)的計數(shù)器(時間戳);

  • 用戶已有的 SysTick 功能不能受到干擾

    • 比如用戶使用 SysTick 作為RTOS的基準時鐘(非Tickless模式);

    • 比如用戶使用 SysTick 作為普通的毫秒級延時(就像前面例子代碼所展示的那樣);

  • 用戶不需要修改自己任何已有的 SysTick 代碼。



【部署 perf_counter 庫】

要實現(xiàn)上述功能,可以直接借助一個叫做 perf_counter 的庫,這是我基于這幾年在代碼性能分析中總結出來的,我已經(jīng)把它放在 github 上進行開源,其地址為:https://github.com/GorgonMeducer/perf_counter
這個庫目前支持 Arm Compiler 5(armcc) 和 Arm Compiler 6(armclang)。它不僅提供了源代碼,還提供了編譯好的 library (.lib)可供全系列Cortex-M處理器使用。
第一步,下載最新的release:


解壓縮后可以看到如下的內(nèi)容:

如果只是普通的使用,直接拷貝 lib 目錄到你的工程即可。


第二步,將庫加入到已有的 MDK 工程中:



別忘記在工程的頭文件搜尋路勁中包含 perf_counter.h 所在文件夾,例如(具體位置根據(jù)你工程的情況而定,不要死腦經(jīng)):



第三步:編譯并調(diào)整一些工程選項

如果你編譯后很順利,則請?zhí)^下面的內(nèi)容,快進到 0 error 0 warning的圖片之后。



好,下面讓我們來談談你可能遇到的問題,以及對應的解決方案:


問題一:提示找不到 $Super$$SysTick_Handler

.\Out\example.axf: Error: L6218E: Undefined symbol $Super$$SysTick_Handler (referred from systick_wrapper_ual.o).Not enough information to list image symbols.Not enough information to list load addresses in the image map.Finished: 2 information, 0 warning and 1 error messages.".\Out\example.axf" - 1 Error(s), 0 Warning(s).

perf_counter 庫是一個“附加型”庫——它假設你自己已經(jīng)實現(xiàn)了一個SysTick的中斷處理程序,并開啟了中斷模式——如果你沒有,直接加一個空的就好了:

void SysTick_Handler (void) {}好,問題解決。什么?你的工程也根本沒有用SysTick?好辦,請在進入main后調(diào)用函數(shù)init_cycle_counter()?并傳遞false,例如:

int main(void){ ... init_cycle_counter(false); ...}這樣做的目的是告訴 perf_counter:“請自己玩的開心”。


問題二:wchar和enum的尺寸不兼容:

需要強調(diào)的是,perf_counter.lib 庫在編譯的時候,開啟了 Short enums/wchar(分別對應命令行的?-fshort-enums -fshort-wchar)。這么做其實沒什么特別的原因,但如果你的工程使用了不同的配置,例如:


下圖的工程配置中,沒有勾選 "Short enums/wchar"


你一定會看到這樣的編譯錯誤:

.\Out\example.axf: Error: L6242E: Cannot link object perf_counter.o as its attributes are incompatible with the image attributes. ... wchart-16 clashes with wchart-32. ... packed-enum clashes with enum_is_int.

既然知道了原因,解決方法就很簡單,要么在工程配置中勾選上這一選項;要么使用源代碼編譯(不使用lib):



也就是圖中所示的:perf_counter.c systick_wrapper_ual.s。


? ? perf_counter.c 依賴了 CMSIS,所以確保你的工程中加入了對CMSIS的支持——推薦的是使用MDK自帶的 CMSIS,在RTE配置界面中勾選:



如果你使用的是工程自帶的CMSIS(很多STM32工程就是這樣),請確保你的CMSIS?是較新的版本(判斷標準就是是否帶有 cmsis_compiler.h)。


此外,這里的 systick_wrapper_ual.s 是一個匯編源程序,使用的是Arm的老語法(Unified Assembly Language),如果你的工程使用的是 Arm Compiler 5(armcc),這里就沒什么需要特別注意的了;如果你的工程使用的是 Arm Compiler 6(armclang),則你需要檢查工程配置,以確保MDK能正確的選擇對應的Assembler


注意這里的 Assembler Option,根據(jù)你MDK版本的不同,它可能有以下幾個有效選項:
  • armclang(Auto Select)——我吐血推薦選這個

  • armclang(GNU Syntax)——?這個意思就是使用 GNU的匯編語法,顯然不能選它;

  • armclang(Arm Syntax)——這是最新MDK(從5.32開始)才有的選項,選了也行;

  • armasm(Arm Syntax)——這就是 Arm Compiler 5里一直使用的老匯編器,選他當然兼容性最好。


做好了以上兩個準備工作,編譯應該就很順利了。是不是覺得有點頭大?頭大就用?.lib 啊……完全不用經(jīng)歷這些痛苦




至此,我們完成了 perf_counter 庫在工程中的部署。那么它帶給我們哪些功能呢?


【SysTick第一吃:微秒級精確延時】


#include?"perf_counter.h"
...delay_us(30);????//!...

再也不用擔心編譯器優(yōu)化導致延時不準啦?。?!

再也不擔心庫不通用啦?。?!

再也不用擔心芯片不支持DWT啦?。。。。?!

再也不用擔心調(diào)試/追蹤會干擾DWT啦?。。?!





【SysTick第二吃:精確測量代碼的時鐘周期】

perf_counter.h 提供了兩個函數(shù),用于精確測量任意代碼片段所消耗的CPU時鐘周期數(shù)(不是us數(shù)哦):
extern void start_cycle_counter(void);extern int32_t stop_cycle_counter(void);它們的使用非常簡單直接,例如:
start_cycle_counter();//!?測量?打印??"Hello?World\r\n" 究竟用了多少個時鐘周期printf("Hello World! \r\n");int32_t?iCycleUsed?=?stop_cycle_counter(void);printf("Cycle?Used:?%d",?iCycleUsed);當然,如果你的工程環(huán)境允許你用printf的話,還可以用 perf_counter.h 自帶的宏將上述代碼簡化一下:

//!?the?demo?of?__cycleof__()__cycleof__() {????printf("Hello?World\r\n");}其運行結果為:

(以上結果為FVP仿真結果,CPU周期數(shù)值不可以做參考)


我們甚至還可以添加一點注釋性的字符串,幫助我們區(qū)分測試的范圍:

//!?the?demo?of?__cycleof__()__cycleof__("Print?string")?{????printf("Hello?World\r\n");}

我們看到,傳遞給__cycleof__的提示字符串"Print string"被添加到了"total cycle count:..." 的前面,一目了然。


實際上,start_cycle_counter()stop_cycle_counter() 的組合還可以用來測量中斷處理程序實際使用的系統(tǒng)周期數(shù)——讀過我【實時性迷思】系列文章的小伙伴,一定知道測量“事件處理函數(shù)所需時間”的意義:

volatile?int32_t?g_nMaxHandlingCycles = 0;
void?USART0_RX_Handler(void){????start_cycle_counter();????????//!?你的USART0 接收中斷處理程序實際內(nèi)容????...????????int32_t nCycles = stop_cycle_counter();????g_nMaxHandlingCycles?=?MAX(nCycles,?g_nMaxHandlingCycles);}

從此一舉告別“拍腦袋憑感覺”說中斷處理時間要多長的舊世界。


此外,start_cycle_counter()?和 stop_cycle_counter() 還支持類似體育老師所使用的秒表的功能,即,起跑后、可以分別記錄每一個學生所用的時間。具體表現(xiàn)為:

int32_t nCycles = 0;start_cycle_counter();???? //!...nCycles?=?stop_cycle_counter();??//!...nCycles?=?stop_cycle_counter();??//!...nCycles?=?stop_cycle_counter();??//!< 第三次獲取從開始以來的時間...具體什么情況下要用到這樣的方式就見仁見智了,這里就不再繼續(xù)展開。


最后,需要強調(diào)一下,雖然 start_cycle_counter()stop_cycle_counter()startstop 的字樣,但這只是邏輯上的,并不會真正的干擾 SysTick 的功能(也就是不會開啟或者關閉 SysTick)。這也是這個庫敢于聲稱自己不會影響用戶已有的 SysTick 功能的原因。

【SysTick第三吃:系統(tǒng)時間戳】

閱讀到這里,聰明的你一定已經(jīng)發(fā)現(xiàn)了:無論是 perf_counter(performance counter)庫名的明示,還是 start_cycle_counter()stop_cycle_counter() 的強大功能,都暗示其實這個庫應該不是專門用來提供微秒延時函數(shù) delay_us() 的,實際上,只要你稍微看一眼源代碼就會發(fā)現(xiàn)上述猜想完全沒錯—— delay_us() 其實才是附贈的:
void delay_us(int32_t iUs){ iUs *= SystemCoreClock / 1000000ul; start_cycle_counter(); while(stop_cycle_counter() < iUs);}

看到真相的你,有沒有意識到,在 start_cycle_counter()stop_cycle_counter() 之間不能調(diào)用 delay_us() 呢?

既然 delay_us() 都是“cycle counter”送的,還有啥別的功能是附贈的么?——還真有:系統(tǒng)時間戳。想象一下,既然 start_cycle_counter()stop_cycle_counter() 的組合可以獲得從開始以來的時間,那么如果我在進入main()之前就執(zhí)行 start_cycle_counter() ,然后在需要的時候調(diào)用 stop_cycle_counter() 是不是就可以獲取“從main()開始已經(jīng)執(zhí)行了多少個周期”的系統(tǒng)時間戳呢?
Bingo!答對了,原理上就是這樣,只不過實際上,為了保留 start_cycle_counter() stop_cycle_counter() 給用戶使用,per_counter庫就自己獨立實現(xiàn)了對應的邏輯——用戶可以通過調(diào)用函數(shù)?clock() 來獲取這一信息:
#ifdef __PERF_CNT_USE_LONG_CLOCK____attribute__((nothrow)) extern int64_t clock(void);#endif熟悉系統(tǒng)庫 朋友可能會立即產(chǎn)生疑問,真正的定義不應該是這樣的么:
extern _ARMABI clock_t clock(void);clock_t 在 Cortex-M環(huán)境下定義如下:

typedef unsigned int clock_t; /* cpu time type */為什么perf_counter.h 要采用不一樣的定義呢?


說起來也簡單:clock() 函數(shù)返回的是系統(tǒng)周期數(shù),而不是什么以 us 或者 ms 為單位的時間——考慮到現(xiàn)在處理器頻率動輒幾百兆赫茲,有的甚至達到了1GHz(比如 NXP的RT系列),如果用 int32_t?(哪怕用 uint32_t)也撐不了幾秒鐘。


假設系統(tǒng)頻率為1GHz,使用 uint32_t 來計數(shù),由于32bit整數(shù)取值范圍是0~4G,因此,最多4秒就撐不住了……


那究竟多長才夠呢?



當我們使用 int64_t 的時候,哪怕系統(tǒng)頻率是 4GHz,2G 秒 ≈ 24855 天 ≈ 68年。雖然沒有一萬年那么久,不過多半一個嵌入式設備也沒法用這么久(千年蟲警告),但考慮到大部分Cortex-M嵌入式系統(tǒng)估計沒有4GHz這么夸張,輕松跑個1000多年不溢出應該是沒有問題的。


既然我們鐵了心要用 int64_t 來取代 clock_t 原本的 int32_t,怎么解決這里的沖突呢?——顯然去修改系統(tǒng)頭文件 是不允許的!


翻開Arm的隱藏寶典:AAPCS,我們發(fā)現(xiàn)以下的規(guī)則:

32位系統(tǒng)下,

  • 如果函數(shù)的返回值其大小不超過32bit,則保存在寄存器 r0中;

  • 如果函數(shù)的返回值其大小為64bit,則其低 32bit 保存在 r0中、高32bit保存在 r1中。


顯然,當我們實現(xiàn)clock()函數(shù)時返回 int64_t的值與 返回 int32_t其實是兼容的——因為低32bit的內(nèi)容實際上都是保存在 r0 里的,此時如果用戶調(diào)用clock() 的時候:

  • 使用的是里定義的函數(shù)原型,即? clock_t clock(void),則,當函數(shù)返回時,r1里保存的值會被無視,只有r0里的值被視作返回值;

  • 使用的是我們自己定義的函數(shù)原型,即 int64_t clock(void),則你可以獲得完整的 int64_t 時間戳。


既然原理清楚了,再看 perf_counter.h 里面的定義,我們會發(fā)現(xiàn)clock()的函數(shù)原型被一個宏?__PERF_CNT_USE_LONG_CLOCK__ 保護著:

#ifdef __PERF_CNT_USE_LONG_CLOCK____attribute__((nothrow)) extern int64_t clock(void);#endif這實際上是告訴我們,如果我們想獲得 int64_t 時間戳時,只要在工程中定義宏??__PERF_CNT_USE_LONG_CLOCK__?就可以了。



忙活了半天,有的小伙伴可能會疑惑了:饒了這么一大圈,clock() 究竟有啥用處呢?這玩法就多了,快一鍵三聯(lián)~ 下次我們好好來說說。



【后記】

perf_counter(https://github.com/GorgonMeducer/perf_counter)是我在工作中總結和整理出的一個庫,它的特點是在不干擾已有 SysTick 功能的前提下額外為我們提供系統(tǒng)周期測量的功能——并在這基礎上衍生出了 delay_us() 和 系統(tǒng)時間戳的功能——正可謂一鴨三吃,把SysTick榨干到了極致。perf_counter 庫的原理其實很簡單,但其中要處理的 corner case 確實很惱人,我也是歷經(jīng)一年多才真正想明白這里面的彎彎繞。后面如果閱讀量不錯的話,我會考慮專門出一篇介紹 perf_counter 原理的文章。其中,關于如何“不影響現(xiàn)有SysTick中斷處理程序”的功能,已經(jīng)在之前的文章《【嵌入式秘術】手把手教你如何劫持RTOS》中進行了詳細介紹,有興趣的小伙伴可以再回味回味。
在開源的過程中,為了簡化用戶的使用,我做了如下的優(yōu)化:
  • 在 Arm Compiler 5(armcc)和 Arm Compiler 6中,不需要用戶手工對庫進行初始化——庫會在進入main()之前“自己做”;

  • Lib中的perf_counter.lib適用于包含Cortex-M0在內(nèi)的全系列Cortex-M處理器,做到全覆蓋;

  • perf_counter.h 幾乎不依賴 之外的庫。使用.lib進行部署,非常簡潔方便。


如果你要用 safe_atom_code(),則需要 __disable_irq() 和 __set_PRIMASK() 的定義,一般Cortex-M工程都有。這些定義是由 CMSIS提供的。一般來說,普通的 perf_counter 功能并不需要涉及任何這些內(nèi)容。


perf_counter庫的使用當然也存在限制,重要的事情在最后說:
  • 如果你原本的 RTOS 使用了 SysTick并開啟了Tickless模式,perf_counter雖然不會干擾原有的 SysTick功能,但自己的計時功能卻會受到 Tickless模式的干擾;

  • perf_counter庫假設你原本的SysTick應用會保持一個固定的定時周期——也就是 LOAD寄存器的內(nèi)容是固定的、不會隨著程序的執(zhí)行而經(jīng)常變化。其實RTOStickless模式會干擾perf_counter的計數(shù)可靠性也是這個原因。



一般來說,大部分RTOS和普通的周期性定時功能都不會經(jīng)常動態(tài)的去改變SysTick的計數(shù)周期,所以不必太擔心。

原創(chuàng)不易,如果你喜歡我的思維、覺得我的文章對你有所啟發(fā),

請務必 “點贊、收藏、轉發(fā)” 三連,這對我很重要!謝謝!


歡迎訂閱 裸機思維


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

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

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

關鍵字: 汽車 人工智能 智能驅動 BSP

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

關鍵字: 亞馬遜 解密 控制平面 BSP

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

關鍵字: 騰訊 編碼器 CPU

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

關鍵字: 華為 12nm EDA 半導體

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

關鍵字: 華為 12nm 手機 衛(wèi)星通信

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

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

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

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

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

關鍵字: BSP 信息技術
關閉
關閉