99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

王超的小站
認證:VIP會員
所在專題目錄 查看專題
Python開發環境搭建(for Bootloader)
PIC16 & PIC18 MCU Bootloader開發
PIC24 & dsPIC33 MCU Bootloader開發
作者動態 更多
PIC24 & dsPIC33 MCU Bootloader開發
2021-11-08 15:12
PIC16 & PIC18 MCU Bootloader開發
2021-11-08 15:00
Python開發環境搭建(for Bootloader)
2021-11-08 14:58
Python開發環境搭建 (for Control)
2021-01-27 18:43
MCU擴展CAN/CAN FD接口方案-MCU軟件動手實驗
2020-11-25 14:11

PIC24 & dsPIC33 MCU Bootloader開發

“PIC24與dsPIC33都是Microchip 16-bit MCU,閃存程序存儲器架構一致,因此將PIC24與dsPIC33系列MCU的Bootloader開發放到一起來講解。通過本文,您將學習16-bit MCU閃存程序存儲器的架構與操作,進而具備基本的Bootloader開發能力。” 


1. 示例工程

      為了方便大家學習,我這里挑選常見的MCU型號做了些Bootloader參考工程,如PIC24FJ64GU205,dsPIC33CK256MP508和dsPIC33CH512MP508等,大家可以登錄如下Gitee鏈接下載,下載后每個工程下面有一個readme.hml,內有詳細的工程建立及驗證說明,因此本文中出現的像MCC設置細節,大家都可以參考相關例程的readme.hml,以了解具體操作,本文不會重復說明。

      本文基于上述Gitee網頁的PIC24FJ64GU205的示例工程講解,兩個文件夾分別對應下文不同的“中斷向量“處理方式。

2. 閃存程序存儲器構成

      如圖1所示,程序存儲器空間由可字尋址的區塊構成,指令字寬度為24位,用戶可用23位程序計數器(PC),可尋址4M×24位的程序存儲器地址空間。程序存儲器空間雖然被視為24位寬(16-bit MCU指令字寬度),但將程序存儲器的每個地址視作一個低位字和一個高位字的組合更加合理,其中高位字的高字節部分未實現。低位字的地址始終為偶數,而高位字的地址為奇數。所以在代碼執行過程中,PC地址按2遞增,即PC<0>固定為0。

圖1 - 程序存儲器構成

      接下來看下程序空間存儲器映射示意,圖2左側為PIC24和dsPIC33 MCU的默認程序存儲空間映射,起始地址0x000000處為復位向量,會存儲一條goto語句。地址0x000004開始為中斷向量表(IVT),對于PIC24 MCU向量表延伸至0x0000FE;對于dsPIC33 MCU向量表延伸至0x0001FE。接下來是用戶程序存儲空間和閃存配置字;在往后是0x800000至0xFFFFFF測試存儲空間,這部分用戶不可用。

圖2 - 程序空間存儲器映射      

      圖2右側為加入Bootloader功能后用戶程序空間需要分為2塊,1塊為Booloader代碼,另一塊為應用程序代碼。同時需要注意最后一個包含配置字的頁進行保留,僅供配置字使用。因為程序存儲器按頁擦除,為了修改配置字可能需要讀取最后一個頁的程序存儲器數據,將其存入RAM,然后修改指定配置字內容,在將這一頁按行逐步回寫,但擦除回寫過程異常掉電可能導致配置字未正確寫入使MCU變磚塊,因此雖有空間浪費但仍建議將最后一頁保留給配置字使用,并且保證bootloader和應用程序配置字一致,這樣燒錄應用程序過程中也不需要更改配置字,只燒寫其它程序內容即可。

      注:存儲器頁的大小不同器件可能不同,這里PIC24FJ64JU205和dsPIC33CK系列MCU 8行構成一個存儲器的頁,每個行128條指令,所以一個頁共1024條指令,換算為字的話一個存儲器頁含有0x800個字。

3. Bootloader與應用程序的中斷向量關聯
      對于本文的Bootloader開發方法,將復位向量,中斷向量表和Bootloader應用程序代碼三部分作為整個Bootloader工程,也就是bootloader工程放在了程序存儲器空間地址0x000000起始處。如此處理便要面臨一個問題,中斷向量表在bootloader工程中,并且可能提前編譯燒錄到MCU中,那么發生特定中斷后,bootloader中的硬件中斷向量表如何才能正確跳轉到后續燒錄的應用程序中斷代碼?這里有2種方法,一種是非CodeGuardTM的MCU采用中斷重映射的通用方法;另一種是帶CodeGuardTM的MCU,因其有輔助中斷向量表(AVIT),可將IVT分配給Bootloader,而AVIT分配給應用程序工程。當然帶有CodeGuardTM的MCU也可以采用中斷重映射的通用方法。接下來我們分別講解這兩種方法Bootloader開發的關鍵思路。

圖3 - 中斷向量映射

3.1 通用方法 - 中斷向量表重映射
      如圖4所示,中斷向量映射便是事先Bootloader工程和應用程序工程溝通好,明確應用程序工程中各個中斷向量重映射的地址,這樣當硬件中斷向量來了之后,會自動跳轉到應用程序的重映射中斷向量入口,接著借由重映射中斷向量處存放的goto語句進一步跳轉到最終的用戶中斷向量程序代碼。通過圖4也可以進一步理解,一個中斷向量分配給Bootloader工程還是分配給應用工程要提前規劃好,中斷向量不能共用。

圖4 - 中斷向量表映射

3.1.1 中斷向量表重映射
      為了更好的理解我們可以看下Gitee中PIC24FJ64GU205工程中斷向量重映射的情況,在MCC配置界面不勾選"Code Protect Bootloader"即是該種映射方法,這里將T1Interrupt分配給Bootloader工程(硬件中斷向量地址0x001A),之后在Bootloader工程的程序空間可以看到0x001A處存放的為Bootloader工程中斷函數__T1Interrupt的地址0x000208。

圖5 - 中斷向量映射

      將T2Interrupt及所有其它的中斷分配給應用程序工程(T2Interrupt硬件中斷向量地址0x0022),之后在Bootloader工程的程序空間可以看到0x0022處存放的為0x1A2C地址,在應用程序工程的程序空間中可以看到0x1A2C處存放的為重映射goto語句,進一步goto到0x1CBA的地址,而該地址即是應用程序中斷函數__T2Interrupt的地址。

圖6 - 中斷向量映射

      下圖為Booloader工程實現上述中斷重映射功能MCC生成的代碼,主要基于偽指令實現。

圖7 - 中斷向量映射代碼實現

      同樣的在應用程序工程中也會有相應的映射表存在,就是前面說的該種方法在開發之前Bootloader工程和應用程序工程都要知道硬件向量的重映射地址,先溝通好。除了與Bootloader工程中hardware_interrupt_table.S和interrupt.S類似的中斷向量表映射部分,應用程序工程特殊的還在application_header_not_blank.S中為應用程序空間的起始地址處放置了一條goto語句,保證和0x0地址處復位向量處goto語句一致,這就使得應用程序無論是單獨燒錄,還是與Bootloader工程結合(通過Bootloader工程跳轉到應用程序工程起始地址)都可以正常工作。
#include "boot_config.h"

    .section .application_header_not_blank, code, address(BOOT_CONFIG_APPLICATION_IMAGE_APPLICATION_HEADER_ADDRESS), keep

    /* Firmware Image Reset Remap */
    goto __resetPRI

3.1.2 Flash空間分配

3.1.2.1 Bootloader工程

      Bootloader工程的Flash空間分配通過MCC實現,配置如下,具體空間大小可根據實際應用分配。

圖8 - Bootloader工程Flash空間分配

      該配置下生成的核心代碼在memory_partition.S中,對于未分配給Bootloader的空間利用noload和keep屬性進行保護,保證Bootloader代碼不會被分配到該空間。
#include "boot_config.h"

    .section *, code, address(BOOT_CONFIG_PROGRAMMABLE_ADDRESS_LOW), noload, keep
reserved_application_memory:
    .space 0xAEFE  -  BOOT_CONFIG_PROGRAMMABLE_ADDRESS_LOW, 0x00
3.1.2.2 應用程序工程

      相應的應用程序工程的Flash空間分配在MCC界面顯示如下。

圖9 - Application工程Flash空間分配

      該配置下生成的核心代碼仍在memory_partition.S中,將Bootloader程序空間和包含配置字的flash空間最后一個頁(除了配置字部分)進行保留。Bootloader程序保留空間不包括復位向量和硬件中斷向量表,因為應用程序工程為了可以單獨工作這部分同樣需要中斷向量重映射。而flash最后一個頁空間保留是因為若配置字寫保護使能,則flash最后一個頁不能擦除,所以一般最后一個頁不分配代碼,防止配置字寫保護。注意:Bootloader和應用程序工程的配置字必須嚴格一致。
#include "boot_config.h"
    .equ    ERASE_PAGE_MASK,(~((2048) - 1)) 
    .equ    LAST_PAGE_START_ADDRESS, (0xAEFE & ERASE_PAGE_MASK)
    .equ    RESERVED_MEMORY_START, (0xA7FE+2)
    .equ    PROGRAM_MEMORY_ORIGIN, (0x100)
    .equ    LAST_ADDRESS_OF_MEMORY, (0xAEFE)

 .section *, code, address(PROGRAM_MEMORY_ORIGIN), noload, keep
boot_loader_memory:
    .space (BOOT_CONFIG_PROGRAMMABLE_ADDRESS_LOW  - PROGRAM_MEMORY_ORIGIN), 0x00

 .section *, code, address(RESERVED_MEMORY_START), noload, keep
config_page_memory:
    .space (LAST_ADDRESS_OF_MEMORY-RESERVED_MEMORY_START), 0x00

3.2 特殊方法 - 輔助中斷向量表AIVT使能

      對于具有CodeGuard安全性的芯片,可以將0x000000到0x0XXX00的用戶程序空間分為三部分:

      1)BootSegment (BS) 引導段

      2)GeneralSegment (GS) 通用段

      3)ConfigurationSegment (CS) 配置段。

圖10 - CodeGuard使能 (PIC24FJ64GU205)

      可以通過配置寄存器FSEC的AIVTDIS位使能CodeGuardTM MCU的AVIT。同時將BSEN引導段控制位使能,這樣就可以通過配置寄存器FBSLIM來決定引導段的大小。那么AVIT的偏移量基址BOA,位于引導段最后一頁的起始地址。那么既然使能了這幾個段,肯定是希望代碼保護的,代碼保護可以通過配置寄存器FSEC的BWRP引導段寫保護位和CWRP配置段寫保護位設置。但引導段的寫保護有點特殊,他只是將圖中IVT和BS這部分進行寫保護,而對于AIVT+512 IW(IW是指令字)沒有寫保護。這也合理,因為AIVT是用戶應用程序來使用的,所以AIVT+512個指令字和GS段都沒有被寫保護,使得這些內容可以被自編程進行升級操作。

      圖10中BSLIM為實際分配給引導段頁數的補碼形式,這里示意0x1FFA是0x0005的補碼,代表有5個頁用于引導段。前4個頁用于實際的Bootloader代碼空間,并進行寫保護,而最后一個頁用于應用程序工程的AIVT,可以被Bootloader升級改寫。而最后配置字所在的這一頁(共0x800個字),當配置字(CWRP配置段寫保護位)寫保護后,會一起保護起來,因此最后一個頁同樣在配置字寫保護下同樣不可以分配給應用程序。

3.2.1 輔助中斷向量表使能

      圖11所示,開啟了輔助中斷向量表后,Bootloader和應用程序工程的有自己的中斷向量表,那么此時可以實現Bootloader和應用程序工程開啟同一個中斷。當然同一時刻僅Bootloader或應用程序工程之一使用。

圖11 - 中斷向量映射      

      這里我們可以看下Gitee中PIC24FJ64GU205工程中斷向量使用情況,在MCC配置界面勾選"Code Protect Bootloader"即是該種中斷方法,這里將T1Interrupt分配給Bootloader工程(硬件中斷向量地址0x001A),之后在Bootloader工程的程序空間可以看到0x001A處存放的為Bootloader工程中中斷函數__T1Interrupt的地址0x000B8E。

圖11 - 中斷向量映射

      而T2Interrupt分配給應用程序工程(硬件中斷向量地址0x1822),這里使用了輔助中斷向量表,之后在應用程序工程的程序空間可以看到0x1822處存放的為應用程序中斷函數__T2Interrupt的地址0x00232c。Booloader工程MCC會自動生成使能輔助中斷向量表的相應代碼,system.c中配置字設置如下:
// FSEC
#pragma config BWRP = ON    //Boot Segment Write-Protect bit->Boot Segment is write protected
#pragma config BSS = DISABLED    //Boot Segment Code-Protect Level bits->No Protection (other than BWRP)
#pragma config BSEN = ON    //Boot Segment Control bit->Boot Segment size determined by FBSLIM
#pragma config GWRP = OFF    //General Segment Write-Protect bit->General Segment may be written
#pragma config GSS = DISABLED    //General Segment Code-Protect Level bits->No Protection (other than GWRP)
#pragma config CWRP = ON    //Configuration Segment Write-Protect bit->Configuration Segment is write protected
#pragma config CSS = DISABLED    //Configuration Segment Code-Protect Level bits->No Protection (other than CWRP)
#pragma config AIVTDIS = ON    //Alternate Interrupt Vector Table bit->Enabled AIVT

// FBSLIM
#pragma config BSLIM = 8187    //Boot Segment Flash Page Address Limit bits->8187

      boot_demo.c中使能輔助中斷向量表函數如下:

static void AIVTEnable(bool enable)
{
#if defined(_ALTIVT)
    _ALTIVT = enable;
#elif defined(_AIVTEN)
    _AIVTEN = enable;
#else
    #error "Unknown/unsupported device type.  Implement support for switching to alternate interrupt table mode."
#endif
}

      編譯MCC生成的工程會報若干錯誤,需要手動解決。部分錯誤提示需對Bootloader和應用程序工程屬性的xc16-ld下“Addtional options”加上相應鏈接屬性,按編譯錯誤提示操作即可解決。那么借助這些屬性定義鏈接文件會自動將Bootloader工程分配到引導段,應用程序工程分配到通用段。而引導段的大小則為前述的相關配置字指定。

圖12 - Flash空間分配

4. 閃存編程

      Bootloader開發目的為閃存運行時自編程,主要靠如下寄存器進行控制。NVMCON和NVMKEY寄存器用于使能和選擇所有操作。其余4個寄存器NVMADRL、NVMADRH、NVMSRCADRL和NVMSRCADRH用于定義數據和地址指針,另有TBLPAG用于表讀表寫操作。所有的閃存編程API函數可以通過MCC生成,這里對生成代碼flash.s簡單解讀方便大家更好理解編程操作。首先看一下解鎖函數FLASH_Unlock。這里解鎖并不是真正的解鎖,只是將解鎖的key值保存在_FlashKey指定的地址。
void     FLASH_Unlock(uint32_t  key);
 .global         _FLASH_Unlock
    .type           _FLASH_Unlock, @function
    reset
 _FLASH_Unlock:
    mov     #_FlashKey, W2
    mov     W0, [W2++]
    mov     W1, [W2]
    return;

      真正的解鎖過程在具體flash要操作前通過_FLASH_SendNvmKey部分的“wtite the key sequence”實現。因為_FlashKey已經存儲著前述FLASH_Unlock過程的key,所以此處用這個key去解。而key的值0x00AA0055是通過通信協議傳遞過來的。并且解鎖后會伴隨著NVMCON的WR位置1啟動相應的閃存操作。

reset       
    .global         _FLASH_SendNvmKey
    .type           _FLASH_SendNvmKey, @function
    .extern         NVMKEY
    .extern         TBLPAG

    reset  
_FLASH_SendNvmKey:
    push    W0
    push    W1
    push    W2

    mov    #_FlashKey, w1

    ; Disable interrupts
    mov    INTCON2, W2      ; Save Global Interrupt Enable bit.
    bclr   INTCON2, #15      ; Disable interrupts

    ; Write the KEY sequence
    mov    [W1++], W0
    mov    W0,     NVMKEY
    mov    [W1],   W0
    mov    W0,     NVMKEY
    bset   NVMCON, #15

    ; Insert two NOPs after programming
    nop
    nop

    ; Wait for operation to complete
prog_wait:
    btsc NVMCON, #15
    bra prog_wait

   ; Re-enable interrupts,
    btsc    W2,#15
    BSET    INTCON2, #15    ; Restore Global Interrupt Enable bit.

    pop    W2
    pop    W1
    pop    W0
    return

      而上鎖FLASH_Unlock就是給_FlashKey寫0,這樣即使調用_FLASH_SendNvmKey也不能實現解鎖。

void     FLASH_Unlock(uint32_t  key);
 .global         _FLASH_Lock
    .type           _FLASH_Lock, @function
    .extern         NVMKEY

    reset
 _FLASH_Lock:
    clr W0
    clr W1
    rcall _FLASH_Unlock
    clr NVMKEY    
    return;

      表讀FLASH_ReadWord24用于讀取Flash內容,一次讀出1個指令字。首先保存TBLPAG的當前值導W2,用于函數執行完恢復。W0和W1構成24位地址address,address高8位地址就是W1的低8位,所以將W1賦值給TBLPAG。而address低16位地址在W0中,因為TBLPAG已經有值,所以從低16位地址調用表讀高位字和表讀低位字指令,將結果讀到W1和W0中,返回32位數,即一個24位指令。
uint32_t FLASH_ReadWord24(uint32_t address);
 reset    
    .global         _FLASH_ReadWord24
    .type           _FLASH_ReadWord24, @function
    .extern         TBLPAG


   _FLASH_ReadWord24:
    mov         TBLPAG, W2
    mov         W1, TBLPAG    ; Little endian, w1 has MSW, w0 has LSX
    tblrdh      [W0], W1      ; read MSW of data to high latch
    tblrdl      [W0], W0      ; read LSW of data 
    mov         W2, TBLPAG    ; Restore register, 
    return

      表寫FLASH_WriteDoubleWord24用于寫Flash內容,一次寫入2個指令字。首先進來判斷下NVMCON的WR位清零了沒有,沒有是1則繼續等待WR變為0。寫的起始地址由w1和w0構成,因雙字編程操作需要兩個在4字邊界處對齊的相鄰指令字(各24位),所以要判斷W0的bit0和bit1是否為1,為1則跳到后面的標號3異常處理,如果起始地址正確則繼續往下運行。接著將起始地址賦給目標地址寄存器NVMADRU和NVMADR。緊接著賦值NVMCON為WRITE_DWORD_CODE,這里代表NVMCON的WREN使能,允許寫,NVMOP值為1,即雙字編程。接下來就是當前表寄存器存儲,為了后續恢復。最后表寫要通過表寫保持鎖存器實現,因為表寫指令不會直接寫入閃存程序陣列,而是要將編程的數據先裝入保持鎖存器。而保持鎖存器的起始地址為FA0000h。所以TBLPAG寄存器要賦值為立即數#0xFA,緊接著表寫2條指令字到保持鎖存器。W2、W3和W4、W5就是要寫入的2個32位數。緊接著調用_FLASH_SendNvmKey,完成解鎖和WR置位開始2個指令字寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發生了錯誤的編程/擦除終止,需返回W0的值為1,否則返回0。

bool     FLASH_WriteDoubleWord24(uint32_t address, uint32_t Data0, uint32_t Data1);
 .global         _FLASH_WriteDoubleWord24
    .type           _FLASH_WriteDoubleWord24, @function
    .extern         TBLPAG
    .extern         NVMCON
    .extern         NVMADRU
    .extern         NVMADR
    reset    

_FLASH_WriteDoubleWord24:
    btsc    NVMCON, #15     ; Loop, blocking until last NVM operation is complete (WR is clear)
    bra     _FLASH_WriteDoubleWord24

    btsc    w0, #0          ; Check for a valid address Bit 0 and Bit 1 clear
    bra     3f
    btsc    w0, #1
    bra     3f
good24:
    mov     W1,NVMADRU
    mov     W0,NVMADR       

    mov     #WRITE_DWORD_CODE, W0 
    mov     W0, NVMCON

    mov     TBLPAG, W0          ; save it
    mov     #0xFA,W1
    mov     W1,TBLPAG
    mov     #0,W1

                                ; Perform the TBLWT instructions to write the latches
    tblwtl  W2,[W1]
    tblwth  W3,[W1++]
    tblwtl  W4,[W1]
    tblwth  w5,[W1++]

    call    _FLASH_SendNvmKey

    mov     W0, TBLPAG

    mov     #1, w0               ; default return true
    btsc    NVMCON, #13          ; if error bit set, 
3:  mov     #0, w0               ;   return false

    return;

      FLASH_WriteRow24行寫操作,基于RAM。同樣首先進來判斷下NVMCON的WR位清零了沒有,沒有是1則繼續等待WR變為0。緊接著是地址有效判斷,行編程要128指令字地址對齊,所以地址W0低7位必須是0,不是0則需跳到后面的標號3異常處理。將起始地址賦給目標地址寄存器NVMADR,高位地址NCMADRU不涉及。緊接著賦值NVMCON為WRITE_ROW_CODE,這里NVMCON的WREN使能,允許寫,NVMOP值為2,代表行編程。接著將RAM數據緩沖區data的地址w2賦值給NVMSRCADRL,因為并沒有用到擴展數據空間EDS,所以NVMSRCADRH不用賦值。緊接著調用_FLASH_SendNvmKey,完成解鎖和WR置位開始行寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發生了錯誤的編程/擦除終止,需返回W0的值為1,否則返回0。

bool     FLASH_WriteRow24(uint32_t flashAddress, uint32_t *data);
 .global         _FLASH_WriteRow24
    .type           _FLASH_WriteRow24, @function
    .extern         TBLPAG
    .extern         NVMCON
    .extern         NVMADRU
    .extern         NVMADR
    .extern         NVMSRCADRL 
    reset

 _FLASH_WriteRow24:
    btsc    NVMCON, #15         ; Loop, blocking until last NVM operation is complete (WR is clear)
    bra     _FLASH_WriteRow24

    mov     #((FLASH_WRITE_ROW_SIZE_IN_INSTRUCTIONS*2)-1), w3     ;    get mask and validate all lower bits = 0
    and     w3, w0, w3
    bra     NZ,3f 

    mov     W0,NVMADR       
    mov     W1,NVMADRU

    mov     #FLASH_WRITE_ROW_CODE, W0 ; RPDF = 0 so not compressed
    mov     W0, NVMCON

    mov     W2, NVMSRCADRL

    call    _FLASH_SendNvmKey  


    mov     #1, w0               ; default return true
    btsc    NVMCON, #13          ; if error bit set, 
3:  mov     #0, w0               ;   return false
    return;

      頁擦除操作FLASH_ErasePage,PIC24FJ64GU205和dsPIC33CK 8行構成一個存儲器頁,每個行128條指令,這樣一個頁共1024條指令,所以頁擦除要判斷1024指令字地址對齊,所以地址W0低10位必須是0,不是0則需跳到后面的標號3異常處理。接著賦值NVMCON為ERASE_PAGE_CODE,這里NVMCON的WREN使能,允許寫,NVMOP值為3,代表頁擦除。然后將起始地址賦給目標地址寄存器NVMADRU和NVMADR。緊接著調用_FLASH_SendNvmKey,完成解鎖和WR置位開始行寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發生了錯誤的編程/擦除終止,需返回W0的值為1,否則返回0。

bool     FLASH_ErasePage(uint32_t address); 
 .global         _FLASH_ErasePage
    .type           _FLASH_ErasePage, @function
    .extern         TBLPAG
    .extern         NVMCON
    .extern         NVMADRU 
    .extern         NVMADR
   reset

_FLASH_ErasePage:

    mov     #FLASH_ERASE_PAGE_SIZE_IN_PC_UNITS-1, w2     ;    get mask and validate all lower bits = 0
    and     w2, w0, w2
    bra     NZ,3f 

    mov     #ERASE_PAGE_CODE, w2
    mov     w2, NVMCON
    mov     w0, NVMADR
    mov     w1, NVMADRU        ; MSB

    call    _FLASH_SendNvmKey

    mov     #1, w0                 ; default return true
    btsc    NVMCON, #13            ; if error bit set, 
3:  mov     #0, w0                 ;   return false
    return;
5. 通信協議

      串口通信協議可以詳見16-bit Bootloader的幫助文檔,可以在MCC下點擊?號獲得,在大家開發過程中可以參考。

圖13 - 通信協議

      其基本協議格式如下:

      下面是部分基礎命令格式示例,供大家參考。

      1) 0 - Get Version & More

      2) 3 - Erase Flash Memory

      3) 2 - Write Flash Memory

      4) A - Self Verify Program Memory

      5) 9 - Reset Device

6.參考文檔
1)器件Datasheet
聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 6
收藏 5
關注 43
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 亚洲午夜精品A品久久 | 免费看国产一级特黄aaaa大片 | 日韩天堂在线观看 | 日韩视频中文字幕视频一区 | 丝袜美女被出水一区 | 色婷婷av一区二区三区软件 | 日韩在线视屏 | 正在做饭的少妇中文字幕 | 欧美人与禽猛交乱配视频 | 国产九色在线观看 | 中文字幕中文字幕在线中文字幕三区 | 日本国产黄色 | 国产欧美日韩另类色视频云霸 | 亚洲91av | 国产成人久久婷婷精品流白浆 | 91青青| 亚色视频在线观看 | 少妇情欲一区二区影视 | 久久这里只有精品18 | 狠狠爱ADY亚洲色 | 免费黄色成年网站 | 视频网站高清免费在线观看 | 久久久精品观看 | 亚洲国产一级毛片 | 91亚洲精品第一 | 亚洲精品成人福利网站 | 国产亚洲亚洲国产一二区 | 国产成人欧美一区二区三区一色天 | 成人午夜视频精品一区 | 欧美日韩成人在线视频 | 日韩中文不卡 | 色se02短视频永久网站 | haoleav.com在线| 久久久精品国产一区 | 永久免费A∨片在线观看 | 日韩欧美精品一区二区三区经典 | 一区二区三区视频免费视频观看网站 | 1024看片金沙日韩一区二区 | 国产熟女一区二区三区四区五区 | 国产成人精品久久二区二区 | 久久精品国产亚洲A∨麻豆 日本在线看片免费人成视频 |