性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

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

PIC24 & dsPIC33 MCU Bootloader開發(fā)

“PIC24與dsPIC33都是Microchip 16-bit MCU,閃存程序存儲(chǔ)器架構(gòu)一致,因此將PIC24與dsPIC33系列MCU的Bootloader開發(fā)放到一起來講解。通過本文,您將學(xué)習(xí)16-bit MCU閃存程序存儲(chǔ)器的架構(gòu)與操作,進(jìn)而具備基本的Bootloader開發(fā)能力。” 


1. 示例工程

      為了方便大家學(xué)習(xí),我這里挑選常見的MCU型號(hào)做了些Bootloader參考工程,如PIC24FJ64GU205,dsPIC33CK256MP508和dsPIC33CH512MP508等,大家可以登錄如下Gitee鏈接下載,下載后每個(gè)工程下面有一個(gè)readme.hml,內(nèi)有詳細(xì)的工程建立及驗(yàn)證說明,因此本文中出現(xiàn)的像MCC設(shè)置細(xì)節(jié),大家都可以參考相關(guān)例程的readme.hml,以了解具體操作,本文不會(huì)重復(fù)說明。

      本文基于上述Gitee網(wǎng)頁的PIC24FJ64GU205的示例工程講解,兩個(gè)文件夾分別對(duì)應(yīng)下文不同的“中斷向量“處理方式。

2. 閃存程序存儲(chǔ)器構(gòu)成

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

圖1 - 程序存儲(chǔ)器構(gòu)成

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

圖2 - 程序空間存儲(chǔ)器映射      

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

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

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

圖3 - 中斷向量映射

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

圖4 - 中斷向量表映射

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

圖5 - 中斷向量映射

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

圖6 - 中斷向量映射

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

圖7 - 中斷向量映射代碼實(shí)現(xiàn)

      同樣的在應(yīng)用程序工程中也會(huì)有相應(yīng)的映射表存在,就是前面說的該種方法在開發(fā)之前Bootloader工程和應(yīng)用程序工程都要知道硬件向量的重映射地址,先溝通好。除了與Bootloader工程中hardware_interrupt_table.S和interrupt.S類似的中斷向量表映射部分,應(yīng)用程序工程特殊的還在application_header_not_blank.S中為應(yīng)用程序空間的起始地址處放置了一條goto語句,保證和0x0地址處復(fù)位向量處goto語句一致,這就使得應(yīng)用程序無論是單獨(dú)燒錄,還是與Bootloader工程結(jié)合(通過Bootloader工程跳轉(zhuǎn)到應(yīng)用程序工程起始地址)都可以正常工作。
#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實(shí)現(xiàn),配置如下,具體空間大小可根據(jù)實(shí)際應(yīng)用分配。

圖8 - Bootloader工程Flash空間分配

      該配置下生成的核心代碼在memory_partition.S中,對(duì)于未分配給Bootloader的空間利用noload和keep屬性進(jìn)行保護(hù),保證Bootloader代碼不會(huì)被分配到該空間。
#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 應(yīng)用程序工程

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

圖9 - Application工程Flash空間分配

      該配置下生成的核心代碼仍在memory_partition.S中,將Bootloader程序空間和包含配置字的flash空間最后一個(gè)頁(除了配置字部分)進(jìn)行保留。Bootloader程序保留空間不包括復(fù)位向量和硬件中斷向量表,因?yàn)閼?yīng)用程序工程為了可以單獨(dú)工作這部分同樣需要中斷向量重映射。而flash最后一個(gè)頁空間保留是因?yàn)槿襞渲米謱懕Wo(hù)使能,則flash最后一個(gè)頁不能擦除,所以一般最后一個(gè)頁不分配代碼,防止配置字寫保護(hù)。注意:Bootloader和應(yīng)用程序工程的配置字必須嚴(yán)格一致。
#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使能

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

      1)BootSegment (BS) 引導(dǎo)段

      2)GeneralSegment (GS) 通用段

      3)ConfigurationSegment (CS) 配置段。

圖10 - CodeGuard使能 (PIC24FJ64GU205)

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

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

3.2.1 輔助中斷向量表使能

      圖11所示,開啟了輔助中斷向量表后,Bootloader和應(yīng)用程序工程的有自己的中斷向量表,那么此時(shí)可以實(shí)現(xiàn)Bootloader和應(yīng)用程序工程開啟同一個(gè)中斷。當(dāng)然同一時(shí)刻僅Bootloader或應(yīng)用程序工程之一使用。

圖11 - 中斷向量映射      

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

圖11 - 中斷向量映射

      而T2Interrupt分配給應(yīng)用程序工程(硬件中斷向量地址0x1822),這里使用了輔助中斷向量表,之后在應(yīng)用程序工程的程序空間可以看到0x1822處存放的為應(yīng)用程序中斷函數(shù)__T2Interrupt的地址0x00232c。Booloader工程MCC會(huì)自動(dòng)生成使能輔助中斷向量表的相應(yīng)代碼,system.c中配置字設(shè)置如下:
// 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中使能輔助中斷向量表函數(shù)如下:

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生成的工程會(huì)報(bào)若干錯(cuò)誤,需要手動(dòng)解決。部分錯(cuò)誤提示需對(duì)Bootloader和應(yīng)用程序工程屬性的xc16-ld下“Addtional options”加上相應(yīng)鏈接屬性,按編譯錯(cuò)誤提示操作即可解決。那么借助這些屬性定義鏈接文件會(huì)自動(dòng)將Bootloader工程分配到引導(dǎo)段,應(yīng)用程序工程分配到通用段。而引導(dǎo)段的大小則為前述的相關(guān)配置字指定。

圖12 - Flash空間分配

4. 閃存編程

      Bootloader開發(fā)目的為閃存運(yùn)行時(shí)自編程,主要靠如下寄存器進(jìn)行控制。NVMCON和NVMKEY寄存器用于使能和選擇所有操作。其余4個(gè)寄存器NVMADRL、NVMADRH、NVMSRCADRL和NVMSRCADRH用于定義數(shù)據(jù)和地址指針,另有TBLPAG用于表讀表寫操作。所有的閃存編程API函數(shù)可以通過MCC生成,這里對(duì)生成代碼flash.s簡(jiǎn)單解讀方便大家更好理解編程操作。首先看一下解鎖函數(shù)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”實(shí)現(xiàn)。因?yàn)開FlashKey已經(jīng)存儲(chǔ)著前述FLASH_Unlock過程的key,所以此處用這個(gè)key去解。而key的值0x00AA0055是通過通信協(xié)議傳遞過來的。并且解鎖后會(huì)伴隨著NVMCON的WR位置1啟動(dòng)相應(yīng)的閃存操作。

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,這樣即使調(diào)用_FLASH_SendNvmKey也不能實(shí)現(xiàn)解鎖。

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內(nèi)容,一次讀出1個(gè)指令字。首先保存TBLPAG的當(dāng)前值導(dǎo)W2,用于函數(shù)執(zhí)行完恢復(fù)。W0和W1構(gòu)成24位地址address,address高8位地址就是W1的低8位,所以將W1賦值給TBLPAG。而address低16位地址在W0中,因?yàn)門BLPAG已經(jīng)有值,所以從低16位地址調(diào)用表讀高位字和表讀低位字指令,將結(jié)果讀到W1和W0中,返回32位數(shù),即一個(gè)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內(nèi)容,一次寫入2個(gè)指令字。首先進(jìn)來判斷下NVMCON的WR位清零了沒有,沒有是1則繼續(xù)等待WR變?yōu)?。寫的起始地址由w1和w0構(gòu)成,因雙字編程操作需要兩個(gè)在4字邊界處對(duì)齊的相鄰指令字(各24位),所以要判斷W0的bit0和bit1是否為1,為1則跳到后面的標(biāo)號(hào)3異常處理,如果起始地址正確則繼續(xù)往下運(yùn)行。接著將起始地址賦給目標(biāo)地址寄存器NVMADRU和NVMADR。緊接著賦值NVMCON為WRITE_DWORD_CODE,這里代表NVMCON的WREN使能,允許寫,NVMOP值為1,即雙字編程。接下來就是當(dāng)前表寄存器存儲(chǔ),為了后續(xù)恢復(fù)。最后表寫要通過表寫保持鎖存器實(shí)現(xiàn),因?yàn)楸韺懼噶畈粫?huì)直接寫入閃存程序陣列,而是要將編程的數(shù)據(jù)先裝入保持鎖存器。而保持鎖存器的起始地址為FA0000h。所以TBLPAG寄存器要賦值為立即數(shù)#0xFA,緊接著表寫2條指令字到保持鎖存器。W2、W3和W4、W5就是要寫入的2個(gè)32位數(shù)。緊接著調(diào)用_FLASH_SendNvmKey,完成解鎖和WR置位開始2個(gè)指令字寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發(fā)生了錯(cuò)誤的編程/擦除終止,需返回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。同樣首先進(jìn)來判斷下NVMCON的WR位清零了沒有,沒有是1則繼續(xù)等待WR變?yōu)?。緊接著是地址有效判斷,行編程要128指令字地址對(duì)齊,所以地址W0低7位必須是0,不是0則需跳到后面的標(biāo)號(hào)3異常處理。將起始地址賦給目標(biāo)地址寄存器NVMADR,高位地址NCMADRU不涉及。緊接著賦值NVMCON為WRITE_ROW_CODE,這里NVMCON的WREN使能,允許寫,NVMOP值為2,代表行編程。接著將RAM數(shù)據(jù)緩沖區(qū)data的地址w2賦值給NVMSRCADRL,因?yàn)椴]有用到擴(kuò)展數(shù)據(jù)空間EDS,所以NVMSRCADRH不用賦值。緊接著調(diào)用_FLASH_SendNvmKey,完成解鎖和WR置位開始行寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發(fā)生了錯(cuò)誤的編程/擦除終止,需返回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行構(gòu)成一個(gè)存儲(chǔ)器頁,每個(gè)行128條指令,這樣一個(gè)頁共1024條指令,所以頁擦除要判斷1024指令字地址對(duì)齊,所以地址W0低10位必須是0,不是0則需跳到后面的標(biāo)號(hào)3異常處理。接著賦值NVMCON為ERASE_PAGE_CODE,這里NVMCON的WREN使能,允許寫,NVMOP值為3,代表頁擦除。然后將起始地址賦給目標(biāo)地址寄存器NVMADRU和NVMADR。緊接著調(diào)用_FLASH_SendNvmKey,完成解鎖和WR置位開始行寫操作。寫操作完成后如果NVMCON的WRERR置位,代表發(fā)生了錯(cuò)誤的編程/擦除終止,需返回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. 通信協(xié)議

      串口通信協(xié)議可以詳見16-bit Bootloader的幫助文檔,可以在MCC下點(diǎn)擊?號(hào)獲得,在大家開發(fā)過程中可以參考。

圖13 - 通信協(xié)議

      其基本協(xié)議格式如下:

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

      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
聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 6
收藏 4
關(guān)注 42
成為作者 賺取收益
全部留言
0/200
成為第一個(gè)和作者交流的人吧