News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

FREELOADER

Started by JonW, Sep 20, 2026, 08:03 PM

Previous topic - Next topic

Frizie

It indeed refuses to install on Windows 7 (that's the laptop I always use to write my Positron programs—offline).
It says "Missing api-ms-win-core-path-l1-1-0.dll".
I need to find a way to fix that first.
Ohm sweet Ohm | www.picbasic.nl

JonW

#21
Hi Frizie, it won't run on Win7.  I'll look at doing a simple C cmd line version.  I can compile that to run in 95 +



J

top204

Many thanks Jon.

If size is the problem, I can place it on my google drive, and put a permanent link to the files on the forum.

I still have approx 10GB spare on the google drive.

Best regards
Les


John Lawton

I'm also happy to host files on my Easy-Driver site.

John
-----------------------------------------------------------------------------------------
Amicus 8 and 16A/16B dev boards
Especially created for Positron development
https://www.easy-driver.co.uk/Amicus

JonW

Cool beans, chaps, that will save me a load of work.  I am now halfway through building the C command-line version; this should work from Win95 to Win11 and can be built with an open-source compiler for other OS too.  It should be finished in a day or so and tested. 

I am only doing the 18F for now, and it should be easy enough to port to 16F and DSPic.  Also, not sure it's worth it on the 16F enhanced devices.


I will produce HTML help files as these are much easier to host and read.

RGV250

Hi Jon,
You have gone above and beyond, I was just looking for a guide to how to be able to do them for myself. Or is that what the HTML files are for?

Regards,
Bob

JonW

Hi Bob

I am working on the detailed guide for both the PC and the PIC, but you don't need to for the above devices, as I have them all done for the Amicus and Johns 18F dev board.

John Lawton

Hi Jon,

your Amicus boards are being shipped today.

John
-----------------------------------------------------------------------------------------
Amicus 8 and 16A/16B dev boards
Especially created for Positron development
https://www.easy-driver.co.uk/Amicus

JonW

Cheers John

Im ready for them  ;D

JonW

#29
Guys

Attached is a completely new command-line version that should work from Win95 to Win11. I can supply a Linux one but have not tested it fully yet

The new freeloader application is again a single exe and has an HTML help file with all the commands and how to use it.
It does the same as the above Python Gui but is driven from the command line now to make it work on all Win builds

In addition, I have built and tested the following devices and packaged them in separate files, including all required files and edge-case hex files.
I have built all the K20, K22, Q43 and K40 devices but only included the following as the others have not been tested in devices yet.

K20: P25K20, P26K20
K22: P23K22, P25K22, P26K22
Q43: P25Q43, P27Q43
K40: P27K40, P47K40

Appreciate it if you can test them, and I will hold back on doing more until they are proven by others

Cheers

Jon



RGV250

Hi Jon,
Hopefully not a stupid question.
When you say test them, do you want us to just install it and test the test program or try other programs.

Bob

JonW

#31
Hi Bob

Yeah, absolutely, you can use your own bas files as long as they have the same config.  There is no need to install it; the freeloader. exe is already built and just needs extensions added and run in a command-line window.  Download the file and place it into a folder.  Every Pic has all the files.  Load the Pxxxx_mwboot.hex into your device with PicKit

Compile your program and either add the hex file to the folder or add freeloader.exe to your working folder.  You can also use the Pxxx_Blink.bas or hex that's included as a test and change the LED to any port. You can delete the config block or leave it; it's there for informational purposes and matches what is in the bootloader hex.

Copy the folder location, open a CMD window, and navigate to the folder.  Type freeloader yourfile.hex -com5  or freeloader --info com5

Obviously, you will change com5 to whatever your com port is; by default, I have used 115200, and the PIC runs at 64MHz internal osc, MCLR as a Pin

There are also edge case hex files built which stress the bootloader (one will fail to upload and this is intentional)

Please read the HTML help file; it has all of the commands in there and how to use them

Jon




Frizie

That sounds very promising Jon.
I have a day off tomorrow (Wednesday) and will go busy with it, run the tests and let you know the results.

Many thanks in advance :P
Ohm sweet Ohm | www.picbasic.nl

Frizie

Pffffiieeuw!  :o
Your "FREELOADER" bootloader is incredibly good, Jon!  ;D

I ran some tests this afternoon with the commandline version.
I didn't find any errors, and FREELOADER is super fast.
While Tiny Bootloader+ takes several minutes for the same program (it claims 115200 baud, but I saw little difference compared to 9600 baud), FREELOADER is lightning-fast.

I've added your bootloader to the list of PIC programmers in the Positron IDE.
Pressing F10 in the Positron IDE compiles the PIC Basic program and then programs it right after that (fast!) into the PIC via the bootloader  :P


One small request for the future:
Is it possible to specify the resettime as a parameter?
Currently, after powering up the PIC, there is a (short) delay of 1–2 seconds before the program starts.
My programs include a buzzer that beeps immediately upon power-up, so right now there is that 1–2 second lag.
It would be fantastic if I could set that to 0 seconds using a parameter, after all, manual resetting isn't necessary since the DTR signal handles it.

And can I make a donation?  8)
Ohm sweet Ohm | www.picbasic.nl

JonW

#34
Ha nice one, glad it's of use; give the donation to Les ;D   Many thanks
It's about as fast as you can get with the write times internal to the PIC.  I calculated that the TBL was wasting hours per week on upload alone, and it briced at times.


The delays on the devices do vary a little but should be less than 0.2; they comprise:
 
Power up timer 64ms
K20/22 ONLY: 12ms Start up/PLL wait (stupid device with no PLL ready bit)
Mwboot waits 100ms before entering your code; I've already reduced this to the bare minimum.

What device are you using? 47k20?  Maybe plot this on a scope with reset pulse edge vs buzzer output with direct code and bootloader added?

You may also want to share how you added this; it will be useful


Pepe

#35
Is it possible to modify Freeloader to write to the EEPROM of the 18F2550 because I've modified the bootloader and it works when simulating it in Proteus, but it doesn't write to the EEPROM and only runs the program that makes the LED blink? I have to leave the 'leave EEPROM alone' option enabled for only the flash programming to work.

' FREELOADER / mwboot / mwload
' Adaptación para PIC18F2550
'****************************************************************************
'*  MWBOOT  - PIC18F2550                                                    *
'*                                                                          *
'*  Board   : PIC18F2550, UART en RC6 (TX) / RC7 (RX)                       *
'*  Clock   : 48 MHz (Cristal 20MHz + PLL)                                  *
'*  Baud    : 115200                                                        *
'*  Flash   : 0x08000 (32 K)    EEPROM 256 B                                *
'*  Slot    : 0x07BF8   boot code 0x07C00   INFO 0x07FE4                    *
'*  App     : 0x00000 .. 0x07BF7                                            *
'****************************************************************************
    Declare Warnings = Off
    Device = 18F2550
    Declare Xtal = 48
    Declare Library_Core = Off

'---------------------------------------------------------------------------
' MEMORY DEFINITIONS (32 KB Flash, 32-byte write latches, 64-byte erase)
'---------------------------------------------------------------------------
$define cFlashBytes     32768                           ' 32 KB
$define cPageBytes      256                             ' host frame
$define cBootPages      4                               ' 1024 B para bootloader
$define cBootStart      $eval (cFlashBytes - (cBootPages * cPageBytes))  ' 0x7C00
$define cSlot           $eval (cBootStart - 8)          ' 0x7BF8

'---------------------------------------------------------------------------
' EUSART: 48 MHz, BRG16 = 1, BRGH = 1 -> 115200 baud -> Divisor = 103
'---------------------------------------------------------------------------
$define cBaudDivisor    103

'---------------------------------------------------------------------------
' Receive timeout scaling (PIR1 en Access Bank)
'---------------------------------------------------------------------------
$define cLoopCycles     7
$define cMidPerMs       $eval (((_xtal * 250) + (cLoopCycles * 128)) / (cLoopCycles * 256))
$define cWindowMs       100
$define cByteMs         50

'---------------------------------------------------------------------------
' INFO layout & constants
'---------------------------------------------------------------------------
$define cInfo           $eval (cFlashBytes - 28)        ' 0x7FE4
$define cInfoU          $eval (cInfo >> 16)             ' 0x00
$define cInfoH          $eval ((cInfo >> 8) & 255)      ' 0x7F
$define cInfoL          $eval (cInfo & 255)             ' 0xE4
$define cBuild          1
$define cFamily         3
$define cFeatures       $02                             ' CORREGIDO: b1 EEPROM, b0 READ (Sin modo Lite $20)
$define cDisp_IE        0x0C
$define cDisp_EW        0x12
$define cDisp_WX        0x0F
$define cDisp_XR        0x0A
$define cBootU          $eval (cBootStart >> 16)        ' 0x00
$define cBootH          $eval ((cBootStart >> 8) & 255) ' 0x7C
$define cEeU            0x31                            ' W / R ADDR U = 0x31 -> EEPROM
$define cEeBlocks       1                               ' 256 Bytes EEPROM = 1 bloque
$define cRowBytes       32                              ' 18F2550 write block size = 32 B
$define cRowsPerFrame   8                               ' 8 x 32 = 256 B por frame
$define cEraseRowBytes  64                              ' 18F2550 erase block size = 64 B
$define cEraseRows      4                               ' 4 x 64 = 256 B por frame

' EE/Flash EECON1 Commands
$define cFlash_Erase    0x94                            ' EEPGD=1, CFGS=0, FREE=1, WREN=1
$define cFlash_Write    0x84                            ' EEPGD=1, CFGS=0, FREE=0, WREN=1
$define cEE_Data        0x04                            ' EEPGD=0, CFGS=0, WREN=1
$define cNVM_Idle       0x00

$define cVec0           $eval ((cBootStart >> 1) & 255)
$define cVec2           $eval ((cBootStart >> 9) & 255)
$define cVec3           $eval (240 | ((cBootStart >> 17) & 15))
$define cBaudActual     $eval ((48000000 + (2 * (cBaudDivisor + 1))) / (4 * (cBaudDivisor + 1)))
$define cFlashU         $eval (cFlashBytes >> 16)
$define cFlashH         $eval ((cFlashBytes >> 8) & 255)
$define cFlashL         $eval (cFlashBytes & 255)
$define cSlotU          $eval (cSlot >> 16)
$define cSlotH          $eval ((cSlot >> 8) & 255)
$define cSlotL          $eval (cSlot & 255)
$define cPageH          $eval (cPageBytes >> 8)
$define cPageL          $eval (cPageBytes & 255)
$define cEeSizeH        1                               ' CORREGIDO: Byte alto de 256 (0x01)
$define cEeSizeL        0                               ' CORREGIDO: Byte bajo de 256 (0x00)
$define cBaudU          $eval (cBaudActual >> 16)
$define cBaudH          $eval ((cBaudActual >> 8) & 255)
$define cBaudL          $eval (cBaudActual & 255)

'---------------------------------------------------------------------------
' Variables (Access RAM)
'---------------------------------------------------------------------------
    Dim bRxTimeout As Byte
    Dim bTo1       As Byte
    Dim bTo2       As Byte
    Dim bTo3       As Byte
    Dim bCmd       As Byte
    Dim bAdrU      As Byte
    Dim bAdrH      As Byte
    Dim bAdrL      As Byte
    Dim bLen       As Byte
    Dim bCnt       As Byte
    Dim bCrcH      As Byte
    Dim bCrcL      As Byte
    Dim bCrcB      As Byte
    Dim bCrcN      As Byte
    Dim bRows      As Byte
    Dim bTxB       As Byte
    Dim wFSR0 As FSR0L.Word
    Dim bBuf[256]  As Byte

    GoTo BootloaderStart

    Org cSlot                                   ' 0x07BF8
    Nop
    Nop
    Nop
    Nop

BootloaderStart:                                ' 0x07C00
'---------------------------------------------------------------------------
' Hardware Init: ADCON1 para digital, Puertos UART en RC6/RC7
'---------------------------------------------------------------------------
    EECON1   = cNVM_Idle
    ADCON1   = $0F                              ' Todos los pines a Digital
    TRISC.6  = 0                                ' TX = Salida
    TRISC.7  = 1                                ' RX = Entrada
    SPBRGH   = 0
    SPBRG    = cBaudDivisor
    BAUDCON  = (1 << 3)                         ' BRG16 = 1
    TXSTA    = ((1 << 5) | (1 << 2))            ' TXEN = 1, BRGH = 1
    RCSTA    = ((1 << 7) | (1 << 4))            ' SPEN = 1, CREN = 1

    bRxTimeout = cWindowMs
    GoSub RxByte
    If WREG <> "U" Then GoTo Bootloader_Exit
    bRxTimeout = cByteMs
    WREG = "B"
    GoSub TxByte

CmdLoop:
    STKPTR = 0
    bCrcH = $FF
    bCrcL = $FF
    GoSub RxCrc
    bCmd = WREG
    If bCmd = "U" Then Sync_Reply
    GoSub RxCrc
    bAdrU = WREG
    GoSub RxCrc
    bAdrH = WREG
    GoSub RxCrc
    bAdrL = WREG
    GoSub RxCrc
    bLen = WREG
    bCnt = bLen
    If bCnt <> 0 Then Rx_Data
    If bCmd <> "W" Then Rx_Crc
Rx_Data:
    wFSR0 = AddressOf(bBuf)
Rx_Data_Loop:
    GoSub RxCrc
    POSTINC0 = WREG
    Djnz bCnt, Rx_Data_Loop
Rx_Crc:
    GoSub RxCrc
    GoSub RxCrc
    If bCrcH <> 0 Then Crc_Bad
    If bCrcL <> 0 Then Crc_Bad

    Asm
        Movf    bCmd, w
        Xorlw   0x49             ; "I"
        Bz      Do_Info
        Xorlw   cDisp_IE
        Bz      Do_Erase
        Xorlw   cDisp_EW
        Bz      Do_Write
        Xorlw   cDisp_WX
        Btfsc   STATUS, 2
        Bra     Do_Exit
        Xorlw   cDisp_XR
        Btfsc   STATUS, 2
        Bra     Do_Read
    EndAsm
    WREG = "?"
    GoTo Reply

Crc_Bad:
    WREG = "C"
    GoTo Reply

Sync_Reply:
    WREG = "B"
Reply:
    GoSub TxByte
    GoTo CmdLoop

'---------------------------------------------------------------------------
' Command: I - Info
'---------------------------------------------------------------------------
Do_Info:
    bCrcH = $FF
    bCrcL = $FF
    WREG = "K"
    GoSub TxCrc
    TBLPTRU = cInfoU
    TBLPTRH = cInfoH
    TBLPTRL = cInfoL
    bCnt = 26
    GoSub Tx_Table
    TBLPTRU = $3F                               ' 0x3FFFFE = DEVID
    TBLPTRH = $FF
    TBLPTRL = $FE
    bCnt = 2
    GoSub Tx_Table
Tx_CrcEnd:
    WREG = bCrcH
    GoSub TxByte
    WREG = bCrcL
    GoTo Reply

'---------------------------------------------------------------------------
' Command: E - Erase 256-byte frame (4 x 64-byte blocks)
'---------------------------------------------------------------------------
Do_Erase:
    GoSub Guard_Erase
    EECON1 = cNVM_Idle
    WREG = "K"
    GoTo Reply

'---------------------------------------------------------------------------
' Command: W - Write 256-byte frame (8 x 32-byte latches)
'---------------------------------------------------------------------------
Do_Write:
    Asm
        Movlw   cEeU
        Xorwf   bAdrU, w
        Btfsc   STATUS, 2
        Bra     W_EE
    EndAsm
    GoSub Guard_Erase                           ' Borra frame y deja TBLPTR al inicio
    Asm
        Movf    bAdrU, w
        Iorwf   bAdrH, w
        Bnz     W_Data          ; no es página 0
        Movlw   cVec0           ; Redirección vector Reset página 0 -> Bootloader
        Movwf   bBuf
        Movlw   0xEF
        Movwf   bBuf+1
        Movlw   cVec2
        Movwf   bBuf+2
        Movlw   cVec3
        Movwf   bBuf+3
W_Data:
        Lfsr    0, bBuf
        Tblrd*-                 ; TBLPTR = frame - 1
        Movlw   cRowsPerFrame   ; 8 bloques de 32 bytes
        Movwf   bRows
W_Row:
        Movlw   cRowBytes       ; 32 bytes
        Movwf   bCnt
W_Byte:
        Movf    POSTINC0, w
        Movwf   TABLAT
        Tblwt+*                 ; Carga latches de escritura
        Decfsz  bCnt, f
        Bra     W_Byte
    EndAsm
    WREG = cFlash_Write
    GoSub NVM_Go                                ' Programa el bloque de 32 bytes
    Djnz bRows, W_Row
    Asm
        Movf    bAdrU, w        ; Read-back de verificación
        Movwf   TBLPTRU
        Movf    bAdrH, w
        Movwf   TBLPTRH
        Clrf    TBLPTRL
        Lfsr    0, bBuf
W_Check:
        Tblrd*+
        Movf    TABLAT, w
        Cpfseq  POSTINC0
        Bra     Nvm_Fail
        Decfsz  bCnt, f         ; 256 bytes
        Bra     W_Check
    EndAsm
    EECON1 = cNVM_Idle
    WREG = "K"
    GoTo Reply

'---------------------------------------------------------------------------
' Command: X - Exit
'---------------------------------------------------------------------------
Do_Exit:
    GoSub Tx_K_Done
    GoTo Bootloader_Exit

Tx_K_Done:
    WREG = "K"
    GoSub TxByte
K_Load:
    If PIR1.4 = 0 Then K_Load                   ' TXIF en PIR1.4 para PIC18F2550
K_Drain:
    If TXSTA.1 = 0 Then K_Drain                 ' TRMT en TXSTA.1
    Return

'---------------------------------------------------------------------------
' Guard_Erase (CORREGIDO: Salta borrado si la dirección es de EEPROM)
'---------------------------------------------------------------------------
Guard_Erase:
    Asm
        Movlw   cEeU
        Xorwf   bAdrU, w
        Bz      Guard_EE_Skip                   ; Si es dirección EEPROM (0x31), omite borrado Flash
       
        Movf    bLen, w
        Iorwf   bAdrL, w
        Bnz     Guard_L
        Movlw   cBootH
        Subwf   bAdrH, w
        Movlw   cBootU
        Subwfb  bAdrU, w
        Bc      Guard_A
        Movf    bAdrU, w
        Movwf   TBLPTRU
        Movf    bAdrH, w
        Movwf   TBLPTRH
        Clrf    TBLPTRL
        Movlw   cEraseRows                       ; 4 bloques de 64 bytes
        Movwf   bRows
    EndAsm
E_Row:
    WREG = cFlash_Erase
    GoSub NVM_Go
    TBLPTRL = TBLPTRL + cEraseRowBytes
    Djnz bRows, E_Row
Guard_EE_Skip:
    Return

Guard_L:
    WREG = "L"
    GoTo Reply
Guard_A:
    WREG = "A"
    GoTo Reply
Nvm_Fail:
    EECON1 = cNVM_Idle
    WREG = "F"
    GoTo Reply

'---------------------------------------------------------------------------
' NVM_Go (CORREGIDO: Secuencia estricta de desbloqueo NVM en ASM puro)
'---------------------------------------------------------------------------
NVM_Go:
    EECON1 = WREG
    EECON1.3 = 0                                ' Limpia flag WRERR previo
    Asm
        Bcf     INTCON, 7                       ; GIE off (Deshabilita interrupciones)
        Movlw   0x55
        Movwf   EECON2
        Movlw   0xAA
        Movwf   EECON2
        Bsf     EECON1, 1                       ; Activa bit WR
    EndAsm
NVM_Wait:
    If EECON1.1 = 1 Then NVM_Wait              ' Espera que WR se limpie
    If EECON1.3 = 1 Then Nvm_Fail              ' WRERR check
    Return

'***************************************************************************
'*  Subrutinas I/O                                                         *
'***************************************************************************
RxByte:
    bTo1 = bRxTimeout
Rx_1:
    bTo2 = cMidPerMs
Rx_2:
    bTo3 = 0
Rx_3:
    If PIR1.5 = 1 Then Rx_Got                   ' RCIF en PIR1.5 para 18F2550
    Djnz bTo3, Rx_3
    Djnz bTo2, Rx_2
    Djnz bTo1, Rx_1
    If bRxTimeout = cWindowMs Then GoTo Bootloader_Exit
    RCSTA.4 = 0                                 ' Limpia OERR
    RCSTA.4 = 1
    GoTo CmdLoop
Rx_Got:
    WREG = RCREG
    Return

TxByte:
    bTxB = WREG
Tx_Wait:
    If PIR1.4 = 0 Then Tx_Wait                  ' TXIF en PIR1.4 para 18F2550
    TXREG = bTxB
    Return

RxCrc:
    GoSub RxByte
    GoTo Crc16

TxCrc:
    GoSub Crc16
    GoTo TxByte

Tx_Table:
    Asm
        Tblrd*+
    EndAsm
    WREG = TABLAT
    GoSub TxCrc
    Djnz bCnt, Tx_Table
    Return

Crc16:
    Asm
        Movwf   bCrcB
        Xorwf   bCrcH, f
        Movlw   8
        Movwf   bCrcN
Crc_Bit:
        Bcf     STATUS, 0
        Rlcf    bCrcL, f
        Rlcf    bCrcH, f
        Bnc     Crc_Next
        Movlw   0x21
        Xorwf   bCrcL, f
        Movlw   0x10
        Xorwf   bCrcH, f
Crc_Next:
        Decfsz  bCrcN, f
        Bra     Crc_Bit
        Movf    bCrcB, w
    EndAsm
    Return

'---------------------------------------------------------------------------
' EEPROM R/W (Módulo EECON1 / EEADR / EEDATA)
'---------------------------------------------------------------------------
W_EE:
    Asm
        Movlw   cEeBlocks
        Cpfslt  bAdrH
        Bra     Guard_A
        Decf    bLen, w
        Addwf   bAdrL, w
        Bnc     EE_Go
        Bra     Guard_L
EE_Go:
        Movf    bLen, w
        Movwf   bCnt
        Lfsr    0, bBuf
    EndAsm
    EEADR = bAdrL
EE_Byte:
    GoSub EE_Read
    Asm
        Cpfseq  INDF0
        Rcall   EE_Write
        Cpfseq  POSTINC0
        Bra     Nvm_Fail
    EndAsm
    EEADR = EEADR + 1
    Djnz bCnt, EE_Byte
    EECON1 = cNVM_Idle
    WREG = "K"
    GoTo Reply

EE_Write:
    EEDATA = INDF0
    WREG = cEE_Data
    GoSub NVM_Go
EE_Read:
    EECON1 = 0
    EECON1.0 = 1                                ' RD = 1
    WREG = EEDATA
    Return

'---------------------------------------------------------------------------
' Command: R - Read Flash / EEPROM
'---------------------------------------------------------------------------
Do_Read:
    Asm
        Movf    bLen, w
        Btfss   STATUS, 2
        Bra     Guard_L
        Setf    bCrcH
        Setf    bCrcL
        Movlw   0x4B
        Rcall   TxCrc
        Movf    bAdrU, w
        Movwf   TBLPTRU
        Movf    bAdrH, w
        Movwf   TBLPTRH
        Movf    bAdrL, w
        Movwf   TBLPTRL
        Movlw   cEeU
        Xorwf   bAdrU, w
        Bz      R_EE
        Rcall   Tx_Table
        Bra     Tx_CrcEnd
    EndAsm
R_EE:
    EEADR = bAdrL
R_EE_Byte:
    GoSub EE_Read
    GoSub TxCrc
    EEADR = EEADR + 1
    Djnz bCnt, R_EE_Byte
    EECON1 = cNVM_Idle
    GoTo Tx_CrcEnd

Bootloader_Exit:
    Asm
        Clrf    TBLPTRU
    EndAsm
    GoTo(cSlot)

    Org cInfo
    CData $4D, $57, $42, 1, cFamily, cFeatures, cBuild, _
          cFlashU,  cFlashH,  cFlashL, _
          cSlotU,   cSlotH,   cSlotL, _
          cPageH,   cPageL, _
          cEeSizeH, cEeSizeL, _
          $F0, $00, $00, _
          cBaudU,   cBaudH,   cBaudL, _
          $00, $00, $00

'***************************************************************************
' Configuration Fuses (CORREGIDO: Fuses de protección WRT desactivados)
'***************************************************************************
Config_Start
    PLLDIV   = 5                                ' 20 MHz / 5 = 4 MHz entrada al PLL
    CPUDIV   = OSC1_PLL2                        ' 96 MHz PLL / 2 = 48 MHz CPU
    USBDIV   = 2
    FOSC     = HSPLL_HS                         ' Cristal HS con PLL habilitado
    FCMEN    = OFF
    IESO     = OFF
    PWRT     = On
    BOR      = OFF
    VREGEN   = On
    MCLRE    = On
    LVP      = OFF
    XINST    = OFF
    WRT0     = OFF                              ' Desactiva protección escritura bloque 0
    WRT1     = OFF                              ' Desactiva protección escritura bloque 1
    WRT2     = OFF                              ' Desactiva protección escritura bloque 2
    WRT3     = OFF                              ' Desactiva protección escritura bloque 3
    WRTB     = OFF                              ' Desactiva protección escritura boot block
    WRTC     = OFF                              ' Desactiva protección escritura registros Config
Config_End

okmn

PIC18F56Q71 – flash write, bootloader and config questions (Positron8 4.0.6.x)

Hello Les and all. I am using Positron8 4.0.6.4 with the PIC18F56Q71. I want to load my application with a UART bootloader at the top of flash (JonW's mwboot). I have read the manual and the .def file, but I could not clear up the points below. Thank you.

18F56Q71.def says "$define _erase 256 ' Size of the Flash Memory Erase Segment (in Words)". The datasheet (DS40002329F, section 10.3) says the erase page is 128 words (256 bytes). 18F56Q43.def says "_erase 128". Which value is correct for the Q71? Does Cwrite or any other command use this value?

On the Q series (Q43/Q71), does Cwrite read-erase-rewrite the 256-byte page, or must the target area already be erased? The manual (Cwrite, p.391) does not say.

"Cerase" is in the reserved-words list (Positron8 and Positron16), but the manual does not describe it. Does this command exist? What is its syntax and what area does it erase on the Q71 (one page = 256 bytes?)?

The manual says "Declare BootLoader enables the special settings that a serial bootloader requires at the start of code space" (default On). What exactly does it change on the 18F Q series? mwboot moves the application's first 8 bytes into its own "slot" and writes its own GOTO at address 0. In that case, should the application use Declare BootLoader = On or Off?

My application must end below 0xFCF8 (above that is the bootloader). Is there a Declare, or any way, to make the compiler give an error if code passes a given address, or to reserve the top of flash? Or should I check it by hand in the .lst file?

 JonW's Q43 note says "the short form RSTOSC = HFINTOSC_64MHZ works; the long form from the .ppi fails". Is it the same on the Q71? Could you share a complete Config_Start ... Config_End example you recommend for the 18F56Q71 (64 MHz internal oscillator, MCLR on, LVP on, WDT off)?

On the Q71 the EEPROM is 256 bytes at 0x380000. Are Eread/Ewrite fully supported on the Q71 in Positron8 4.0.6.x? Does Edata place its data at 0x380000 in the hex file?

For an application that uses interrupts (MVECEN = OFF, classic 0x0008/0x0018 vectors), is any special setting needed with a bootloader at the top of flash? If I use MVECEN = ON (IVT), is there anything I should watch for in Positron?

The Positron16 manual lists Cwrite/Cerase as reserved words but does not describe them. Is self-writing to program memory supported on the dsPIC33CK (e.g. dsPIC33CK64MP102) with Positron16? We would like to write a bootloader for dsPIC later too.

Many thanks for your time. We will use your answers in our project and credit the source.



JonW

Hi Pepe

FREELOADER doesn't need changing. It already writes EEPROM on any part where the bootloader says it can. It reads the EEPROM size, address and "EEPROM supported" flag from the chip's INFO block, then sends the Edata from 0xF00000 in the hex, which is where the 2550's 256 bytes live. The issue is with your port.

This and the post above were exactly why I didn't want to share the code. No disrespect to you, but it just causes endless work. I will take a look, but I don't have that device on hand.

Pepe

Thank you for your reply.

JonW

#39
OKMN


I'll take the mwboot bits and leave the compiler internals to Les..


                                                          ALL please remember this is provided free and is new (its a week old). I didn't create the bootloader to cause Les an endless barrage of posts.   


I will try to answer the best I can vs questions

First, the Q71 isn't in mwboot yet. The current build covers the Q43, K42, K83, K40, K22 and K20 families. The Q71 has the same NVM model as the Q43 (NVMCON/NVMLOCK, 256-byte page, EEPROM at 0x380000), so a port should be small. I'll put it on the list. Until then, use a Q43 if you want to test on a supported part.

Cwrite, Cerase and _erase: mwboot doesn't use any of them. It drives the NVM registers directly in asm. It erases each 256-byte page before writing it and reads it back to check. Your app doesn't need Cwrite to be loaded. Whether Cwrite erases first on the Q parts, what Cerase does and which _erase value is right are questions for Les. For what it's worth, 128 words = 256 bytes is what the datasheet says.

Declare BootLoader: all my bench test apps are built with the default, and they load and run fine. The one hard rule is that the first 8 bytes of your app must start with a GOTO. mwboot moves those bytes into its slot at flash−776 and runs them from there. If real code sits at address 0 instead of a jump, it will run straight into the bootloader. Check the .lst: address 0 should be a GOTO to your start.

Staying below 0xFCF8: FREELOADER refuses a hex that has anything in the slot or the bootloader. It tells you before it writes anything, so you can't brick the bootloader by mistake. FREELOADER app.hex COM5 --dry-run shows you the plan without touching the part. If you want the compiler itself to stop you, that's Les's area. Otherwise, check the end address in the .lst.

Config: mwboot never writes config. The app runs with whatever fuses the bootloader was programmed with, and the fuses in your app's hex are ignored when loading. On the Q43, the short form RSTOSC = HFINTOSC_64MHZ worked for me. I haven't tried the Q71, so check the names against its .ppi, or Les can confirm.

EEPROM: FREELOADER writes Edata to the part's EEPROM. It accepts EEPROM data at 0x380000, 0x310000 or 0xF00000 in the hex and moves it to wherever the connected part keeps it. Whether Eread/Ewrite are fully supported on the Q71 is one for Les.

Interrupts: with MVECEN = OFF, the vectors at 0x0008/0x0018 belong to your app, and mwboot doesn't touch them. Only the first 8 bytes move. With MVECEN = ON, mwboot never writes IVTBASE, so the same applies. Just keep your vector table and your code below the slot.

dsPIC33CK: the silicon supports self-write (RTSP), so a bootloader is possible. Whether Positron16 has commands for it is Les's call. I'd do it the same way as mwboot anyway, driving NVMCON directly in asm.


It also has nothing to do with Les.

Cheers

Jon

▲