<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      痞子衡嵌入式:飛思卡爾Kinetis系列MCU啟動那些事(1)- KBOOT架構


        大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是飛思卡爾Kinetis系列MCU的KBOOT架構

        Bootloader是嵌入式MCU開發里很常見的一種專用的應用程序,在一個沒有Bootloader的嵌入式系統里如果要更新Application,只能通過外部硬件調試器/下載器,而如果有了Bootloader,我們可以輕松完成Application的更新升級以及加載啟動,除此以外在Bootloader中還可以引入更多高級特性,比如Application完整性檢測、可靠升級、加密特性等。
        KBOOT是設計運行于Kinetis芯片上的一種Bootloader,KBOOT由飛思卡爾(現恩智浦)官方推出,其功能非常全面,今天痞子衡就為你揭開KBOOT的神秘面紗:

      一、KBOOT由來

        飛思卡爾Kinetis系列MCU是從2010年開始推出的,早期的Kinetis產品比如MK60, MKL25并沒有配套標準Bootloader功能,不過可以從飛思卡爾官網上找到很多風格迥異的Bootloader參考設計,比如AN2295(UART型)、AN4655(I2C型)、AN4379(USB-MSD型)等,這些Bootloader參考方案都是不同的飛思卡爾應用工程師設計的,因此所用的通信協議以及上位機工具都不相同,雖然這些AN一定程度上能解決客戶使用Bootloader的需求,但是在Bootloader后續維護升級以及拓展性方面有一定缺陷。
        飛思卡爾也逐漸意識到了這一點,為了完善軟件生態建設與服務質量,于是在2013年初組建了一支專門開發Kinetis Bootloader的軟件團隊,即KBOOT Team,這個Team成立的目的就是要開發出一個Unified Kinetis Bootloader(簡稱KBOOT),這個bootloader必須擁有良好的架構,易于擴展和維護,功能全面且經過完善的驗證。
        KBOOT項目發展至今(2017)已近5年,目前被廣泛應用于主流Kinetis芯片上,是Kinetis芯片集成Bootloader的首選,其官方主頁是 www.nxp.com/kboot

      二、KBOOT架構

        從架構角度來分析KBOOT,拋開各種附加特性,其實KBOOT最核心的就是這三大組件:Peripheral Interface、Command & Data Processor、Memory Interface,如下圖所示:

      2.1 Peripheral Interface

        KBOOT首要功能是能夠與Host進行數據傳輸,我們知道數據傳輸接口種類有很多,KBOOT設計上可同時支持多種常見傳輸接口(UART, SPI, I2C, USB-HID, CAN),為此KBOOT在Peripheral Interface組件中抽象了Peripheral的行為(byte/packet層傳輸等),使得在Peripheral種類拓展上更容易。
        KBOOT中使用一個名叫g_peripherals[]的結構體數組來集合所有外設,下面示例僅包含UART, USB:

      //! @brief Peripheral array.
      const peripheral_descriptor_t g_peripherals[] = {
      #if BL_CONFIG_LPUART_0
          // LPUART0
          {.typeMask = kPeripheralType_UART,
           .instance = 0,
           .pinmuxConfig = uart_pinmux_config,
           .controlInterface = &g_lpuartControlInterface,
           .byteInterface = &g_lpuartByteInterface,
           .packetInterface = &g_framingPacketInterface },
      #endif // BL_CONFIG_LPUART_0
      
      #if BL_CONFIG_USB_HID
          // USB HID
          {.typeMask = kPeripheralType_USB_HID,
           .instance = 0,
           .pinmuxConfig = NULL,
           .controlInterface = &g_usbHidControlInterface,
           .byteInterface = NULL,
           .packetInterface = &g_usbHidPacketInterface },
      #endif    // BL_CONFIG_USB_HID
      
          { 0 } // Terminator
      };
      

        如下便是用于抽象外設行為的Peripheral descriptor原型,該原型可以描述所有類型的peripheral:

      //! @brief Peripheral descriptor.
      //!
      //! Instances of this struct describe a particular instance of a peripheral that is
      //! available for bootloading.
      typedef struct PeripheralDescriptor
      {
          //! @brief Bit mask identifying the peripheral type.
          //! See #_peripheral_types for a list of valid bits.
          // 外設的類型名,KBOOT用于識別當前外設的類型
          uint32_t typeMask;
      
          //! @brief The instance number of the peripheral.
          // 外設的編號,KBOOT可以支持同一外設的多個實例
          uint32_t instance;
      
          //! @brief Configure pinmux setting for the peripheral.
          // 外設的I/O初始化
          void (*pinmuxConfig)(uint32_t instance, pinmux_type_t pinmux);
      
          //! @brief Control interface for the peripheral.
          // 外設的行為控制
          const peripheral_control_interface_t *controlInterface;
      
          //! @brief Byte-level interface for the peripheral.
          //! May be NULL since not all periperhals support this interface.
          // 外設的byte級別傳輸控制
          const peripheral_byte_inteface_t *byteInterface;
      
          //! @brief Packet level interface for the peripheral.
          // 外設的packet級別傳輸控制
          const peripheral_packet_interface_t *packetInterface;
      } peripheral_descriptor_t;
      
      //! @brief Peripheral control interface.
      typedef struct _peripheral_control_interface
      {
          // 檢測是否外設是否被激活
          bool (*pollForActivity)(const peripheral_descriptor_t *self);
          // 外設IP底層初始化
          status_t (*init)(const peripheral_descriptor_t *self, serial_byte_receive_func_t function);
          // 外設IP底層恢復
          void (*shutdown)(const peripheral_descriptor_t *self);
          // 特殊外設pump控制(比如USB-MSC, DFU等)
          void (*pump)(const peripheral_descriptor_t *self);
      } peripheral_control_interface_t;
      
      //! @brief Peripheral abstract byte interface.
      typedef struct _peripheral_byte_inteface
      {
          // byte傳輸初始化,一般為NULL
          status_t (*init)(const peripheral_descriptor_t *self);
          // byte發送
          status_t (*write)(const peripheral_descriptor_t *self, const uint8_t *buffer, uint32_t byteCount);
      } peripheral_byte_inteface_t;
      
      //! @brief Peripheral Packet Interface.
      typedef struct _peripheral_packet_interface
      {
          // packet傳輸初始化
          status_t (*init)(const peripheral_descriptor_t *self);
          // 接收一包packet
          status_t (*readPacket)(const peripheral_descriptor_t *self, uint8_t **packet, uint32_t *packetLength, packet_type_t packetType);
          // 發送一包packet
          status_t (*writePacket)(const peripheral_descriptor_t *self, const uint8_t *packet, uint32_t byteCount, packet_type_t packetType);
          // 立即終止當前packet
          void (*abortDataPhase)(const peripheral_descriptor_t *self);
          // 完成當前packet
          status_t (*finalize)(const peripheral_descriptor_t *self);
          // 獲取最大packet包長
          uint32_t (*getMaxPacketSize)(const peripheral_descriptor_t *self);
          // byte接收callback
          void (*byteReceivedCallback)(uint8_t byte);
      } peripheral_packet_interface_t;
      

      2.2 Memory Interface

        KBOOT其次功能是能夠讀寫存儲空間,Kinetis上涉及的存儲空間包括內部SRAM, Flash,Register、I/O以及外部QuadSPI NOR Flash(可以映射在MCU內部存儲空間),為此KBOOT在Memory Interface組件中抽象了Memory的行為(read/write/erase等),使得在Memory種類拓展上更容易。
        KBOOT中使用一個名叫g_memoryMap[]的結構體數組來集合所有存儲空間,下面示例包含了典型的存儲空間(Flash、RAM、Register、I/O、QSPI NOR Flash):

      //! @brief Memory map.
      //!
      //! This map is not const because it is updated at runtime with the actual sizes of
      //! flash and RAM for the chip we're running on.
      //! @note Do not change the index of Flash, SRAM, or QSPI (see memory.h).
      memory_map_entry_t g_memoryMap[] = {
          { 0x00000000, 0x0003ffff, kMemoryIsExecutable, &g_flashMemoryInterface },    // Flash array (256KB)
          { 0x1fff0000, 0x2002ffff, kMemoryIsExecutable, &g_normalMemoryInterface },   // SRAM (256KB)
          { 0x68000000, 0x6fffffff, kMemoryNotExecutable, &g_qspiMemoryInterface },    // QSPI memory
          { 0x04000000, 0x07ffffff, kMemoryNotExecutable, &g_qspiAliasAreaInterface }, // QSPI alias area
          { 0x40000000, 0x4007ffff, kMemoryNotExecutable, &g_deviceMemoryInterface },  // AIPS0 peripherals
          { 0x40080000, 0x400fefff, kMemoryNotExecutable, &g_deviceMemoryInterface },  // AIPS1 peripherals
          { 0x400ff000, 0x400fffff, kMemoryNotExecutable, &g_deviceMemoryInterface },  // GPIO
          { 0xe0000000, 0xe00fffff, kMemoryNotExecutable, &g_deviceMemoryInterface },  // M4 private peripherals
          { 0 }                                                                        // Terminator
      };
      

        如下便是用于抽象存儲器操作的memory_map_entry原型,該原型可以描述所有類型的memory:

      //! @brief Structure of a memory map entry.
      typedef struct _memory_map_entry
      {
          // 存儲空間起始地址
          uint32_t startAddress;
          // 存儲空間結束地址
          uint32_t endAddress;
          // 存儲空間屬性(Flash/RAM,是否能XIP)
          uint32_t memoryProperty;
          // 存儲空間操作接口
          const memory_region_interface_t *memoryInterface;
      } memory_map_entry_t;
      
      typedef struct _memory_region_interface
      {
          // 存儲空間(IP控制器)初始化
          status_t (*init)(void);
          // 從存儲空間指定范圍內讀取數據
          status_t (*read)(uint32_t address, uint32_t length, uint8_t *buffer);
          // 將數據寫入存儲空間指定范圍內
          status_t (*write)(uint32_t address, uint32_t length, const uint8_t *buffer);
          // 將pattern填充入存儲空間指定范圍內
          status_t (*fill)(uint32_t address, uint32_t length, uint32_t pattern);
          // 對于支持page/section編程的存儲器做一次page/section數據寫入
          status_t (*flush)(void);
          // 將存儲空間指定范圍內容擦除
          status_t (*erase)(uint32_t address, uint32_t length);
      } memory_region_interface_t;
      

      2.3 Command & Data Processor

        KBOOT核心功能便是與Host之間的命令交互,KBOOT主要工作于Slave模式,實時監聽來自Host的命令并做出響應,KBOOT僅能識別事先規定好的命令格式,因此KBOOT必須配套一個專用上位機工具使用。你可能會疑問,為什么這個組件又叫Data Processor?因為有些命令是含有Data phase的(比如read memory, write memory),對于這些命令時除了基本的命令交互響應之后,還必須有數據傳輸交互響應。
        KBOOT中使用如下名叫g_commandInterface和g_commandHandlerTable[]的結構變量來實現核心命令交互,KBOOT中一共實現了19條命令:

      // See bl_command.h for documentation on this interface.
      command_interface_t g_commandInterface = 
      {
          bootloader_command_init,
          bootloader_command_pump,
          (command_handler_entry_t *)&g_commandHandlerTable,
          &g_commandData
      };
      
      //! @brief Command handler table.
      const command_handler_entry_t g_commandHandlerTable[] = {
          // cmd handler              // data handler or NULL
          { handle_flash_erase_all, NULL },              // kCommandTag_FlashEraseAll = 0x01
          { handle_flash_erase_region, NULL },           // kCommandTag_FlashEraseRegion = 0x02
          { handle_read_memory, handle_data_producer },  // kCommandTag_ReadMemory = 0x03
          { handle_write_memory, handle_data_consumer }, // kCommandTag_WriteMemory = 0x04
          { handle_fill_memory, NULL },                  // kCommandTag_FillMemory = 0x05
          { handle_flash_security_disable, NULL },       // kCommandTag_FlashSecurityDisable = 0x06
          { handle_get_property, NULL },                    // kCommandTag_GetProperty = 0x07
          { handle_receive_sb_file, handle_data_consumer }, // kCommandTag_ReceiveSbFile = 0x08
          { handle_execute, NULL },                         // kCommandTag_Execute = 0x09
          { handle_call, NULL },                            // kCommandTag_Call = 0x0a
          { handle_reset, NULL },                           // kCommandTag_Reset = 0x0b
          { handle_set_property, NULL },                    // kCommandTag_SetProperty = 0x0c
          { handle_flash_erase_all_unsecure, NULL },        // kCommandTag_FlashEraseAllUnsecure = 0x0d
          { handle_flash_program_once, NULL },              // kCommandTag_ProgramOnce = 0x0e
          { handle_flash_read_once, NULL },                 // kCommandTag_ReadOnce = 0x0f
          { handle_flash_read_resource, handle_data_producer }, // kCommandTag_ReadResource = 0x10
          { handle_configure_memory, NULL },                    // kCommandTag_ConfigureMemory = 0x11
          { handle_reliable_update, NULL },                     // kCommandTag_ReliableUpdate = 0x12
          { handle_generate_key_blob, handle_key_blob_data },   // kCommandTag_GenerateKeyBlob = 0x13
      };
      

        如下便是用于核心命令交互的Command interface原型:

      //! @brief Interface to command processor operations.
      typedef struct CommandInterface
      {
          // command處理控制單元初始化
          status_t (*init)(void);
          // command處理控制單元pump
          status_t (*pump)(void);
          // command服務函數查找表
          const command_handler_entry_t *handlerTable;
          // command處理控制單元狀態數據
          command_processor_data_t *stateData;
      } command_interface_t;
      
      //! @brief Format of command handler entry.
      typedef struct CommandHandlerEntry
      {
          // command服務函數
          void (*handleCommand)(uint8_t *packet, uint32_t packetLength);
          // command的data級處理函數(只有少部分command有此函數)
          status_t (*handleData)(bool *hasMoreData);
      } command_handler_entry_t;
      
      //! @brief Command processor data format.
      typedef struct CommandProcessorData
      {
          // command處理控制狀態機當前狀態(command/data兩種狀態)
          int32_t state;
          // 指向當前處理的packet地址
          uint8_t *packet;
          // 當前處理的packet長度
          uint32_t packetLength;
          // command的data級處理控制狀態數據
          struct DataPhase
          {
              uint8_t *data;               //!< Data for data phase
              uint32_t count;              //!< Remaining count to produce/consume
              uint32_t address;            //!< Address for data phase
              uint32_t memoryId;           //!< ID of the target memory
              uint32_t dataBytesAvailable; //!< Number of bytes available at data pointer
              uint8_t commandTag;          //!< Tag of command running data phase
              uint8_t option;              //!< option for special command
          } dataPhase;
          // 指向command服務函數查找表地址
          const command_handler_entry_t *handlerEntry; //! Pointer to handler table entry for packet in process
      } command_processor_data_t;
      

        至此,飛思卡爾Kinetis系列MCU的KBOOT架構痞子衡便介紹完畢了,掌聲在哪里~~~

      posted @ 2017-04-02 21:45  痞子衡  閱讀(1721)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 丝袜人妻一区二区三区网站| 亚洲日产韩国一二三四区| 国产精品午夜福利资源| 成人国产精品中文字幕| 国产强奷在线播放免费| 中文字幕无线码中文字幕| 欧美性猛交xxxx乱大交极品| 欧美做受视频播放| 亚洲区一区二区三区精品| 内射老阿姨1区2区3区4区| 色综合伊人色综合网站| 亚洲国产在一区二区三区| 高清有码国产一区二区| 国产成人亚洲综合图区| 韩国精品一区二区三区在线观看 | 欧美福利电影A在线播放| 亚洲成亚洲成网中文字幕| 人妻中文字幕不卡精品| 精品人妻中文无码av在线| 久久精品国产免费观看频道| 国产一区一一区高清不卡| 久久精品囯产精品亚洲| 日本熟妇乱一区二区三区| 猫咪社区免费资源在线观看| 新竹市| 国产超碰无码最新上传| 一区二区和激情视频| 石河子市| 免费国产午夜理论片不卡| 日韩中文字幕精品人妻| 久久久亚洲欧洲日产国码二区| 狠狠干| 无码AV无码免费一区二区| 天堂亚洲免费视频| 国产精品va在线观看无码不卡| 亚洲性色AV一区二区三区| 中文字幕日韩精品有码| 精品一区二区三区国产馆| 亚洲日本va午夜在线影院| 亚洲男人的天堂久久香蕉| 极品少妇无套内射视频|