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

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

3天內(nèi)不再提示

CANopenNode的移植接口詳解

CHANBAEK ? 來源:安德魯?shù)脑O(shè)計筆記本 ? 作者:安德魯蘇 ? 2023-06-23 15:49 ? 次閱讀

引言

CANopen是實現(xiàn)CAN設(shè)備組網(wǎng)的典型協(xié)議棧和規(guī)范,對應(yīng)于軟件系統(tǒng)中,有一些開源的軟件組件,實現(xiàn)了CANopen協(xié)議棧,例如CANopenNode和CAN Festival。CANFestival和CANopenNode都是用于在嵌入式系統(tǒng)上實現(xiàn)CANopen協(xié)議通信的開源軟件協(xié)議棧,但需要注意的是,它們使用了不同的開源協(xié)議:

  • CANFestival使用LGPLv2開源協(xié)議,這意味著CANFestival的源代碼是免費提供的,任何人都可以使用、修改和分發(fā),但衍生作品使用相同的GPL許可證。如果一個公司產(chǎn)品中使用CANFestival組件,他們也必須按照同樣的LGPLv2開源協(xié)議提供其產(chǎn)品的源代碼。
  • CANopenNode使用 Apache v2.0開源協(xié)議。這是一個自由度比LGPLv2更為開發(fā)的一個開源協(xié)議,允許在使用軟件方面有更大的靈活性。任何人都可以使用、修改和發(fā)布CANopenNode,甚至用于商業(yè)目的,而不需要發(fā)布其衍生作品的源代碼。

表x CANopenNode vs CAN Festival

image.png

本文將以CANopenNode為例,講解CANopen協(xié)議的一種實現(xiàn),并在具體的微控制器平臺上適配運行。

CANopenNode項目簡介

CANopenNode是一個免費的開源CANopen協(xié)議棧的實現(xiàn)。CANopen協(xié)議棧是一個在嵌入式控制器上的基于CAN總線高層應(yīng)用協(xié)議,遵循國際標準CiA 301(EN 50325-4)。CANopenNode實現(xiàn)了CANopen協(xié)議棧的絕大多數(shù)功能:

  • 網(wǎng)絡(luò)管理協(xié)議中,NMT從站狀態(tài)機(啟動、停止、復(fù)位設(shè)備)和簡單的NMT主站。
  • 錯誤控制協(xié)議中,心跳消息的生產(chǎn)者(發(fā)送方)和消費者(接收方)
  • PDO連接和動態(tài)映射到過程變量的快速交互
  • SDO快速傳輸、常規(guī)(分段)傳輸和塊傳輸
  • SDO主站
  • 緊急消息
  • 同步協(xié)議中的生產(chǎn)者(發(fā)送方)和消費者(接收方)
  • 授時協(xié)議中的生產(chǎn)者(發(fā)送方)和消費者(接收方)
  • 非易失性存儲
  • LSS服務(wù)的主站和從機,LSS快速掃描

CANopenNode的源碼在開源軟件網(wǎng)站GitHub上發(fā)布,https://github.com/CANopenNode/CANopenNode,開發(fā)者可以直接下載完整的CANopenNode源碼。此處需要注意,v1.3之后,持續(xù)開發(fā)的v2.0/4.0,在實現(xiàn)內(nèi)容上有較大變化。本文選用已經(jīng)標注“Verified”的v1.3版本,這也是目前最新的相對穩(wěn)定的發(fā)布版本。

圖片

figure-conode-github-pack

圖x 在GitHub上下載CANopenNode源碼包CANopenNode組件是以ANSI C語言編寫,可以作為一個標準的應(yīng)用組件,方便地移植到不同的微控制器平臺,或者是實時操作系統(tǒng)上。通過使用CANopenNode組件,可以在CANopen設(shè)備節(jié)點上創(chuàng)建一個對象字典(Object Dictionary),其中包含若干個變量(代表著配置信息),可以由本機直接通過C語言訪問,也可以由別的CANopen節(jié)點通過CAN網(wǎng)絡(luò)訪問,以此來實現(xiàn)CAN總線網(wǎng)絡(luò)系統(tǒng)中的信息交換,以及軟件系統(tǒng)對硬件系統(tǒng)的控制。

CANopenNode組件本身并不是一個完整的應(yīng)用程序,它包含一組實現(xiàn)CANopen協(xié)議棧的源碼和基于本身的樣例工程。如果要運行CANopenNode組件,還需要在一個具體的硬件平臺上進行適配,例如文本中即將用到的集成FlexCAN外設(shè)模塊的MM32F0140微控制器。

CANopenNode的開源站點上還開放了更多CANopen的功能組件,例如可以運行在Linux主機系統(tǒng)作為master的CANopenSocket項目,在多微控制器平臺上實現(xiàn)演示用例和測試工具的CANopenDemo項目,可以編輯對象字典生成C源碼文件的CAnopenEditor項目等等。

CANopenNode實現(xiàn)的工作流,如圖x所示。

圖片

figure-conode-workflow

圖x CANopenNode的工作流程其中,CAN總線接收線程和定時器周期執(zhí)行線程,可以在微控制器的中斷服務(wù)程序中實現(xiàn),主線線程可以在main()函數(shù)的主循環(huán)中實現(xiàn)。至于SDO客戶端和LSS(一個配置CANopen節(jié)點ID和比特率的服務(wù))客戶端,可以在應(yīng)用層的用戶程序中根據(jù)需要調(diào)用。

CANopenNode的源碼文件組織結(jié)構(gòu),如圖x所示。

圖片

figure-conode-source-files

圖x CANopenNode源碼文件的組織結(jié)構(gòu)CANopenNode項目的stack目錄下分別實現(xiàn)了CANopen協(xié)議中的對象(通信過程),并封裝在各自獨立的源文件中。特別地,在stack/drvTemplate目錄中,為開發(fā)者提供了一個向具體目標平臺移植CANopenNode的源碼模板,同時還提供了在多種不同微控制器平臺上移植CANopenNode的范例,例如stack/STM32, stack/LPC1768,stack/PIC32等。

CANopenNode的移植接口

CANopenNode的源碼目錄中,專門為在具體微控制器平臺上實現(xiàn)移植提供了源碼模板,位于stack/drvTemplate目錄中。本節(jié)簡要分析其中的代碼結(jié)構(gòu),為后續(xù)基于具體目標平臺實現(xiàn)移植奠定基礎(chǔ)。

stack/drvTemplate目錄下包含四個源文件:CO_driver.h, CO_driver_target.h, eeprom.c和eeprom.h。

CO_driver_target.h

CO_driver_target.h源文件包含了支持如下功能的數(shù)據(jù)類型定義、函數(shù)原型和宏定義:

  • 基本的數(shù)據(jù)類型
  • CANopen消息的接收和發(fā)送緩沖區(qū)
  • 同微控制器集成CAN外設(shè)模塊的接口
  • CAN外設(shè)的接收和發(fā)送中斷函數(shù)的聲明(將用于在移植過程中嵌入硬件中斷服務(wù)程序中)

這個源文件定義了的CANopen的底層驅(qū)動程序,還定義了一些專用于優(yōu)化協(xié)議執(zhí)行過程的數(shù)據(jù)結(jié)構(gòu),它不再使用的CAN消息隊列,而是直接將數(shù)據(jù)連接CANopen設(shè)備的對象(通信過程)上,盡量提高響應(yīng)速度,并減少不必要的計算和內(nèi)存開銷。

CO_CANmodule_t結(jié)構(gòu)類型中,包含了一組接收消息對象(CO_CANrx_t類型)和一組發(fā)送消息對象(CO_CANtx_t類型),每個CANopen通信對象都有自己專屬的其中一個成員。例如,心跳消息生產(chǎn)者可以創(chuàng)建一個CANopen發(fā)送對象,它就需要在CO_CANtx_t數(shù)組中預(yù)留一個表項。同步模塊可能產(chǎn)生一個同步對象或是接收一個同步的對象,它就需要在CO_CANtx_t數(shù)組或者CO_CANrx_t數(shù)組中預(yù)留一個表項。

接收過程

在接收到CAN消息之前,CO_CANrx_t中的每個成員都必須被初始化,此時需要調(diào)用CO_CANrxBufferInit()函數(shù),例如,在CO_HBconsumer中就使用了CO_CANrx_t中的多個成員(需要監(jiān)控多個遠程節(jié)點),就需要多次調(diào)用CO_CANrxBufferInit()函數(shù),對每個CO_CANrx_t進行初始化。CO_CANrxBufferInit()函數(shù)的兩個主要參數(shù),一個是CAN ID,另一個是一個回調(diào)函數(shù)的指針,這兩個參數(shù)將被寫入到CO_CANrx_t數(shù)組中。其中的回調(diào)函數(shù)是根據(jù)具體功能模塊實現(xiàn)的,用以處理接收的幀消息,將必要的數(shù)據(jù)搬運到合適的內(nèi)存中,然后觸發(fā)其他任務(wù)以繼續(xù)處理接收數(shù)據(jù)?;卣{(diào)函數(shù)的程序必須要短小精悍,僅做少量必要的計算和數(shù)據(jù)搬運工作,以避免耽誤后續(xù)接收幀的時機。

接收CAN幀的操作將在CAN外設(shè)模塊的接收中斷服務(wù)中進行。當在接收中斷服務(wù)程序中捕獲到CAN消息后,程序首先將它的CAN ID同CO_CANrx_t數(shù)組中的成員進行匹配,如果匹配到預(yù)先配置好的CO_CANrx_t,就會執(zhí)行其中的回調(diào)函數(shù)。

回調(diào)函數(shù)有兩個傳入?yún)?shù):

  • object - CO_CANrxBufferInit()函數(shù)注冊的一個指向傳輸對象的指針
  • msg - 一個指向CO_CANrxMsg_t類型CAN消息的指針

回調(diào)函數(shù)可以返回CO_ReturnError_t類型的狀態(tài)值:

  • CO_ERROR_NO
  • CO_ERROR_RX_OVERFLOW
  • CO_ERROR_RX_PDO_OVERFLOW
  • CO_ERROR_RX_MSG_LENGTH
  • CO_ERROR_RX_PDO_LENGTH。

發(fā)送過程

在發(fā)送CAN消息之前,CO_CANtx_t列表中的成員必須被CO_CANtxBufferInit()函數(shù)初始化。例如,心跳消息生產(chǎn)者就必須初始化它在CO_CANtx_t數(shù)組中的成員。CO_CANtxBufferInit()函數(shù)翻譯一個指向CO_CANtx_t類型結(jié)構(gòu)體的指針,其中包含了一個緩沖區(qū),可以存放即將要發(fā)送幀的數(shù)據(jù)。之后,可以通過調(diào)用CO_CANsend()函數(shù)啟動發(fā)送過程。如果恰巧微控制器硬件的發(fā)送緩沖區(qū)是可用的,就可以直接將發(fā)送消息從內(nèi)存中搬運到CAN外設(shè)的硬件緩沖區(qū)中等待發(fā)送,否則,CO_CANsend()函數(shù)將設(shè)定_bufferFull_標志位為True,之后將通過發(fā)送中斷觸發(fā)的硬件發(fā)送緩沖區(qū)可用事件,觸發(fā)數(shù)據(jù)搬運過程并啟動發(fā)送。CO_CANtx_t中的數(shù)據(jù)在通過CAN外設(shè)發(fā)送出去之前,是不可改動的。這里CO_CANtx_t隊列中可能有多個成員的_bufferFull_標志位為True,此時,編號更小的CO_CANtx_t將被優(yōu)先發(fā)送出去。

關(guān)鍵區(qū)域的函數(shù)

CANopenNode被設(shè)計基于多個線程運行,不同系統(tǒng)平臺對多線程的實現(xiàn)方式也不盡相同。在微控制器平臺,可以使用不同優(yōu)先級的中斷服務(wù)程序?qū)崿F(xiàn)多個線程。此時,需要將多個線程可能共同訪問的資源保護起來。一種簡單的實現(xiàn),可以在中斷服務(wù)程序或者后臺的調(diào)度器使用這些共享資源時,禁用對方,或者使用信號量等同步機制。

部分函數(shù)可以在不同的線程被調(diào)用:

  • CO_driver.h中的CO_CANsend()函數(shù)
  • CO_Emergency.h中的CO_errorReport()函數(shù)和CO_errorReset()函數(shù)

通常只有兩個線程會訪問到對象字典變量:一個是主線程,另一個是定時器線程。CANopenNode在主線程中運行CANopenNode的初始化過程和SDO服務(wù)端程序。PDO的程序運行在周期更短的定時器線程中,并且處理PDO的過程不能被主線程打斷。主線程必須保護定時器線程同時在訪問的對象字典變量,應(yīng)用層的程序也是如此。需要注意的是,并不是所有的對象字典變量可以被映射到PDO,所以這些不被PDO操作的變量是不需要被保護起來的。SDO服務(wù)端操作是會保護操作對象字典中的變量。

CAN接收線程對接收到的CAN消息幀進行簡單處理后,將它們寫入對應(yīng)的對象中,交由別的線程在后續(xù)繼續(xù)處理。這個過程不需要保護任何關(guān)鍵區(qū)域。但有一個例外,當同步消息出現(xiàn)在CANopen的總線上時, 需要臨時禁用CANrx(),直到所有的PDO都處理完畢。

這里需要開發(fā)者在移植CANopenNode到具體的微控制器平臺上時,需要實現(xiàn)保護關(guān)鍵區(qū)的宏函數(shù):

#define CO_LOCK_CAN_SEND()  /**< Lock critical section in CO_CANsend() */
#define CO_UNLOCK_CAN_SEND()/**< Unlock critical section in CO_CANsend() */

#define CO_LOCK_EMCY()      /**< Lock critical section in CO_errorReport() or CO_errorReset() */
#define CO_UNLOCK_EMCY()    /**< Unlock critical section in CO_errorReport() or CO_errorReset() */

#define CO_LOCK_OD()        /**< Lock critical section when accessing Object Dictionary */
#define CO_UNLOCK_OD()      /**< Unock critical section when accessing Object Dictionary */

內(nèi)存同步函數(shù)

在接收CAN通信幀和處理消息的線程間同步消息緩沖區(qū)。當在中斷服務(wù)程序中運行接收函數(shù),則不需要進行任何同步操作,因為一旦中斷發(fā)生,CPU的使用權(quán)會自動從其它處理消息幀的線程切換到中斷服務(wù)程序。否則,需要使用一些同步機制,確保先接收到完整的CAN消息幀之后再處理它們。例如,使用GCC編譯器時,可以使用GCC編譯器內(nèi)置的內(nèi)存邊界函數(shù)__sync_synchronize(),此時,只要將CANrxMemoryBarrier()函數(shù)映射到這個內(nèi)存邊界函數(shù)即可。

#define CANrxMemoryBarrier() {__sync_synchronize();}

CO_driver_target.h文件中定義了一組內(nèi)存同步相關(guān)的函數(shù):

/** Memory barrier */
#define CANrxMemoryBarrier()
/** Check if new message has arrived */
#define IS_CANrxNew(rxNew) ((uintptr_t)rxNew)
/** Set new message flag */
#define SET_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)1L;}
/** Clear new message flag */
#define CLEAR_CANrxNew(rxNew) {CANrxMemoryBarrier(); rxNew = (void*)0L;}

CO數(shù)據(jù)類型

CO_driver_target.h文件的后續(xù),還定了一些基本數(shù)據(jù)類型:

/**
 * @defgroup CO_dataTypes Data types
 * @{
 *
 * According to Misra C
 */
/* int8_t to uint64_t are defined in stdint.h */
typedef unsigned char           bool_t;     /**< bool_t */
typedef float                   float32_t;  /**< float32_t */
typedef long double             float64_t;  /**< float64_t */
typedef char                    char_t;     /**< char_t */
typedef unsigned char           oChar_t;    /**< oChar_t */
typedef unsigned char           domain_t;   /**< domain_t */
/** @} */

以及CANopenNode在操作CAN硬件驅(qū)動時涉及到的結(jié)構(gòu)體類型的定義,包括:

  • CO_CANrxMsg_t - 接收CAN幀結(jié)構(gòu)體
  • CO_CANrx_t - 接收消息對象
  • CO_CANtx_t - 發(fā)送消息對象
  • CO_CANmodule_t - CAN外設(shè)模塊對象

以及最后聲明了CO_CANinterrupt()函數(shù),便于開發(fā)者在移植時嵌入中斷服務(wù)程序:

void CO_CANinterrupt(CO_CANmodule_t *CANmodule);

CO_driver.c

CO_driver.c文件是CANopenNode對接微控制器的底層接口,在CO_driver.c文件的函數(shù)中,添加操作目標微控制器平臺包含CAN外設(shè)模塊在內(nèi)的電路系統(tǒng)的代碼,建立CANopenNode同具體微控制器平臺的綁定。CO_driver.c文件中實現(xiàn)了一些對CAN外設(shè)驅(qū)動進行抽象的函數(shù),如表x所示。

表x CANopenNode抽象的CAN外設(shè)驅(qū)動函數(shù)清單

image.png

在具體的目標微控制器平臺上移植CANopenNode時,需要結(jié)合具體的硬件CAN外設(shè)模塊,補充這些函數(shù)中對硬件的操作。

eeprom.h & eeprom.c

eeprom.h和eeprom.c文件,綁定了讀寫EEPROM存儲器的驅(qū)動程序,可以在CANopen協(xié)議運行的過程中,將對象字典保存在EEPROM存儲器中。在基本的移植中,可以不實現(xiàn)將對象字典存儲在外部存儲器的功能。

/**
 * Eeprom object.
 */
typedef struct{
    uint8_t     *OD_EEPROMAddress;      /**< From CO_EE_init_1() */
    uint32_t     OD_EEPROMSize;         /**< From CO_EE_init_1() */
    uint8_t     *OD_ROMAddress;         /**< From CO_EE_init_1() */
    uint32_t     OD_ROMSize;            /**< From CO_EE_init_1() */
    uint32_t     OD_EEPROMCurrentIndex; /**< Internal variable controls the OD_EEPROM vrite */
    bool_t       OD_EEPROMWriteEnable;  /**< Writing to EEPROM is enabled */
}CO_EE_t;

/**
 * First part of eeprom initialization. Called after microcontroller reset.
 *
 * @param ee This object will be initialized.
 * @param OD_EEPROMAddress Address of OD_EEPROM structure from object dictionary.
 * @param OD_EEPROMSize Size of OD_EEPROM structure from object dictionary.
 * @param OD_ROMAddress Address of OD_ROM structure from object dictionary.
 * @param OD_ROMSize Size of OD_ROM structure from object dictionary.
 *
 * @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_DATA_CORRUPT (Data in eeprom corrupt) or
 * CO_ERROR_CRC (CRC from MBR does not match the CRC of OD_ROM block in eeprom).
 */
CO_ReturnError_t CO_EE_init_1(
        CO_EE_t                *ee,
        uint8_t                *OD_EEPROMAddress,
        uint32_t                OD_EEPROMSize,
        uint8_t                *OD_ROMAddress,
        uint32_t                OD_ROMSize);

/**
 * Second part of eeprom initialization. Called after CANopen communication reset.
 *
 * @param ee          - This object.
 * @param eeStatus    - Return value from CO_EE_init_1().
 * @param SDO         - SDO object.
 * @param em          - Emergency object.
 */
void CO_EE_init_2(
        CO_EE_t                *ee,
        CO_ReturnError_t        eeStatus,
        CO_SDO_t               *SDO,
        CO_EM_t                *em);

/**
 * Process eeprom object.
 *
 * Function must be called cyclically. It strores variables from OD_EEPROM data
 * block into eeprom byte by byte (only if values are different).
 *
 * @param ee This object.
 */
void CO_EE_process(CO_EE_t *ee);

基于FlexCAN適配CANopenNode

(未完待續(xù))

一個CANopenNode的應(yīng)用樣例

(未完待續(xù))

總結(jié)

(未完待續(xù))

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

    關(guān)注

    5082

    文章

    19123

    瀏覽量

    305143
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8596

    瀏覽量

    151145
  • 移植
    +關(guān)注

    關(guān)注

    1

    文章

    379

    瀏覽量

    28130
  • 開源
    +關(guān)注

    關(guān)注

    3

    文章

    3348

    瀏覽量

    42496
  • CANopen
    +關(guān)注

    關(guān)注

    8

    文章

    253

    瀏覽量

    43586
收藏 人收藏

    評論

    相關(guān)推薦

    基于MM32G5330的FlexCAN實現(xiàn)CANopenNode協(xié)議棧移植

    本文將介紹如何基于靈動MM32G5330的FlexCAN實現(xiàn)CANopenNode協(xié)議棧的移植,并使用靈動官方提供的開發(fā)板Mini-G5333進行驗證。
    發(fā)表于 04-12 09:15 ?1497次閱讀
    基于MM32G5330的FlexCAN實現(xiàn)<b class='flag-5'>CANopenNode</b>協(xié)議棧<b class='flag-5'>移植</b>

    串行通訊接口詳解

    本帖最后由 eehome 于 2013-1-5 09:52 編輯 串行通訊接口詳解,
    發(fā)表于 08-08 11:20

    uCOS-II如何在STM32上的移植詳解

    下載用uCOS-II在STM32上的移植詳解.pdf (1.64 MB )
    發(fā)表于 05-26 02:13

    STM32程序的移植詳解步驟

    一,概括程序的移植包括以下幾步1.觀察待移植程序調(diào)用了哪些文件,將這些文件放入移植的工程當中2.在keil當中添加這些文件,并且添加.h文件的路徑3.處理頭文件及軟件版本匹配的問題二,詳解
    發(fā)表于 08-23 07:27

    RTAI分析及在s3c4510上的移植詳解

    RTAI分析及在s3c4510上的移植詳解
    發(fā)表于 03-28 09:52 ?24次下載

    uCOSII在LPC2210上的移植詳解

    uCOSII在LPC2210上的移植詳解:嵌入式實時操作系統(tǒng)在目標處理器平臺上的移植是嵌入式軟件開發(fā)的基礎(chǔ)和前提。論文實現(xiàn)了源碼公開的嵌入式實時操作系統(tǒng)μC/OS- II 在ARM7 微控制器LPC2
    發(fā)表于 12-31 15:11 ?144次下載

    嵌入式Linux內(nèi)核移植詳解(頂嵌)

    嵌入式內(nèi)核移植步驟詳解 含配置含義及內(nèi)容等方面
    發(fā)表于 11-20 16:00 ?19次下載

    LCD接口類型詳解

    LCD接口類型詳解--大盛唐電子,專業(yè)代理啊ALLANCEMXICISOCOMEXARHKCATO天馬屏!
    發(fā)表于 06-06 14:48 ?0次下載

    PCI-Express接口術(shù)語詳解

    計算機接口中關(guān)于PCI-Express的詳解
    發(fā)表于 09-01 14:55 ?0次下載

    幾種串行通信接口標準詳解

    幾種串行通信接口標準詳解
    發(fā)表于 01-03 11:34 ?0次下載

    網(wǎng)絡(luò)接口跨平臺移植擴展控件設(shè)計

    網(wǎng)絡(luò)接口跨平臺移植擴展控件設(shè)計_魏惠茹
    發(fā)表于 01-07 21:39 ?0次下載

    《Linux設(shè)備驅(qū)動開發(fā)詳解》第23章、Linux設(shè)備驅(qū)動的移植

    《Linux設(shè)備驅(qū)動開發(fā)詳解》第23章、Linux設(shè)備驅(qū)動的移植
    發(fā)表于 10-27 10:58 ?9次下載
    《Linux設(shè)備驅(qū)動開發(fā)<b class='flag-5'>詳解</b>》第23章、Linux設(shè)備驅(qū)動的<b class='flag-5'>移植</b>

    Uboot移植步驟詳解

    Uboot移植步驟詳解
    發(fā)表于 10-30 08:46 ?21次下載
    Uboot<b class='flag-5'>移植</b>步驟<b class='flag-5'>詳解</b>

    uCOS_ARM移植要點詳解

    uCOS_ARM移植要點詳解
    發(fā)表于 10-31 11:25 ?11次下載
    uCOS_ARM<b class='flag-5'>移植</b>要點<b class='flag-5'>詳解</b>

    基于FlexCAN適配CANopenNode

    總結(jié)在微控制器平臺上移植CANopenNode,需要根據(jù)具體硬件條件,適配2個源文件。
    的頭像 發(fā)表于 06-23 15:51 ?1570次閱讀
    基于FlexCAN適配<b class='flag-5'>CANopenNode</b>