加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    •  
    • 1.1 開發(fā)手冊(cè)
    • 1.2 開發(fā)工具
    •  
    • 1.3 軟件框架
    • 1.4 內(nèi)核
    • 1.5 組件
    •  
    • 2.1 開發(fā)流程
    • 2.2 操作系統(tǒng)適配
    • 2.3 風(fēng)險(xiǎn)與限制
    •  
    • 3.1 編譯器關(guān)鍵字
    • 3.2 自動(dòng)初始化
    • 3.3 設(shè)備框架
    • 3.4 模組連接套件
    • 3.5 Shell工具
    • 3.6 單元測(cè)試
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

干貨 | 中國(guó)移動(dòng)oneos框架基礎(chǔ)及其組件解析

2021/10/22
823
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

1、oneos系統(tǒng)

 

1.1 開發(fā)手冊(cè)

OneOS中國(guó)移動(dòng)針對(duì)物聯(lián)網(wǎng)領(lǐng)域推出的輕量級(jí)操作系統(tǒng),具有可裁剪、跨平臺(tái)、低功耗、高安全等特點(diǎn),支持ARM Cortex-M、MIPS、RISC-V等主流芯片架構(gòu),兼容POSIX、CMSIS等標(biāo)準(zhǔn)接口,支持MicroPython語(yǔ)言開發(fā),提供圖形化開發(fā)工具,能夠有效提升開發(fā)效率并降低開發(fā)成本,集成公共組件,適用于安全易用的物聯(lián)網(wǎng)產(chǎn)品。

移動(dòng)官網(wǎng)提供完善的oneos開發(fā)文檔 https://os.iot.10086.cn/v2/doc/homePage

 

 

也可參考RT-Thread的資料,https://www.rt-thread.org/document/site/#/

1.2 開發(fā)工具

OneOS開發(fā)環(huán)境是基于命令行的OneOS-Cube,在對(duì)應(yīng)工程目錄下,執(zhí)行menuconfig配置系統(tǒng),scons編譯構(gòu)造。

具體操作說(shuō)明:https://os.iot.10086.cn/v2/doc/detailPage/documentHtml?idss=157071776529260544&proId=156799478777782272

 

 

1.3 軟件框架

OneOS總體架構(gòu)采用分層設(shè)計(jì),主體由驅(qū)動(dòng)、內(nèi)核、組件、安全框架組成,采用一個(gè)輕量級(jí)內(nèi)核加多個(gè)系統(tǒng)組件的模式。

 

與freeRTOS只包括內(nèi)核相比,oneos支持通用組件或第三方庫(kù),尤其對(duì)接移動(dòng)平臺(tái)方便,遵循 Apache 2.0 license 開源協(xié)議,任意使用。

1.4 內(nèi)核

Oneos內(nèi)核提供任務(wù)管理調(diào)度、任務(wù)間同步與通信、定時(shí)器、內(nèi)存管理等常用RTOS功能,與常規(guī)的RTOS如freeRTOS相比,僅有幾點(diǎn)小區(qū)別:

1、任務(wù),創(chuàng)建task后需要額外調(diào)用才啟動(dòng),不同于freeRTOS創(chuàng)建所有的task后統(tǒng)一啟動(dòng)調(diào)度,全部task都開始執(zhí)行。這種各task獨(dú)立啟動(dòng)的,需要注意先后關(guān)系,不能task1啟動(dòng)后就向task2的隊(duì)列發(fā)消息,此時(shí)隊(duì)列可能為NULL且發(fā)送前沒有判斷,會(huì)導(dǎo)致重啟。

2、消息隊(duì)列,其動(dòng)態(tài)創(chuàng)建和發(fā)送接口類似,但接收隊(duì)列消息需要傳入的參數(shù)不同,需要傳入期望接收的字節(jié)大小。巧合的是項(xiàng)目使用的消息隊(duì)列都是同一個(gè)結(jié)構(gòu)體,如果不一致,需要特殊處理。

3、工作隊(duì)列,將task進(jìn)行了一定封裝,不需要為處理某個(gè)事件而新建task,交給系統(tǒng)提前創(chuàng)建的task統(tǒng)一執(zhí)行,執(zhí)行結(jié)束后觸發(fā)回調(diào)函數(shù),這樣多個(gè)長(zhǎng)時(shí)間運(yùn)行但不經(jīng)常觸發(fā)的,可以交給工作隊(duì)列處理,該功能在UIS8910中系統(tǒng)自帶。

4、郵箱,Oneos特有的,可理解為簡(jiǎn)化版的消息隊(duì)列。

如果對(duì)freeRTOS不熟悉的,可以參考入門文章<FreeRTOS及其應(yīng)用,萬(wàn)字長(zhǎng)文,基礎(chǔ)入門>。

1.5 組件

正如前面提到,如何使用oneos,移動(dòng)官網(wǎng)有詳細(xì)的說(shuō)明,本文只是介紹oneos的基本開發(fā)流程,分析其部分功能的實(shí)現(xiàn)方式,后續(xù)以其設(shè)備框架、SHELL和單元測(cè)試三部分為主。

2、系統(tǒng)移植

 

2.1 開發(fā)流程

基于oneos的開發(fā)方式和以往不同,先將原始工程編譯生成庫(kù),全部復(fù)制到oneos工程,再基于oneos系統(tǒng)開發(fā)業(yè)務(wù)邏輯,其開發(fā)環(huán)境和原始工程開發(fā)環(huán)境無(wú)關(guān)。Oneos工程編譯生成的bin文件下載到設(shè)備,完整版本支持microPython,可以導(dǎo)入python文件直接運(yùn)行。

 

可能部分功能比較特殊,使用原始庫(kù)文件無(wú)法實(shí)現(xiàn),例如獲取系統(tǒng)某個(gè)參數(shù)。在原始工程開發(fā),可以直接將客制化代碼插入某個(gè)接口攔截,基于oneos開發(fā)時(shí)盡量避免,但是實(shí)在不行也只能這樣。這樣操作后,原始工程編譯成功,但鏈接肯定失敗,但不影響結(jié)果,只要輸出lib庫(kù)即可。

2.2 操作系統(tǒng)適配

如果沒有原始SDK,要運(yùn)行oneos,直接將原始庫(kù),例如STM32原廠HAL庫(kù)復(fù)制到oneos/thirdparty即可;但是有基礎(chǔ)SDK,且SDK是基于其它RTOS開發(fā),則其庫(kù)要在oneos運(yùn)行,需要進(jìn)行適配轉(zhuǎn)換,存在兩種方式。

以目前支持cat1網(wǎng)絡(luò)比較火的兩個(gè)芯片平臺(tái)為例。紫光展銳UIS8910平臺(tái)使用freeRTOS,且基本開源,因此可以將UIS8910工程中的freeRTOS系統(tǒng)接口,其函數(shù)內(nèi)容替換使用oneos的接口實(shí)現(xiàn)。

翱捷ASR1603平臺(tái)使用threadX,且已封庫(kù),因此是在oneos工程,將oneos的系統(tǒng)內(nèi)核接口函數(shù)內(nèi)容使用ASR1603提供的庫(kù)實(shí)現(xiàn)。

<公眾號(hào):嵌入式系統(tǒng)>

 

前者UIS8910是oneos直接在底層替換了freeRTOS,相當(dāng)于只運(yùn)行了一套較為干凈的oneos;后者完全是將兩套R(shí)TOS的接口互相匹配,且中間并不是一對(duì)一替換。

2.3 風(fēng)險(xiǎn)與限制

原始工程開發(fā)函數(shù)是直接調(diào)用,引入oneos框架后,內(nèi)核適配、驅(qū)動(dòng)框架增加了代碼量,運(yùn)行效率也存在一定損失。對(duì)網(wǎng)絡(luò)modem相關(guān)的操作,oneos使用AT通信,其阻塞方式對(duì)原有應(yīng)用邏輯存在較大影響,不如原始API便捷。

3、系統(tǒng)組件

 

3.1 編譯器關(guān)鍵字

重點(diǎn)介紹section關(guān)鍵字,后續(xù)章節(jié)都與其有關(guān),section主要作用是將函數(shù)或者變量放在指定段中,可在指定的地方取函數(shù)執(zhí)行。

//main.c  
//section demo  
#include "stdio.h"  
   
int __attribute__((section("my_fun"))) test1(int a,int b)  
{  
 return (a+b);  
}

int test(int b)  
{  
 return 2*b;  
}

int __attribute__((section("my_fun"))) test0(int a,int b)  
{  
 return (a*b);  
}  
   
int __attribute__((section("my_val"))) chengi;  
int __attribute__((section("my_val"))) chengj;  
   
int main(void)  
{  
 int sum,c,j;    
 chengi=1,chengj=2;  
   
 sum=test1(chengi,chengj);  
 c=test(100);  
 j=test0(chengi,chengj);  
       
  printf("sum=%d,c=%d,j=%drn",sum,c,j);  

  return 0;  
}  

編譯生成map文件:

gcc -o main.exe main.c -Wl,-Map,my_test.map

my_test.map 文件片段如下:

.text  0x00401460 0xa0 C:UsersthinkccmGLaeH.o0x00401460 test0x0040146a main

.text 0x00401500 0x0 c:/mingw/bin/../libmingw32.a(CRTglob.o)

...... my_fun 0x00404000 0x200 [!provide] PROVIDE (___start_my_fun, .)

my_fun  0x00404000 0x1c C:UsersthinkccmGLaeH.o

0x00404000 test10x0040400d test0

[!provide] PROVIDE (___stop_my_fun, .)

.data 0x00405000 0x200

0x00405000 _data_start_ = . ...... *(.data_cygwin_nocopy) my_val 0x00406000 0x200

[!provide] PROVIDE (___start_my_val, .)

my_val  0x00406000 0x8 C:UsersthinkccdMcTrl.o0x00406000    chengi0x00406004 chengj

[!provide] PROVIDE (___stop_my_val, .)

.rdata 0x00407000 0x400

分析可見,使用section修飾的函數(shù)和變量在自定義的片段,而且是連續(xù)存放,這樣可根據(jù)變量的地址得出與其同段變量的地址,為后續(xù)自動(dòng)初始化等功能提供了基礎(chǔ)。

3.2 自動(dòng)初始化

基于前面section的作用,可以將同類函數(shù)指針全部使用同一個(gè)段名修飾,然后開機(jī)后系統(tǒng)自動(dòng)檢索段內(nèi)函數(shù)指針,逐個(gè)執(zhí)行,對(duì)上層應(yīng)用就是無(wú)需主動(dòng)調(diào)用,系統(tǒng)自動(dòng)初始化??紤]到硬件初始化與應(yīng)用功能初始化的先后順序,可以對(duì)段名進(jìn)行分配,map文件按段名排序。自動(dòng)初始化主體是OS_INIT_EXPORT宏。

typedef os_err_t (*os_init_fn_t)(void);

#define OS_INIT_EXPORT(fn, level) 
const os_init_fn_t __os_call_##fn OS_SECTION(".init_call."level) = fn

#define OS_BOARD_INIT(fn) OS_INIT_EXPORT(fn, "1")

#define OS_PREV_INIT(fn) OS_INIT_EXPORT(fn, "2")

#define OS_DEVICE_INIT(fn) OS_INIT_EXPORT(fn, "3")

#define OS_CMPOENT_INIT(fn) OS_INIT_EXPORT(fn, "4")

#define OS_ENV_INIT(fn) OS_INIT_EXPORT(fn, "5")

#define OS_APP_INIT(fn) OS_INIT_EXPORT(fn, "6")

例如shell初始化函數(shù),定義如下:

OS_APP_INIT(sh_system_init);

將宏定義展開

/* 含義是函數(shù)指針 __os_call_sh_system_init
*  其指向sh_system_init函數(shù),且該指針編譯后放在".init_call.6"段
*/
const os_init_fn_t __os_call_sh_system_init
    __attribute__((section((".init_call.6")))) = sh_system_init

系統(tǒng)自身也有自定義函數(shù),用來(lái)標(biāo)記起止點(diǎn)函數(shù)

OS_INIT_EXPORT(os_init_start, "0");
OS_INIT_EXPORT(os_board_init_start, "0.end");
OS_INIT_EXPORT(os_board_init_end, "1.end");
OS_INIT_EXPORT(os_init_end, "6.end");

最終生成的map文件如下圖:

//系統(tǒng)底層在合適的時(shí)機(jī)調(diào)用如下兩函數(shù),將指定段區(qū)間內(nèi)的所有函數(shù)自動(dòng)執(zhí)行

void os_board_auto_init(void)
{
    const os_init_fn_t *fn_ptr_board_init_start;
    const os_init_fn_t *fn_ptr_board_init_end;
    const os_init_fn_t *fn_ptr;

    fn_ptr_board_init_start = &__os_call_os_board_init_start + 1;
    fn_ptr_board_init_end   = &__os_call_os_board_init_end - 1;

    for (fn_ptr = fn_ptr_board_init_start; fn_ptr <= fn_ptr_board_init_end; fn_ptr++)
    {
        (void)(*fn_ptr)();
    }

    return;
}

static void os_other_auto_init(void)
{
    const os_init_fn_t *fn_ptr_other_init_start;
    const os_init_fn_t *fn_ptr_other_init_end;
    const os_init_fn_t *fn_ptr;

    fn_ptr_other_init_start = &__os_call_os_board_init_end + 1;
    fn_ptr_other_init_end   = &__os_call_os_init_end - 1;

    for (fn_ptr = fn_ptr_other_init_start; fn_ptr <= fn_ptr_other_init_end; fn_ptr++)
    {
        (void)(*fn_ptr)();
    }

    return;
}

系統(tǒng)執(zhí)行os_other_auto_init時(shí)實(shí)現(xiàn)了sh_system_init的自動(dòng)執(zhí)行,即使應(yīng)用層沒有顯示的去調(diào)用它。使用符號(hào)段的方式實(shí)現(xiàn)初始化函數(shù)自動(dòng)執(zhí)行,應(yīng)用層修改軟件,增加功能啟動(dòng)或者裁剪,對(duì)底層代碼無(wú)需任何改動(dòng)。

3.3 設(shè)備框架

3.3.1 設(shè)備模型

一般HAL包括GPIO、UARTADC等,每個(gè)設(shè)備節(jié)點(diǎn)的類型和控制接口、參數(shù)個(gè)數(shù)及含義完全不同,即使都是GPIO,不同原廠提供的接口也各不相同。設(shè)備框架就是在底層封裝原始API,然后統(tǒng)一注冊(cè)到設(shè)備節(jié)點(diǎn)表,使用時(shí)獲取節(jié)點(diǎn)及其對(duì)應(yīng)的操作接口,這樣應(yīng)用層的代碼在風(fēng)格上比較統(tǒng)一。

 

應(yīng)用層需要操作設(shè)備時(shí),根據(jù)名稱查找設(shè)備,再使用該提供的API進(jìn)行操作,無(wú)需關(guān)注該設(shè)備具體對(duì)應(yīng)的端口、狀態(tài)等細(xì)節(jié)信息;其風(fēng)格與linux驅(qū)動(dòng)接近。

3.3.2 設(shè)備注冊(cè)

I2C設(shè)備為例:

#define OS_DEVICE_INFO static OS_SECTION("device_table") const  os_device_info_t

OS_DEVICE_INFO asr1603_i2c1_device = {
 .name = "i2c1",
 .driver = "ASR1603_I2C_DRIVER",
 .info = OS_NULL,
};

 OS_DEVICE_INFO asr1603_i2c2_device = {
 .name = "i2c2",
 .driver = "ASR1603_I2C_DRIVER",
 .info = OS_NULL,
};

所有的設(shè)備信息存在device_table段,只是分配設(shè)備驅(qū)動(dòng)類型和名稱。

OS_DRIVER_INFO asr1603_i2c_driver = {
 .name = "ASR1603_I2C_DRIVER",
 .probe = asr1603_i2c_probe, //I2C設(shè)備初始化和注冊(cè)
};

OS_DRIVER_DEFINE(asr1603_i2c_driver, "2");

#define OS_DRIVER_DEFINE(_driver_, sequence)            
    static os_err_t __driver_##_driver_##_init(void)    
    {                                                   
        return driver_match_devices(&_driver_);         
    }                                                   
    OS_INIT_EXPORT(__driver_##_driver_##_init, sequence)
//OS_INIT_EXPORT即為前面提到的開機(jī)自啟動(dòng)定義宏

開機(jī)后自動(dòng)執(zhí)行_asr1603_i2c_driver_driver__init,也就是自動(dòng)將device_table段設(shè)備對(duì)應(yīng)的驅(qū)動(dòng)程序asr1603_i2c_probe自動(dòng)執(zhí)行,實(shí)現(xiàn)了所有設(shè)備的初始化,

static int asr1603_i2c_probe(const os_driver_info_t *drv, const os_device_in
                             fo_t *dev)
{
    ...
 //所有的 I2C 設(shè)備(一種設(shè)備有多個(gè))進(jìn)行初始化
    if(!strcmp(dev->name, "i2c1"))
    {
        g_i2c1.id = ASR1603_DEV_I2C1;
        i2c_p = &g_i2c1;
    }
    else if(!strcmp(dev->name, "i2c2"))
    {
        g_i2c2.id = ASR1603_DEV_I2C2;
        i2c_p = &g_i2c2;
    }
    ....

    asr1603_wrap_i2c_init(i2c_p->id);

    i2c_p->i2c_bus.ops = &i2c_bus_ops; //底層操作 I2C 的接口,與實(shí)際硬件綁定
    i2c_p->i2c_bus.priv = i2c_p;

    ret = os_i2c_bus_device_register(&(i2c_p->i2c_bus), dev->name, OS_DEVICE
                                     _FLAG_RDWR, &(i2c_p->i2c_bus));

    return ret;
}

os_i2c_bus_device_register將I2C設(shè)備注冊(cè)到系統(tǒng)設(shè)備列表os_device_list,包括其對(duì)外接口i2c_ops。

struct os_device_ops
{
    os_err_t  (*init)   (os_device_t *dev);
    os_err_t  (*open)   (os_device_t *dev, os_uint16_t oflag);
    os_err_t  (*close)  (os_device_t *dev);
    os_size_t (*read)   (os_device_t *dev, os_off_t pos, void *buffer, os_size_t size);
    os_size_t (*write)  (os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size);
    os_err_t  (*control)(os_device_t *dev, os_int32_t cmd, void *args);
};

所有設(shè)備對(duì)外提供接口都類似,部分不支持的為NULL,風(fēng)格和linux設(shè)備驅(qū)動(dòng)一致,這些接口是封裝前面i2c_bus_ops提供的硬件特有驅(qū)動(dòng),這樣完成了I2C設(shè)備框架與硬件驅(qū)動(dòng)綁定以及自動(dòng)初始化。

3.3.3 框架應(yīng)用

應(yīng)用層使用I2C設(shè)備:

os_device_find("i2c1");

獲取成功后,正常流程是使用i2c_ops提供的接口操作設(shè)備,實(shí)際調(diào)用也基于i2c_bus_ops封裝的接口,可見oneos也不太標(biāo)準(zhǔn);最佳操作可以參考UART的用法。

3.4 模組連接套件

模組連接套件 Molink (Module link kit),設(shè)備通過(guò)AT與網(wǎng)絡(luò)模組交互的接口,內(nèi)置基帶的使用虛擬AT通道。

 

 

Molink對(duì)單片機(jī)加模組的方案非常合適,對(duì)內(nèi)置基帶的芯片,反而影響效率,因?yàn)槠銩T是阻塞方式實(shí)現(xiàn),例如掃描周圍wifi熱點(diǎn),會(huì)導(dǎo)致當(dāng)前task阻塞幾秒鐘,這樣處理只是為統(tǒng)一API接口,實(shí)現(xiàn)MCU+模組和內(nèi)置基帶兩種硬件方案的應(yīng)用代碼無(wú)縫遷移。

名稱高大上,其實(shí)就是開機(jī)初始化一個(gè)大數(shù)組,在module_asr1603_create(),不同作用的AT分類,封裝AT收發(fā)、解析接口。

 

使用mo-link先獲取數(shù)組中對(duì)應(yīng)項(xiàng),使用其支持的API操作AT指令,以阻塞方式運(yùn)行。對(duì)于ASR1603內(nèi)置基帶的,socket沒有使用AT方式,而是LWIP接口,這種效率高。

3.5 Shell工具

和linux中shell類似,以命令行觸發(fā)函數(shù)運(yùn)行,在shell控制口,默認(rèn)是OS_CONSOLE_DEVICE_NAME輸入命令,shell task會(huì)解析并自動(dòng)掃描內(nèi)部函數(shù)表,執(zhí)行函數(shù)后輸出回應(yīng),將結(jié)果顯示在控制終端上。

Shell對(duì)軟件調(diào)試非常方便,例如調(diào)試I2C接口,只需定義:

SH_CMD_EXPORT(test, test_i2c, "test i2c api");

開機(jī)后串口輸入test字符串,設(shè)備即運(yùn)行test_i2c()函數(shù),其原理如下:

#define SH_CMD_EXPORT(cmd, func, desc)      SH_FUNCTION_EXPORT_CMD(func, __cmd_##cmd, desc)

#define SH_FUNCTION_EXPORT_CMD(func, cmd, desc)                         
    const char __fsym_##cmd##_name[] = #cmd;                            
    const char __fsym_##cmd##_desc[] = desc;                            
    OS_USED const sh_syscall_t __fsym_##cmd OS_SECTION("FSymTab") =     
    {                                                                   
        __fsym_##cmd##_name,                                            
        __fsym_##cmd##_desc,                                            
        (syscall_func_t)func                                            
    };

SH_CMD_EXPORT宏將前面i2c提供的參數(shù)轉(zhuǎn)換,在FsymTab段創(chuàng)建一個(gè)名為__fsym___cmd_test的結(jié)構(gòu)體,其3個(gè)成員分別是字符名,描述和函數(shù)體。

OS_APP_INIT(sh_system_init);

開機(jī)自啟動(dòng)sh_system_init,創(chuàng)建gs_shell_task任務(wù),接收shell控制口的字符數(shù)據(jù),滿足一定條件后進(jìn)入sh_exec,搜索FsymTab段區(qū)間變量名,sh_get_cmd_func找到對(duì)應(yīng)函數(shù)再執(zhí)行。

shell工具便于調(diào)試,調(diào)試復(fù)雜功能注意??臻g;但其在數(shù)據(jù)安全方面存在較大隱患,且占用獨(dú)立的task和串口,浪費(fèi)硬件資源,正式發(fā)布的軟件務(wù)必關(guān)閉。

3.6 單元測(cè)試

類比assert的作用,判斷條件為假時(shí)觸發(fā)異常,單元測(cè)試與其類似,統(tǒng)計(jì)判斷結(jié)果導(dǎo)致報(bào)告。OneOS 開發(fā)的單元測(cè)試框架atest(and test),和網(wǎng)上開源的差不多。

#define ATEST_TC_EXPORT(name, testcase, init, cleanup, priority)                            
    OS_USED static const atest_tc_entry_t gs_atest##testcase OS_SECTION("AtestTcTab") =     
    {                                                                                       
        #name,                                                                              
        init,                                                                               
        testcase,                                                                           
        cleanup,                                                                            
        priority                                                                            
    };

其原理就是軟件自動(dòng)執(zhí)行某一段代碼,將運(yùn)行結(jié)果和期望值進(jìn)行比較并統(tǒng)計(jì),對(duì)軟件質(zhì)量的檢測(cè)效果,取決于單元測(cè)試用例的設(shè)計(jì)水平。該功能與平臺(tái)無(wú)關(guān),適用于新平臺(tái)首次使用時(shí)測(cè)試API。

4、 Python開發(fā)

基于前面shell的原理,可以按輸入的字符串執(zhí)行與之綁定的函數(shù),如果對(duì)字符串進(jìn)行一定的規(guī)則定義,支持自動(dòng)解析執(zhí)行,即可實(shí)現(xiàn)函數(shù)按提供的文本執(zhí)行。這套文本規(guī)則就是python語(yǔ)法,解析器就是MicroPython內(nèi)核,這樣就能實(shí)現(xiàn)在嵌入式平臺(tái)使用python開發(fā)。

MicroPython對(duì)軟件進(jìn)行天然的分層,嚴(yán)格區(qū)分驅(qū)動(dòng)層和應(yīng)用層,實(shí)現(xiàn)應(yīng)用軟件的跨平臺(tái)移植。Oneos集成的就是開源的MicroPython,其源碼下載地址是:https://github.com/micropython/micropython

OneOS-MicroPython開發(fā)環(huán)境:VsCode+NODE+Pymakr ,其中.mpy文件混淆加密的工具在MicroPython源碼mpy-cross中自行編譯。

短期內(nèi)Python不會(huì)成為嵌入式的主流開發(fā)語(yǔ)言,但掌握其基礎(chǔ)也有大有裨益。

中國(guó)移動(dòng)

中國(guó)移動(dòng)

中國(guó)移動(dòng)有限公司(「本公司」,包括子公司合稱為「本集團(tuán)」)于1997年9月3日在香港成立,本集團(tuán)在中國(guó)內(nèi)地所有三十一個(gè)省、自治區(qū)、直轄市以及香港特別行政區(qū)提供通信和信息服務(wù),業(yè)務(wù)主要涵蓋個(gè)人、家庭、政企和新興市場(chǎng)的語(yǔ)音、數(shù)據(jù)、寬帶、專線、IDC、云計(jì)算、物聯(lián)網(wǎng)等,是中國(guó)內(nèi)地最大的通信和信息服務(wù)供應(yīng)商,亦是全球網(wǎng)絡(luò)和客戶規(guī)模最大、盈利能力領(lǐng)先、市值排名位居前列的世界級(jí)通信和信息運(yùn)營(yíng)商。

中國(guó)移動(dòng)有限公司(「本公司」,包括子公司合稱為「本集團(tuán)」)于1997年9月3日在香港成立,本集團(tuán)在中國(guó)內(nèi)地所有三十一個(gè)省、自治區(qū)、直轄市以及香港特別行政區(qū)提供通信和信息服務(wù),業(yè)務(wù)主要涵蓋個(gè)人、家庭、政企和新興市場(chǎng)的語(yǔ)音、數(shù)據(jù)、寬帶、專線、IDC、云計(jì)算、物聯(lián)網(wǎng)等,是中國(guó)內(nèi)地最大的通信和信息服務(wù)供應(yīng)商,亦是全球網(wǎng)絡(luò)和客戶規(guī)模最大、盈利能力領(lǐng)先、市值排名位居前列的世界級(jí)通信和信息運(yùn)營(yíng)商。收起

查看更多

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄