News:

;) This forum is the property of Proton software developers

Main Menu

Tiny Multi Bootloader

Started by AlbertoFS, May 19, 2025, 05:35 PM

Previous topic - Next topic

AlbertoFS

I downloaded the files of this bootloader and I do not know what is the correct asm file for the PIC18F25K22?
Thank you
73's de EA3AGV

JonW

If you are looking for the bootloader firmware, you must contact Evan on the tiny bootloader site and pay for it.

JonW

The website is very fragmented, but this link should download all the latest files HERE.  If you look in the firmware folder, a guy named Dan has provided the ASM for that device.

Alternatively you can pay Evan to generate a custom one for you

AlbertoFS

I want to try the version 0.14xx and I will try it.
I took an asm file for the PIC18F25K22 and I rewrite it with Positron.
It takes a little more bits but if more easy to read & to modify for other PICs.
Now it is the time to try it in hardware.
Thank you.
73's de EA3AGV

top204

#4
As Jon correctly stated, the Tiny Bootloader web site is very fragmented, and very difficult to navigate, and a lot of the source codes are not there or not tested etc... It is in desperate need of maintenance, because it has some important and useful sources on it (somewhere). LOL.

I created a bootloader for the Tiny bootloader in Positron8, and it is actually smaller than the original bloated, and confusing, assembler code. I uploaded it to the Tiny Bootloader site forum, but it just got ignored and forgotten. I did the same for the original Tiny+ bootloaders many years ago for projects I was working on, using their mechanism, but my code. :-)

The Tiny bootloader source is for a PIC18F26K40 device, using the internal oscillator at 64MHz, but it may help you in creating your own. It is listed below, and, as can be seen, it is a whole lot easier to navigate and understand the code than the original assembler codes:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Multi-Tiny+ Serial Bootloader for a PIC18F26K40 device.
' Operates with a 64MHz internal oscillator and a Baud of 19200.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
'
Declare Warnings = Off
    Device = 18F26K40                               ' Tell the compiler what device to compile for
    Declare Xtal = 64                               ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Library_Core = Off                      ' Disable the compiler's Library core and any extra items the compiler adds to a user's program

$define cIdTypePIC      0x6E                        ' The microcntroller type for the PC application
$define cMax_Flash      _code                       ' The amount of flash memory on the device (in bytes)
$define cWriteBlockSize _block                      ' The size of the block write to flash memory
$define cEepromSize     _eeprom                     ' Size of EEPROM (256 or 1024)

$define cBootloader_Address $eval (cMax_Flash - 264) ' 264 bytes long reserved at the top of flash for the bootloader
'
' Bit names of the NVMCONx SFRs
'
$define cRD      0
$define cWR      1
$define cWREN    2
$define cWRERR   3
$define cFREE    4
$define cNVMREG0 6
$define cNVMREG1 7
'
' Create variables for the bootloader
'
    Dim bWriteBuffer[64] As Byte                    ' Buffer used for holding data
    Dim bCRC             As Byte                    ' Holds the CRC value
    Dim bByteCount       As Byte                    ' Holds the amount of bytes for a block flash write
    Dim bFlags           As Byte                    ' Holds the requirement of which memory area to write
    Dim tEepromWrite     As bFlags.6                ' Set if EEPROM is to be written
    Dim tConfigWrite     As bFlags.7                ' Set if Config memory is to be written

    Dim bTimeoutCounter1 As Byte                    ' \
    Dim bTimeoutCounter2 As Byte                    ' |  Timeout counter for receiving a byte
    Dim bTimeoutCounter3 As Byte                    ' /

    Dim wFSR0 As FSR0L.Word                         ' Convert 8-bit SFRs FSR0L\H into a 16-bit SFR

$ifndef False
    $define False 0
$endif
$ifndef True
    $define True 1
$endif
'-----------------------------------------------------------------------
' Reset
'
    GoTo BootloaderStart                            ' Jump to the start of the bootloader
'
' Set the high flash memory address where the bootloader sits
'
    Org cBootloader_Address
    Nop                                             ' \
    Nop                                             ' | Space to store the first 4 mnemonics from the user program
    Nop                                             ' |
    Nop                                             ' /

BootloaderStart:
    ANSELC = 0                                      ' Set PORTC to digital
'
' Set the microcontroller to internal 64MHz operation with an HFINTOSC_1MHZ fuse
' Notes     : Waits for the oscillator to become stable
'
    OSCCON1 = %01100000
    OSCCON3 = %00000000
    OSCEN   = %00000000
    OSCFRQ  = %00001000
    OSCTUNE = %00000000
    Repeat: Until OSCSTATbits_HFOR = 1
'
' UART1 Actual Baud = 19230.8
' UART1 Baud Error = 0.15625
'
    BAUDCONbits_BRG16 = 0
    SP1BRG = 207                                    ' \
    SP1BRGH = 0                                     ' | Setup USART1 for 19200 Baud at 64MHz operation
    TX1STA  = 36                                    ' |
    RC1STA  = 144                                   ' /
'
' Configure USART1 PPS
'
    PPS_Unlock()                                    ' Unlock PPS
    TX1PPS = Pin_C6                                 ' Set PORTC.6 as TX
    RX1PPS = Pin_C7                                 ' Set PORTC.7 as RX
    RC6PPS = PPS_Fn_TX1                             ' Set PORTC.6 as TX
    RC7PPS = PPS_Fn_RX1                             ' Set PORTC.7 as RX
'
' Wait for computer response
'
    GoSub ReceiveByteInto_WREG                      ' Receive a byte from USART1 into WREG
    If WREG <> $C1 Then GoTo Bootloader_Exit        ' Expect $C1
    TXREG1 = cIdTypePIC                             ' Send the microcontroller type to the PC application

    Do                                              ' Create a loop
        Clrwdt                                      ' Clear the watchdog timer within the loop
        WREG = "C"                                  ' Everything OK so send the character "C" to the PC application
ContinueLoop:
        TXREG1 = WREG                               ' Transmit the contents of WREG
        bCRC = 0                                    ' Clear the CRC value
        GoSub ReceiveByteInto_WREG                  ' Receive the Upper address
        TBLPTRU = WREG
        bFlags = WREG                               ' For EEPROM and Config
        GoSub ReceiveByteInto_WREG                  ' Receive the High address
        TBLPTRH = WREG
        $if (cEepromSize = 1024)
        NVMADRH = WREG                              ' High address of EEPROM
        $endif
        GoSub ReceiveByteInto_WREG                  ' Receive the Low address
        TBLPTRL = WREG
        NVMADR = WREG                               ' Low address of EEPROM

        GoSub ReceiveByteInto_WREG                  ' Receive the byte count required for writing
        bByteCount = WREG                           ' Place it into variable bByteCount

        wFSR0 = AddressOf(bWriteBuffer)             ' FSR0L\H now hold Buffer Beginning address
        Tblrd*-                                     ' Read from flash memory with auto decrement of address in TBLPTR
RcvOct:
        GoSub ReceiveByteInto_WREG                  ' Receive the type of write
        POSTINC0 = WREG                             ' For Config memory
        NVMDAT = WREG                               ' For EEPROM
        TABLAT = WREG                               ' For Flash memory
        Tblwt+*                                     ' Write to flash memory with auto increment of address
        Djnz bByteCount, RcvOct                     ' Loop for the amount of bytes to receive

        GoSub ReceiveByteInto_WREG                  ' Get CRC
CRC_Failed:                                         ' CRC failed
        WREG = "N"                                  ' Get ready to send the character "N"
        If STATUSbits_Z = 0 Then GoTo ContinueLoop

        If tConfigWrite = True Then                 ' Skip if not writing to Config
            GoTo Write_Config                       ' Write Config
        EndIf
        WREG = (1 << cWREN)                         ' Setup for EEPROM write
        If tEepromWrite = False Then                ' Is it an EEPROM write?
            GoSub SetupEraseBlock                   ' No. So setup to erase the block of flash memory
        EndIf
        GoSub SetupWriteByte
        Continue
        '
        ' Write the configuration fuses (if required)
        '
Write_Config:
        Dec FSR0L                                   ' FSR0 = FSR0 - 1
        Clrwdt                                      ' Clear the watchdog timer
        TABLAT = INDF0                              ' Load TABLAT
        WREG = ((1 << cNVMREG1) | (1 << cNVMREG0) | (1 << cWREN))  ' Setup for Config memory
        GoSub SetupWriteByte
        Tblrd*-                                     ' Write to memory and auto decrement address in TBLPTRL\H
        Tstfsz FSR0L                                ' FSR0L = 0?
        GoTo Write_Config                           ' \ Loop until FSR0L = 0
    Loop                                            ' /
'
' Subroutines
'
SetupEraseBlock:
    WREG = $94                                      ' Setup Erase; EEPGD, FREE, WREN = 1, CFGS = 0

SetupWriteByte:
    NVMCON1 = WREG
    NVMCON2 = $55                                   ' \ Unlock memory writes
    NVMCON2 = $AA                                   ' /
    NVMCON1bits_WR = 1
    Retlw ((1 << cNVMREG1) | (1 << cWREN))          ' Setup for writes in WREG when returned

ReceiveByteInto_WREG:
    Clrwdt                                          ' Clear the watchdog timer
    bTimeoutCounter1 = ((_xtal / 2) + 1)            ' For 20MHz => 11 => 1 second delay
Repeat1:
    bTimeoutCounter2 = 0
Repeat2:
    bTimeoutCounter3 = 0
Repeat3:
    If PIR3bits_RC1IF = 0 Then NotReceivedYet       ' Receive a byte from USART1
    WREG = RC1REG                                   ' Place the read data into WREG
    bCRC = bCRC + WREG                              ' Calculate CRC
    Return

NotReceivedYet:
    Clrwdt                                          ' Clear the watchdog timer within the inner loop
    Djnz bTimeoutCounter3, Repeat3
    Djnz bTimeoutCounter2, Repeat2
    Djnz bTimeoutCounter1, Repeat1
'
' Timeout
'
Bootloader_Exit:
    NVMCON1 = 0                                     ' Deactivate EECON
    RCSTA1bits_SPEN = 0                             ' Deactivate USART1
    GoTo(cBootloader_Address)                       ' Jump to the start of the user program

'-----------------------------------------------------------------------------------------------
' Setup the fuses to use the internal oscillator on a PIC18F26K40. With RA6 and RA7 as I/O lines
'
Config_Start
    RSTOSC = HFINTOSC_1MHZ          ' With HFFRQ = 4MHz and CDIV = 4:1
    FEXTOSC = Off                   ' External Oscillator not enabled
    WDTE = On                       ' WDT enabled
    CLKOUTEN = Off                  ' CLKOUT function is disabled
    CSWEN = On                      ' Writing to NOSC and NDIV is allowed
    FCMEN = Off                     ' Fail-Safe Clock Monitor disabled
    MCLRE = EXTMCLR                 ' MCLR pin is MCLR
    PWRTE = On                      ' Power up timer enabled
    LPBOREN = off                   ' ULPBOR disabled
    BOREN = On                      ' Brown-out turned on
    BORV = VBOR_245                 ' Brown-out Reset Voltage (VBOR) set to 2.45V
    ZCD = Off                       ' ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON
    PPS1WAY = Off                   ' PPSLOCK bit can be set and cleared repeatedly (subject to the unlock sequence)
    STVREN = Off                    ' Stack full/underflow will not cause Reset
    Debug = Off                     ' Background debugger disabled
    XINST = Off                     ' Extended Instruction Set and Indexed Addressing Mode disabled
    SCANE = Off                     ' Scanner module is Not available for use. SCANMD bit is ignored
    LVP = Off                       ' Low Voltage programming disabled
    WDTCPS   = WDTCPS_16            ' Watchdog Divider ratio 1:2091752 (64 seconds)
    WDTCWS   = WDTCWS_7             ' Window always open (100%). Software control. Keyed access not required
    WDTCCS   = LFINTOSC             ' WDT reference clock is the 31.2kHz HFINTOSC output
    WRT0 = Off                      ' Block 0 (000800-001FFF) not write-protected
    WRT1 = Off                      ' Block 1 (002000-003FFF) not write-protected
    WRTC = Off                      ' Configuration registers (300000-30000B) not write-protected
    WRTB = Off                      ' Boot Block (000000-0007FF) write-protected
    WRTD = Off                      ' Data EEPROM not write-protected
    Cp = Off                        ' User NVM code protection disabled
    CPD = Off                       ' Data NVM code protection disabled
    EBTR0 = Off                     ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1 = Off                     ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTRB = Off                     ' Boot Block (000000-0007FF) not protected from table reads executed in other blocks
Config_End

The oscillator could be changed to operate at 64MHz as standard, without the SFR setups, by altering the config fuse settings, but this was when I was first learning the new 18F26K40 device, and wanted things to guarantee work. :-) Also, remember, the bootloader code above enables the Watchdog timer, because that was required by the project it was written for. So if the Watchdog is not required in your programs, disable it in the config fuse settings of the bootloader code listing.

You will probably need to change the "cIdTypePIC" value as well, because I wrote the above source code before it was supported by the bootloader PC application. I actually altered the C++ PC application as well, to make it smoother to use, instead of the bloat in the original. However, I cannot release that source code.

I would highly recommend the PIC18FxxK40 devices. They are very reliable, easy to use, and have lots in them for their price. The newer PIC18FxxQxx devices also seem to match them more closer than other devices, in their internal workings.

AlbertoFS

Thank you very much Les.
73's de EA3AGV

midali

Looks here, maybe is usefull for you: Bootloader

AlbertoFS

I have finished to modify the bootloader for the PIC18F25k22.
I think I'm going to use the PIC18F25K40. But I probably need to modify the piccodes.ini file.
$6D, C, 18F w/32KB flash & 1024B EE,   $8000, $400, 264, 128,
$6E, C, 18F w/64KB flash & 1024B EE,  $10000, $400, 264, 128,

What is the significance of the last parameters of these lines, after $8000/$10000?
Than Yoo.
73's de EA3AGV

JonW

Its documented inside the Piccodes.ini file

; device's line structure:
; ID code (as defined in source firmware!), device family, device name, max flash memory (bytes),EE (bytes), bootloader size (bytes), transfert block size (bytes),
;
; The '$' symbol is for hexadecimal numbers.
;
;     Specific to Family "B". The high bit of for the ID Code indicates this is an Enhanced 16F or 12F PIC

AlbertoFS

Thank you JonW,
The bootloader size (bytes) must be a multiple of write Block number or the number of real compiled bytes?
Sorry I am new in this aera (TinyBootloader)
Thank you
73's de EA3AGV

top204

#10
If memory serves me right, because it has been quite a while since I created a bootloader.

The size of the bootloader, and its starting address depends on the erase block size, because the original reset address jump that is held at the start of flash memory, is stored in the bootloader's flash, or just under it. So when the device's flash is being written too, the flash erase block is cleared, then the bytes are written to it, and the original jump address has to be safe.

It is the PC application that re-arranges the address jumps in the HEX file that is being written, so it swaps the original jump with the start address of the bootloader, and the bootloader jumps to what was once held in the device's reset address. i.e. Address $0000.

The original flash PIC devices did not have this problem, because they could be written just like EEPROM, and one word erased, then written too. Instead of having to erase a larger lump of flash, just to write a single word to it, as the later devices had to. However, looking at some of the brand new devices, it seems they may have gone back to the original method of one word erase, and one word write.

AlbertoFS

Thank you very much Les.
73's de EA3AGV