• <progress id="w0lee"></progress>

  • <span id="w0lee"></span>
  • ESM8000異構CPU實時應用——6路CAN-FD的實現

     2021-9-7 9:58:52     作者:劉乾坤 黃志超 朱賢武    

      ESM8000工控主板搭載了NXP i.MX8M Mini Quad 64位異構處理器,包含了一顆主頻1.6GHz的四核ARM Cortex-A53和一顆主頻400MHz 的ARM Cortex-M4。Linux系統在Cortex-A53核心上運行,對于一些實時性要求極高的應用,Linux系統可能無法滿足對中斷事件的及時響應,而且頻繁的中斷響應也會大大的降低操作系統性能。對這類應用場合就可充分利用i.MX8MM異構多核結構,由高性能的Cortex-A53(Linux系統)完成人機交互、數據處理、通訊管理等復雜運算,而對于實時的數據采集、高速的中斷事件響應等實時任務交由Cotex-M4完成。


      控制器局域網 (Controller Area Network,簡稱CAN或者CAN bus) 是一種功能豐富的總線標準。最開始作為車載總線而被設計出來,隨著CAN總線標準的不斷發展和完善,在工業領域中越來越多的行業會使用到CAN總線。在實際的應用中,為了保證CAN總線的實時性,一般要求CAN總線的負載不能過高。因此在連接多個設備的時候,就需要使用到多路CAN總線來進行連接,保證每一路CAN總線的負載滿足要求。


      英創公司針對多CAN總線應用的需求設計了ETA706模塊,該模塊通過SPI總線與主板連接,利用ESM8000的SPI1,再通過ESM8000的兩位GPIO譯碼出4個片選,擴展了4片MCP2518FD CAN控制芯片,支持CAN2.0 / CAN FD協議,加上主板上自帶的兩路CAN,實現了6路CAN總線方案。CAN擴展原理框圖與硬件測試環境,如圖1、圖2所示:


    ESM8000異構CPU實時應用——多路CAN擴展.png

    圖1:6x CAN擴展驅動原理框圖


    sbc880+esm8000+eta706.png

    圖2:  6x CAN硬件測試環境


      當CAN總線上數據量較大時,SPI總線需要頻繁的中斷和讀寫操作,如果由Linux系統來處理中斷和SPI操作,就會占用相當多的CPU資源。此時就可充分利用i.MX8MM異構CPU結構,由Crotex-M4來處理CAN中斷和SPI通訊,Linux系統只處理Crotex-M4傳遞過來的CAN帖數據,從而大大節省ESM8000上Cortex-A53的開銷,留出更多CPU資源。


      Coretx-M4應用程序基于FreeRTOS,完成了對MCP2518FD參數配置、中斷響應、數據收發等工作。由于擴展的4路MCP2518FD使用ESM8000的SPI1,通過2位GPIO譯碼出4個片選,所以對SPI1的操作使用Mutex信號量進行互斥保護。對多個MCP2815FD進行片選的實現代碼如下:


    #define CH_SEL0 ESM_GPIO26
    #define CH_SEL1 ESM_GPIO27
    ecspi_rtos_handle_t *DRV_SPI_ChipSelectAssert(uint8_t spiSlaveDeviceIndex, bool assert)
    {
        ecspi_rtos_handle_t *handle = NULL;
        static uint8_t last_spiIndex = 0;
        if (assert)
        {        
            if(spiSlaveDeviceIndex < 2)
                handle = &spi[1 + spiSlaveDeviceIndex];
            else        {
                /* Lock resource mutex */
                xSemaphoreTake(spi1_mutex, portMAX_DELAY);  
                
                handle = &spi[0];
                spiSlaveDeviceIndex -= 2;
                /* i.MX8MM 操作一次GPIO的需要300ns左右,所以這里對操作GPIO進行優化 */
                if(spiSlaveDeviceIndex != last_spiIndex)           {
                    switch (spiSlaveDeviceIndex)
                    {
                    case 0:
                        GPIO_PortOutClear(CH_SEL0, (0x1 << CH_SEL0->pin) | (0x1 << CH_SEL1->pin));
                        break;
                    case 1:    
                        if((last_spiIndex & 0x01) == 0)                
                            GPIO_OutSet(CH_SEL0, 1);
                        if((last_spiIndex & 0x02) != 0)
                            GPIO_OutSet(CH_SEL1, 0);
                        break;
                    case 2:
                        if((last_spiIndex & 0x01) != 0)   
                            GPIO_OutSet(CH_SEL0, 0);
                        if((last_spiIndex & 0x02) == 0)
                            GPIO_OutSet(CH_SEL1, 1);
                        break;
                    case 3:
                        GPIO_PortOutSet(CH_SEL0, (0x1 << CH_SEL0->pin) | (0x1 << CH_SEL1->pin));
                        break;
                    default:
                        handle = NULL;
                        last_spiIndex = 0;
                        GPIO_PortOutClear(CH_SEL0, (0x1 << CH_SEL0->pin) | (0x1 << CH_SEL1->pin));
                    }
                    last_spiIndex = spiSlaveDeviceIndex;
                }
            }
        }
        else    {
            if (spiSlaveDeviceIndex > 1)        {
                /* Unlock resource mutex */
                (void)xSemaphoreGive(spi1_mutex);
            }
        }
    return handle;
    }


      4路MCP2815FD的中斷輸出直接連接到ESM8000的4位GPIO, GPIO在i.MX8MM處理器上是按組(PORT)操作的。每組32位IO,而IO中斷又在PORT內再次被分為高低兩組,每組對應16位IO,共享一個中斷源。以擴展的CAN2和CAN3為例,它們的中斷輸出分別連接到ESM8000的GPIO2、GPIO3,分別對應到i.MX8MM的GPIO_PORT5_Pin26和GPIO_PORT5_Pin27,它們使用同一個GPIO中斷源GPIO5_Combined_16_31_IRQn。當GPIO中斷產生后,需要通過讀取gpio_isr中斷狀態寄存器來判斷具體是那位GPIO引起的中斷。對應的中斷處理代碼如下所示:


    static inline void GPIO_CommonIRQHandler(uint8_t index, uint32_t gpio_isr, uint32_t gpio_imr, BaseType_t *reschedule)
    {        
        if (((gpio_imr >> mcp251xfd[index].int_gpio->pin) & 1) != 0)
        {               
            if (((gpio_isr >> mcp251xfd[index].int_gpio->pin) & 1) != 0)
            {
                /* Disable GPIO pin interrupt */            
                GPIO_PinIntEnalbe_FromISR(mcp251xfd[index].int_gpio, false);            
                /* clear the interrupt status */
                GPIO_ClearStatus(mcp251xfd[index].int_gpio);
                /* Unlock the task to process the event. */
                xSemaphoreGiveFromISR(mcp251xfd[index].xMcp251xINT_event, reschedule);
            }        
        }    
    }
    void GPIO5_Combined_16_31_IRQHandler(void)
    {
        uint32_t gpio_isr, gpio_imr;
        BaseType_t reschedule = false;
        gpio_isr = GPIO_PortGetStatus(GPIO5);  
        gpio_imr = GPIO_PortGetIMR(GPIO5);      
        GPIO_CommonIRQHandler(2, gpio_isr, gpio_imr, &reschedule);
        GPIO_CommonIRQHandler(3, gpio_isr, gpio_imr, &reschedule);
        /* Perform a context switch to wake the higher priority task. */
        portYIELD_FROM_ISR(reschedule);      
    }


      在ESM8000的Linux系統中,可以通過RPMsg和Crotex-M4進行通訊來獲取相關的信息,關于RPMsg的介紹可以參考《ESM7000異構CPU實時應用之二基于rpmsg的通訊機制》。英創公司已經提供了相應的驅動文件,加載后會生成標準的CAN設備。在驅動中會通過RPMsg和Crotex-M4進行通信以及數據的處理,但對于用戶來說是不需要關心的,直接使用標準的socketcan操作驅動生成的CAN設備就行了,用戶程序對CAN設備的操作,驅動都會將對應的操作通過RPMsg發送給Crotex-M4,然后由Crotex-M4實際對硬件執行對應的操作,如下圖所示:


    ESM8000異構CPU實時應用——多路CAN擴展.png

    圖3:軟件原理框圖


      驅動文件在系統啟動完成后會自動加載,如下圖:


    ESM8000異構CPU實時應用——多路CAN擴展.png


      通過命令ifconfig –a可以查看新生成的can0-can5這6個CAN設備,使用標準的socketcan就能夠對這6個CAN設備進行操作。詳細的程序可以參考英創公司提供的例程test_socketcan。下面主要介紹針對這6路CAN設備進行的測試情況。


      首先測試單路CAN總線(can0)的性能,測試采用250Kbps波特率,在該波特率下,CAN總線負載最高大約為每秒2000幀,分別測試了收發不同數據量情況下主板的負載表現,為了更直觀的體現出M4對負載的分擔,我們在同樣條件下測試了直接使用Linux系統(即Cortex-A53)控制時的負載:


    測試數據與擴展方式

    接收

    1000幀/秒

    接收

    2000幀/秒

    發送

    1000幀/秒

    接收和發送

    各1000幀/秒

    異構CPU控制

    A53:10%

    M4:8.5%

    A53:18%

    M4:15.8%

    A53:10%

    M4:5.3%

    A53:18%

    M4:14.8%

    Linux直接控制A53:10%A53:22%A53:24%A53:38%


      因為運行Linux系統的Cortex-A53為4核心,所以A53總負載為400%。通常系統會自動均衡負載,比如20%的負載,理想狀態下會自動為4個核心各配分5%的負載。


      下面同時對比測試兩路CAN總線(can0和can1)通訊的情況:


    測試數據與擴展方式

    接收

    1000幀/秒

    接收

    2000幀/秒

    發送

    1000幀/秒

    接收和發送

    各1000幀/秒

    異構CPU控制

    A53:13%

    M4:24.3%

    A53:25%

    M4:39%

    A53:18%

    M4:10.1%

    A53:32%

    M4:31.8%

    Linux直接控制A53:40%A53:80%A53:46%A53:88%


      通過上面表格的對比,可以看出來通過Cortex-M4擴展的方案可以有效的降低Linux系統的負載,留出更多的CPU資源給用戶使用。


      下面我們采用比較極限的情況來進行測試這套擴展方案的性能,將6路CAN總線同時運行起來,測試每一路CAN總線在250Kbps波特率下每秒接收1000幀和2000幀數據時的系統負載,測試數據如下表:


    測試數據與擴展方式

    接收

    1000幀/秒

    接收

    2000幀/秒

    異構CPU控制

    A53:37.5%

    M4:48%

    A53:48%

    M4:99%


      同時我們驗證了每一路CAN總線接收數據的準確性,均沒有出現丟幀的情況。在250Kbps波特率下,每秒2000幀數據已經達到CAN總線的滿載。而6路CAN總線均滿載的情況下Cortex-M4也已經達到滿載,說明這套方案的極限性能大約為6路CAN總線每一路達到每秒2000幀的數據量。


      如果對這套方案感興趣的客戶,可以和英創的工程師聯系,獲取詳細的測試代碼和資料。

    强奷漂亮脱肉丝袜无码视频-毛1卡2卡3卡4卡免费视频-亚洲成a∨人片在线观看无码-欧美日韩一区二区综合