Jump to content

    

Проблема с Unified Bootloader Host Application-ом

Сгенерировал с помощью МСС код загрузчика. При попытке залить приложение с помощью Unified Bootloader Host Application, получаю сообщение, которая на скриншоте.

 

PIC6F18456

Как перебороть?

bootloader3.png

//******************************************************************************
//        Software License Agreement
//
// ©2016 Microchip Technology Inc. and its subsidiaries. You may use this
// software and any derivatives exclusively with Microchip products.
//
// THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
// EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
// WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR
// PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION WITH ANY
// OTHER PRODUCTS, OR USE IN ANY APPLICATION.
//
// IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
// INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
// WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
// BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
// FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
// ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
// THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
//
// MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.
//******************************************************************************
//
//
//
// Memory Map
//   -----------------
//   |    0x0000     |   Reset vector
//   |               |
//   |    0x0004     |   Interrupt vector
//   |               |
//   |               |
//   |  Boot Block   |   (this program)
//   |               |
//   |    0x0300     |   Re-mapped Reset Vector
//   |    0x0304     |   Re-mapped High Priority Interrupt Vector
//   |               |
//   |       |       |
//   |               |
//   |  Code Space   |   User program space
//   |               |
//   |       |       |
//   |               |
//   |    0x3FFF     |
//   -----------------
//
//
//
// Definitions:
//
//   STX     -   Start of packet indicator
//   DATA    -   General data up to 255 bytes
//   COMMAND -   Base command
//   DLEN    -   Length of data associated to the command
//   ADDR    -   Address up to 24 bits
//   DATA    -   Data (if any)
//
//
// Commands:
//
//   RD_VER      0x00    Read Version Information
//   RD_MEM      0x01    Read Program Memory
//   WR_MEM      0x02    Write Program Memory
//   ER_MEM      0x03    Erase Program Memory (NOT supported by PIC16)
//   RD_EE       0x04    Read EEDATA Memory
//   WR_EE       0x05    Write EEDATA Memory
//   RD_CONFIG   0x06    Read Config Memory (NOT supported by PIC16)
//   WT_CONFIG   0x07    Write Config Memory (NOT supported by PIC16)
//   CHECKSUM    0x08    Calculate 16 bit checksum of specified region of memory
//   RESET       0x09    Reset Device and run application
//
// *****************************************************************************

#define  READ_VERSION   0
#define  READ_FLASH     1
#define  WRITE_FLASH    2
#define  ERASE_FLASH    3
#define  READ_EE_DATA   4
#define  WRITE_EE_DATA  5
#define  READ_CONFIG    6
#define  WRITE_CONFIG   7
#define  CALC_CHECKSUM  8
#define  RESET_DEVICE   9
#define  CALC_CRC       10



// *****************************************************************************
    #include "xc.h"       // Standard include
    #include <stdint.h>
    #include <stdbool.h>
    #include "bootload.h"
    #include "mcc.h"


// *****************************************************************************
void     Get_Buffer (void);     // generic comms layer
uint8_t  Get_Version_Data(void);
uint8_t  Read_Flash(void);
uint8_t  Write_Flash(void);
uint8_t  Erase_Flash(void);
uint8_t  Read_EE_Data(void);
uint8_t  Write_EE_Data(void);
uint8_t  Read_Config(void);
uint8_t  Write_Config(void);
uint8_t  Calc_Checksum(void);
void     StartWrite(void);
void     BOOTLOADER_Initialize(void);
void     Run_Bootloader(void);
bool     Bootload_Required (void);

// *****************************************************************************
#define	MINOR_VERSION   0x07       // Version
#define	MAJOR_VERSION   0x00
//#define STX             			 0x55       // Actually code 0x55 is 'U'  But this is what the autobaud feature of the PIC16F1 EUSART is looking for
#define ERROR_ADDRESS_OUT_OF_RANGE   0xFE
#define ERROR_INVALID_COMMAND        0xFF
#define COMMAND_SUCCESS              0x01

// To be device independent, these are set by mcc in memory.h
#define  LAST_WORD_MASK          (WRITE_FLASH_BLOCKSIZE - 1)
#define  NEW_RESET_VECTOR        0x500
#define  NEW_INTERRUPT_VECTOR    0x504

#define _str(x)  #x
#define str(x)  _str(x)

// *****************************************************************************


// *****************************************************************************
    uint16_t check_sum;    // Checksum accumulator
    uint16_t counter;      // General counter
    uint8_t data_length;
    uint8_t rx_data;
    uint8_t tx_data;
    bool reset_pending = false;

// Force variables into Unbanked for 1-cycle accessibility 
    uint8_t EE_Key_1    __at(0x70);
    uint8_t EE_Key_2    __at(0x71);


frame_t  frame;

// *****************************************************************************
// The bootloader code does not use any interrupts.
// However, the application code may use interrupts.
// The interrupt vector on a PIC16F is located at
// address 0x0004. 
// The following function will be located
// at the interrupt vector and will contain a jump to
// the new application interrupt vector

    asm ("psect  intentry,global,class=CODE,delta=2");
    asm ("pagesel " str(NEW_INTERRUPT_VECTOR));
    asm ("GOTO " str(NEW_INTERRUPT_VECTOR));

void BOOTLOADER_Initialize ()
{
    EE_Key_1 = 0;
    EE_Key_2 = 0;
    
    if (Bootload_Required () == true)
    {
        Run_Bootloader ();     // generic comms layer
    }
    
    STKPTR = 0x1F;
    
    asm ("pagesel " str(NEW_RESET_VECTOR));
    asm ("goto  "  str(NEW_RESET_VECTOR));
}

// *****************************************************************************
bool Bootload_Required ()
{

// ******************************************************************
//  Check the reset vector for code to initiate bootloader
// ******************************************************************                                 

    // This section reads the application start vector to see if the location is blank
    
    NVMADRL = NEW_RESET_VECTOR & 0xFF;    // (0x3FFF) or not.  If blank, it runs the bootloader.
    NVMADRH = (NEW_RESET_VECTOR & 0xFF00UL)>> 8;                                	
    
    // Otherwise, it assumes the application is loaded and instead runs the application.
    
    NVMCON1 = 0x80;
    NVMCON1bits.RD = 1;
    NOP();
    NOP();

    if ((NVMDATH == 0x3F) && (NVMDATL == 0xFF))
    {
        return (true);
    }

    return (false);
}


// *****************************************************************************
uint8_t  ProcessBootBuffer()
{
    uint8_t   len;

    EE_Key_1 = frame.EE_key_1;
    EE_Key_2 = frame.EE_key_2;

// ***********************************************
// Test the command field and sub-command.
    switch (frame.command)
    {
    case    READ_VERSION:
        len = Get_Version_Data();
        break;
    case    READ_FLASH:
        len = Read_Flash();
        break;
    case    WRITE_FLASH:
        len = Write_Flash();
        break;
    case    ERASE_FLASH:
        len = Erase_Flash();
        break;
    case    READ_CONFIG:
        len = Read_Config();
        break;
    case    WRITE_CONFIG:
        len = Write_Config();
        break;
    case    CALC_CHECKSUM:
        len = Calc_Checksum();
        break;
    case    RESET_DEVICE:
        reset_pending = true;
        len = 9;
        break;
    default:
        frame.data[0] = ERROR_INVALID_COMMAND;
        len = 10;
    }
    return (len);
}

// **************************************************************************************
// Commands
//
//        Cmd     Length----------------   Address---------------
// In:   [<0x00> <0x00><0x00><0x00><0x00> <0x00><0x00><0x00><0x00>]
// OUT:  [<0x00> <0x00><0x00><0x00><0x00> <0x00><0x00><0x00><0x00> <VERL><VERH>]
uint8_t  Get_Version_Data()
{
    frame.data[0] = MINOR_VERSION;
    frame.data[1] = MAJOR_VERSION;
    frame.data[2] = 0;       // Max packet size (256)
    frame.data[3] = 1;
    frame.data[4] = 0;
    frame.data[5] = 0;
    NVMADRL = 0x06;               // Get device ID
    NVMADRH = 0x00;
    NVMCON1bits.NVMREGS = 1;
    NVMCON1bits.RD = 1;
    NOP();
    NOP();
    frame.data[6] = NVMDATL;
    frame.data[7] = NVMDATH;
    frame.data[8] = 0;
    frame.data[9] = 0;

    frame.data[10] = ERASE_FLASH_BLOCKSIZE;
    frame.data[11] = WRITE_FLASH_BLOCKSIZE;

    NVMADRL = 0x00;
    NVMADRH = 0x00;
    NVMCON1bits.NVMREGS = 1;
    
    for (uint8_t  i= 12; i < 16; i++)
    {
        NVMCON1bits.RD = 1;
        NOP();
        NOP();
        frame.data[i] = NVMDATL;
        
        if ((++ NVMADRL) == 0x00)
        {
            ++ NVMADRH;
        }
    }

    return  25;   // total length to send back 9 byte header + 16 byte payload
}

// **************************************************************************************
// Read Flash
// In:	[<0x01><DLEN><ADDRL><ADDRH><ADDRU>]
// OUT:	[<0x01><DLEN><ADDRL><ADDRH><ADDRU><DATA>...]
uint8_t Read_Flash()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    NVMCON1 = 0x80;
    
    for (uint16_t i = 0; i < frame.data_length; i += 2)
    {
        NVMCON1bits.RD = 1;
        NOP();
        NOP();
        frame.data[i]  = NVMDATL;
        frame.data[i+1] = NVMDATH;
        
        if ((++ NVMADRL) == 0x00)
        {
            ++ NVMADRH;
        }
    }

    return (frame.data_length + 9);
}

// **************************************************************************************
// Write Flash
// In:	[<0x02><DLENBLOCK><0x55><0xAA><ADDRL><ADDRH><ADDRU><DATA>...]
// OUT:	[<0x02>]
uint8_t Write_Flash()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    NVMCON1 = 0xA4;       // Setup writes
    
    for (uint16_t  i= 0; i < frame.data_length; i += 2)
    {
        if (((NVMADRL & LAST_WORD_MASK) == LAST_WORD_MASK)|| (i == frame.data_length - 2))
            
        NVMCON1bits.LWLO = 0;
        NVMDATL = frame.data[i];
        NVMDATH = frame.data[i+1];

        StartWrite();
        
        if ((++ NVMADRL) == 0x00)
        {
            ++ NVMADRH;
        }
    }
    
    frame.data[0] = COMMAND_SUCCESS;
    EE_Key_1 = 0x00;  // erase EE Keys
    EE_Key_2 = 0x00;
    
    return (10);
}

// **************************************************************************************
// Erase Program Memory
// Erases data_length rows from program memory
uint8_t Erase_Flash ()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    
    for (uint16_t i=0; i < frame.data_length; i++)
    {
        if ((NVMADRH & 0x7F) >= ((END_FLASH & 0xFF00) >> 8))
        {
            frame.data[0] = ERROR_ADDRESS_OUT_OF_RANGE;
            return (10);
        }
        
        NVMCON1 = 0x94;       // Setup writes
        
        StartWrite();
        
        if ((NVMADRL += ERASE_FLASH_BLOCKSIZE) == 0x00)
        {
            ++ NVMADRH;
        }
    }
    
    frame.data[0]  = COMMAND_SUCCESS;
    frame.EE_key_1 = 0x00;  // erase EE Keys
    frame.EE_key_2 = 0x00;
    
    return (10);
}


// **************************************************************************************
// Read Config Words
// In:	[<0x06><DataLengthL><unused> <unused><unused> <ADDRL><ADDRH><ADDRU><unused>...]
// OUT:	[9 byte header + 4 bytes config1 + config 2]
uint8_t Read_Config ()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    NVMCON1 = 0x40;      // can these be combined?
    
    for (uint8_t  i= 0; i < frame.data_length; i += 2)
    {

        NVMCON1bits.RD = 1;
        NOP();
        NOP();
        frame.data[i]   = NVMDATL;
        frame.data[i+1] = NVMDATH;
        ++ NVMADRL;
    }
    
    return (13);           // 9 byte header + 4 bytes config words
}
// **************************************************************************************
// Write Config Words
uint8_t Write_Config ()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    NVMCON1 = 0xC4;       // Setup writes
    
    for (uint8_t  i = 0; i < frame.data_length; i += 2)
    {
        NVMDATL = frame.data[i];
        NVMDATH = frame.data[i+1];

        StartWrite();
        
        if ((++ NVMADRL) == 0x00)
        {
            ++ NVMADRH;
        }
    }
    frame.data[0] = COMMAND_SUCCESS;
    EE_Key_1 = 0x00;  // erase EE Keys
    EE_Key_2 = 0x00;
    
    return (10);
}


// **************************************************************************************
// Calculate Checksum
// In:	[<0x08><DataLengthL><DataLengthH> <unused><unused> <ADDRL><ADDRH><ADDRU><unused>...]
// OUT:	[9 byte header + ChecksumL + ChecksumH]
uint8_t Calc_Checksum()
{
    NVMADRL = frame.address_L;
    NVMADRH = frame.address_H;
    NVMCON1 = 0x80;
    check_sum = 0;
    
    for (uint16_t i = 0;i < frame.data_length; i += 2)
    {
        NVMCON1bits.RD = 1;
        NOP();
        NOP();
        check_sum += (uint16_t)NVMDATL;
        check_sum += ((uint16_t)NVMDATH) << 8;
        
        if ((++ NVMADRL) == 0x00)
        {
            ++ NVMADRH;
        }
    }
    
     frame.data[0] = (uint8_t) (check_sum & 0x00FF);
     frame.data[1] = (uint8_t)((check_sum & 0xFF00) >> 8);
     
     return (11);
}


// In: [<0x08><DataLengthL><DataLengthH> <unused><unused> <ADDRL><ADDRH><ADDRU><unused>...]
// OUT: [9 byte header + ChecksumL + ChecksumH]
/*uint8_t Calc_Checksum()
{
 uint16_t addr = (frame.address_H << 8) | frame.address_L; 
 check_sum = 0;
 for (uint16_t i = 0;i < frame.data_length; i += 2)
 {
 check_sum += FLASH_ReadWord(addr);
 ++ addr;
 }
 frame.data[0] = (uint8_t) (check_sum & 0x00FF);
 frame.data[1] = (uint8_t)((check_sum & 0xFF00) >> 8);
 return (11);
}*/




// *****************************************************************************
// Unlock and start the write or erase sequence.

void StartWrite()
{
    CLRWDT();
//    NVMCON2 = EE_Key_1;
//    NVMCON2 = EE_Key_2;
//    NVMCON1bits.WR = 1;       // Start the write
// had to switch to assembly - compiler doesn't comprehend no need for bank switch
    asm ("movf " str(_EE_Key_1) ",w");
    asm ("movwf " str(BANKMASK(NVMCON2)));
    asm ("movf  " str(_EE_Key_2) ",w");
    asm ("movwf " str(BANKMASK(NVMCON2)));
    asm ("bsf  "  str(BANKMASK(NVMCON1)) ",1");       // Start the write

    NOP();
    NOP();
    return;
}


// *****************************************************************************
// Check to see if a device reset had been requested.  We can't just reset when
// the reset command is issued.  Instead we have to wait until the acknowledgement
// is finished sending back to the host.  Then we reset the device.
void Check_Device_Reset ()
{
    if (reset_pending == true)
    {

        RESET();
    }
}




// *****************************************************************************
// *****************************************************************************

А вот код, сгенерированный с помощью МСС.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now