18F25K83 BOOTLOADER

mikroC, mikroBasic and mikroPascal PRO for Microchip’s 8-bit PIC MCUs.
Post Reply
Author
Message
Richie800
Posts: 50
Joined: 09 Jul 2007 00:31

18F25K83 BOOTLOADER

#1 Post by Richie800 » 15 Dec 2020 13:51

I am trying to create a bootloader for a 25k83 chip based on the UART bootloader. Unfortunately, cannot get it to work. Could someone help me please?
The code can be flashed to the chip just fine. However, when using the Mikrobootloader to load new code, the code does not write the new code correctly. after flashing new code, it will either not go through the bootloader sequence (when Const _Flash_Erase = 64) or end up in a continuous loop (when Const _Flash_Erase = 128).

If I download the code from the chip after flashing the new code (when Const _Flash_Erase = 64) the code does not contain the intended flash code. However, when Const _Flash_Erase = 128, it looks good but does not work or jump to where the code is.

Code: Select all

program Boot_Test_25k83


Const _Flash_Erase = 64
dim block as byte[_FLASH_ERASE]

'-------------- Empty sub function, this is where the start address of "real"
'               program will be placed (by Write_Begin()).
sub procedure Start_Program org 0x7FC0
  ' FLASH_ERASE is 64
  ' 32 nops are stored as last 64 bytes of program memory

  nop nop nop nop  nop nop nop nop
  nop nop nop nop  nop nop nop nop
  nop nop nop nop  nop nop nop nop
  nop nop nop nop  nop nop
  ' 31 is for return  ' 32 is unused
end sub

sub procedure Flash_Write_Sector(dim address as longword, dim sdata as ^byte)
  
  dim saveintcon, i, j as byte
  saveintcon = INTCON
    '--- erase FLASH memory
  TBLPTRU = Higher(address)
  TBLPTRH = Hi(address)
  TBLPTRL = Lo(address)
  ' Write Address High
  '--- write memory
  ' Read Block
  NVMCON1.REG0 = 0         ' Clear the register
  NVMCON1.REG1 = 1         ' Set the Register
  NVMCON1.WREN = 1
  NVMCON1.FREE = 1
  INTCON0.GIE  = 0
  NVMCON2      = $55
  NVMCON2      = $AA
  NVMCON1.WR   = 1
  INTCON0.GIE  = 1
  asm
     TBLRD*-      ; read into TABLAT, and inc
  end asm
  '--- write memory
  FSR0L = Lo(sdata)
  FSR0H = Hi(sdata)
  j = 0
  while (j < (_FLASH_ERASE div _FLASH_WRITE_LATCH))
    i = 0
    while (i < _FLASH_WRITE_LATCH)
      TABLAT = POSTINC0
      asm
        TBLWT+*
      end asm
      Inc(i)
    wend
    NVMCON1.REG0  = 0
    NVMCON1.REG1  = 1
    NVMCON1.WREN  = 1
    NVMCON1.FREE  = 0
    INTCON0.GIE   = 0
    NVMCON2       = $55
    NVMCON2       = $AA
    NVMCON1.WR    = 1
    Inc(j)
  wend
  TABLAT = POSTINC0
  

  INTCON.GIE  = 1

  '--- restore interrupt
  INTCON = saveintcon
end sub

'-------------- This sub procedure will recover the bootlocation 0x0000, 0x0001 and
'               0x0002 to point to the bootloaer"s main. It will also move
'               the reset vector of the program that is uploaded to a new
'               location.
sub procedure Write_Begin
  Flash_Write_Sector(0x7FA0, @block)' address is org of Start_Program
  '--- goto main bootloader (see GOTO _main opcode at the beginning of asm listing)
  ' 0xF0 3A EF 80
  block[0] = 0x80
  block[1] = 0xEF
  block[2] = 0x3A
  block[3] = 0xF0
end sub

sub function Susart_Write_Loop(dim send, receive as byte) as byte
  result = 0
  while(true)
    Delay_8ms
    UART1_Write(send)
    Delay_8ms

    Inc(result)
    if (result = 255) then
      result = 0
      exit
    end if
    if (UART1_Read = receive) then
      result = 1
      exit
    end if
  wend
end sub

sub procedure Start_Bootload
  dim  i, xx, yy as byte
       j as longword
  i = 0
  j = 0
  '--- If 32 words (64 bytes) recieved then write to flash
  while true
    if (i = _FLASH_ERASE) then
      if (j = 0) then
        Write_Begin
      end if
      Flash_Write_Sector(j, @block)
      i = 0
      j = j + _FLASH_ERASE
    end if
    '--- Ask for yy
    UART1_Write("y")
    while UART1_Data_Ready = 0
      nop
    wend
    '--- Read yy
    yy = UART1_Read()
    '--- Ask for xx
    UART1_Write("x")
    while UART1_Data_Ready = 0
      nop
    wend
    '--- Read xx
    xx = UART1_Read
    '--- Save xxyy in block[i]
    block[i] = yy
    Inc(i)
    block[i] = xx
    Inc(i)
  wend
end sub


main: org 0x7500                            ' org main
  orgall(0x7500)                      ' store bootloader code
  ANSELC = 0x00' 
  RC6PPS = 0x13'   //RC6->UART1:TX1;
  U1RXPPS = 0x17'   //RC7->UART1:RX1;
  UART1_Init(9600)                    ' Init USART1 at 9600
  if (Susart_Write_Loop("g","r")) then ' Send "g" for ~5 sec, if "r"
    Start_Bootload()                   '   received start bootload
  else
    Start_Program()                   '   else start user"s program
  end if
end.

Richie800
Posts: 50
Joined: 09 Jul 2007 00:31

Re: 18F25K83 BOOTLOADER

#2 Post by Richie800 » 16 Dec 2020 13:07

Solved

Code: Select all

sub procedure Start_Program org 0x7FC0

Code: Select all

Flash_Write_Sector(0x7FA0, @block)' address is org of Start_Program
These two address should match.

Bootloader works now.

:D

Richie800
Posts: 50
Joined: 09 Jul 2007 00:31

Re: 18F25K83 BOOTLOADER

#3 Post by Richie800 » 23 Dec 2020 03:50

Me again.

The code compiles just fine and I can flash the chip with the bootloader code. However, Rxtx_Data transmitted does not match what is loaded into the 8 byte array. When I send the code over UART, RxTx_Data information matches the data loaded.

Please help.

Code: Select all

const SJW = 1
const BRP = 8
const PHSEG1 = 3
const PHSEG2 = 4
const PROPSEG = 8
const CAN_CONFIG_FLAGS = _CAN_CONFIG_SAMPLE_ONCE and
                                          _CAN_CONFIG_PHSEG2_PRG_ON  and
                                          _CAN_CONFIG_XTD_MSG        and
                                          _CAN_CONFIG_DBL_BUFFER_ON and
                                          _CAN_CONFIG_VALID_XTD_MSG and
                                          _CAN_CONFIG_LINE_FILTER_OFF

Const _Flash_Erase = 128
const START_PROGRAM_ADDR as word = 0x7FC0
const BOOTLOADER_START_ADDR as Longword = 0x6A00   '130316
dim block as byte[_FLASH_ERASE]

dim Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags as byte ' CAN flags
    Rx_Data_Len as byte                                   ' received data length in bytes
    RxTx_Data as byte[8]                                   ' can rx/tx data buffer
    Msg_Rcvd as byte                                       ' reception flag
    Count as word
    Rx_ID, Tx_ID as Word
    TXT as string[3]
    Text2 as string[5]
    I as byte
Sub Procedure wait
    delay_Ms(2)
end sub

sub procedure Flash_Write_Sector(dim address as longword, dim sdata as ^byte)
  dim saveintcon, i, j as byte

  saveintcon = INTCON

    '--- erase FLASH memory
  TBLPTRL = Lo(address)
  TBLPTRH = Hi(address)
  TBLPTRU = Higher(address)
  '--- required erase sequence
  NVMCON1.REG0 = 0         ' Clear the register
  NVMCON1.REG1 = 1         ' Set the Register
  NVMCON1.WREN = 1
  NVMCON1.FREE = 1
  INTCON0.GIE  = 0
  NVMCON2      = 0x55
  NVMCON2      = 0xAA
  NVMCON1.WR   = 1
  INTCON0.GIE  = 1
  asm
     TBLRD*-
  end asm
  '--- write memory
  FSR0L = Lo(sdata)
  FSR0H = Hi(sdata)
  j = 0
  while (j < (_FLASH_ERASE div _FLASH_WRITE_LATCH))
    i = 0
    while (i < _FLASH_WRITE_LATCH)
      TABLAT = POSTINC0
      asm
        TBLWT+*
      end asm
      Inc(i)
    wend
    NVMCON1.REG0  = 0
    NVMCON1.REG1  = 1
    NVMCON1.WREN  = 1
    NVMCON1.FREE  = 0
    INTCON0.GIE   = 0
    NVMCON2       = $55
    NVMCON2       = $AA
    NVMCON1.WR    = 1
    Inc(j)
  wend
  TABLAT = POSTINC0


  INTCON.GIE  = 1

  '--- restore interrupt
  INTCON = saveintcon
end sub

sub procedure Write_Begin()
  Flash_Write_Sector(START_PROGRAM_ADDR, @block)' address is org of Start_Program
  '--- goto main bootloader (see GOTO _main opcode at the beginning of asm listing)
  ' This adjust code to goto the beginning of the bootloader    6C
  ' 0xF0 35 EF 00

'  block[0] = 0x5D
  block[0] = 0x00
  block[1] = 0xEF
  block[2] = 0x35
  block[3] = 0xF0
end sub

sub procedure Start_Bootload
  dim  i as byte
       j as longword
  i = 0
  j = 0
  '--- If 32 words (64 bytes) recieved then write to flash
  while true
    if (i = _FLASH_ERASE) then
      if (j = 0) then
        Write_Begin
      end if
      Flash_Write_Sector(j, @block)
      i = 0
      j = j + _FLASH_ERASE
    end if

    Do

      Msg_Rcvd = CANRead(Tx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags)   ' receive message

    Loop until (Msg_Rcvd = True)

    If (Msg_Rcvd) then
      If RxTx_Data[0] = $0B then
        ' No need to ask for "yy" and "xx"
        'Verify code proper format
         block[i] = RxTx_Data[1]
         inc(I)
         block[i] = RxTx_Data[2]
         inc(I)
         block[i] = RxTx_Data[3]
         inc(I)
         block[i] = RxTx_Data[4]
         inc(I)

         ' Confirm return flags
         RxTx_Data[0] = 20
         RxTx_Data[1] = 20
         RxTx_data[2] = i
         ' Required to transfer MCU address
         RxTx_Data[6] = hi(Rx_ID)
         RxTx_Data[7] = lo(Rx_ID)
         ' Number of bytes to send
         Rx_Data_len = 8
         Wait
         Msg_Rcvd = 0
         Canwrite(1050, RxTx_Data, Rx_Data_len, Can_send_flags)
      end if
      IF (RxTx_Data[5] = 255) and (RxTx_Data[6] = 170) then
        ' Check for end flag
        Reset
      end if
    end if
    Wait

  wend
end sub

sub procedure Start_Program() org START_PROGRAM_ADDR
  ' FLASH_ERASE is 64
  ' 32 nops are stored as last 64 bytes of program memory

  nop nop nop nop  nop nop nop nop
  nop nop nop nop  nop nop nop nop
  nop nop nop nop  nop nop nop nop
  nop nop nop RESET
  ' 31 is for return  ' 32 is unused

end sub

main: ORG BOOTLOADER_START_ADDR
  OrgAll(BOOTLOADER_START_ADDR)
  
  LATB    = $00              ' Setup for input use.
  PortB   = $00
  TRISB   = 0x08
  LATA    = $00             ' Setup for input use.
  PortA   = $00
  TrisA   = $00
  LATC    = $00
  PortC   = $00
  TrisC   = $00              ' CAN Tris setup. This may not be neccessary.
  ANSELC  = 0xE7
  ANSELB  = 0xF7
  ANSELA  = 0xFF
  ODCONB  = 0x00
  SLRCONB = 0xFF
  INLVLB  = 0xFF
  WPUB = 0x00
  ANSELC = 0x00'
  Count   = 0
  Unlock_IOLOCK()  '
    PPS_Mapping(23, _Output, _CANTX1)
  Lock_IOLOCK()

  '-----------------------------------------------------------------------------
  '  Can Bus initialize

  ' Read Data from EEPROM Address
  '-----------------------------------------------------------------------------
   RX_ID = 4010

  '  Can Bus initialize

  '-----------------------------------------------------------------------------

  Can_Init_Flags = 0                                        '
  Can_Send_Flags = 0                                        ' clear flags
  Can_Rcv_Flags  = 0                                        '


  Can_Send_Flags = _CAN_TX_PRIORITY_0 and              ' form value to be used
                    _CAN_TX_XTD_FRAME and              '     with CANSPIWrite
                    _CAN_TX_NO_RTR_FRAME

  Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE and       ' form value to be used
                    _CAN_CONFIG_PHSEG2_PRG_ON and      ' with CANSPIInit
                    _CAN_CONFIG_XTD_MSG and
                    _CAN_CONFIG_DBL_BUFFER_ON and
                    _CAN_CONFIG_VALID_XTD_MSG

  CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, CAN_CONFIG_FLAGS)

  CANSetOperationMode(_CAN_MODE_CONFIG,0xFF)

  CANSetMask(_CAN_MASK_B1,-1,_CAN_CONFIG_XTD_MSG)' set all mask1 bits to ones
  CANSetMask(_CAN_MASK_B2,-1,_CAN_CONFIG_XTD_MSG)' set all mask2 bits to ones
  CANSetFilter(_CAN_FILTER_B2_F3, RX_ID,_CAN_CONFIG_XTD_MSG)

  CANSetOperationMode(_CAN_MODE_NORMAL,0xFF)               ' set NORMAL mode
  '-----------------------------------------------------------------------------

  '-----------------------------------------------------------------------------
  ' Log into Main MCU so and prepare for bootloader
  RxTx_Data[0] = 10
  RxTx_Data[1] = $30
  RxTx_Data[3] = 0
  RxTx_Data[4] = 0
  RxTx_Data[5] = 0
  RxTx_Data[2] = 0
  RxTx_Data[6] = Hi(Rx_ID)
  RxTx_Data[7] = Lo(Rx_ID)
  Rx_Data_Len  = 8
  ' Send data to main MCU
  Canwrite(1050, RxTx_Data, Rx_Data_len, Can_Send_Flags)

'-------------------------------------------------------------------------------
  While Count < 1000
     ' receive message
     Msg_Rcvd = CANRead(Tx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags)
     ' Check Broadcast and message directed to this receiver

     if Msg_Rcvd then                ' Message received
        CanWrite(1000, RxTx_Data , Rx_Data_Len, Can_Send_Flags)
        Wait
        if RxTx_data[0] = 10 then
           RxTx_data[0] = 255
           RxTx_data[1] = 170
           RxTx_data[2] = 255
           RxTx_data[3] = 170
           Rx_Data_Len  = 6
           ' Transmit acknoledgement
           Wait
           CANWrite(1050 , RxTx_Data , Rx_Data_Len, Can_Send_Flags)
           Start_Bootload()             '   received start bootload
           Reset
        end if

     end if

     If (Count = 200) or (Count = 600)  then                ' Re-transmit at midpoint
        '-----------------------------------------------------------------------
        ' Log into Main MCU so and prepare for bootloader
        ' Send data to main MCU
        RxTx_Data[0] = 10
        RxTx_Data[1] = $30
        RxTx_data[3] = 0
        RxTx_data[4] = 0
        RxTx_data[5] = Lo(Count)
        RxTx_data[2] = Hi(Count)
        RxTx_Data[6] = Hi(Rx_ID)
        RxTx_Data[7] = Lo(Rx_ID)
        Rx_Data_Len  = 8
        Canwrite(1050, RxTx_Data, Rx_Data_len, Can_send_flags)
       ' Time is needed for code to respond
        Delay_ms(500)
       '-------------------------------------------------------------------

     end if
     Inc(Count)
  wend
  Start_Program()                   '   else start program

end.

Post Reply

Return to “PIC PRO Compilers”