News:

Let's find out together what makes a PIC Tick!

Main Menu

dsPIC33CK bootloader ?

Started by diebobo, Oct 19, 2023, 04:42 PM

Previous topic - Next topic

diebobo

Hi Les,

In a post on the Tiny+ Bootloader+ forum 23/05/2020 you mentioned you were working on a bootloader for the dsPIC33CK devices.. A while ago we cracked the 200mHz on that chip and was wondering if u made any progress on that bootloader ? For now i am using the trusty 24FJ64GA004 with a bootloader but would really use thoose CK devices with a few projects, but cannot really because of lack of a bootloader.. 

Wimax

A little nudge to and old, but still relevant post  :) Is there any news ?

top204

#2
I was investigating a bootloader for the Positron16 board I was developing, but had to give up on it because of other commitments, and the fact that it is impossible to compete with the chinese, and the modern "I want it for pennies, or free" mentality that now dominates anything to do with electronics, computers, or microcontrollers.

So for the months of work that I had already done, and the money spent on boards and components for R&D, I would have had to do more months, and more money, and maybe sold 10 of them, if lucky! Without a funding support of some kind, advertising is far too expensive, on top of development costs etc...

Regards
Les

diebobo

Quote from: Wimax on Sep 21, 2025, 02:28 PMA little nudge to and old, but still relevant post  :) Is there any news ?

This subject is still alive with me.. Still working on it though paused.. My basis is my bootloader for a 24FJ64GA004 since it shares the same structure as the CK devices, but i found a problem with that 24FJ bootloader which i need to fix first... If working then i got bootloader for the CK PIC + PC Program + Tasmota driver to make WiFi / Wireless upload of program possible ( Last part already works for 24FJ device ).. Although not sure how friendly it all will be of custom everything..

Pcitures of the CK board in use currently.

So wont be anytime soon Wimax, but i also said that about the I2S MIC and all of a sudden there was something workable soon afterall :)

IMG_20250922_190846.jpg


IMG_20250922_190911.jpg


Wimax

 
Quote from: diebobo on Sep 22, 2025, 05:25 PMSo wont be anytime soon Wimax, but i also said that about the I2S MIC and all of a sudden there was something workable soon afterall :)



Hello Diebobo ;)

I remember your project with the i2s microphone very well. At the time, I knew nothing about the dspic33ck256mp508. Some time has passed, and I have spent several nights getting to know this little monster which, I must say, differs greatly in some ways from the pic24fj and hj that I was familiar with. I wanted to experiment with ultrasonic I2s microphones, but I couldn't find anything affordable. Although I had always used the traditional method to program the microcontrollers I worked with, I was trying to figure out how to create a convenient bootloader specifically for Dspic33ck, but that's where I stopped.


Wimax


Hello Everybody! ;D

Proceeding slowly, I would like to try a minimal version of a bootloader, but my hands are tied. From what I have read, the architectural differences between 8-bit and 16-bit MCUs are such that, for example, commands such as "DECLARE Compiler_Start_Address" to declare the initial compilation memory location or "Declare Library_Core = Off" do not work on positron24. It is not enough to insert the 'Org' directive in the source code; it is necessary to intervene on the linker file. Leaving the compiler, I find myself in an area that is quite obscure to me... what changes are necessary and how should we proceed?
Does anyone have any experience in this area?

diebobo

Quote from: Wimax on Oct 05, 2025, 06:33 AMHello Everybody! ;D

Proceeding slowly, I would like to try a minimal version of a bootloader, but my hands are tied. From what I have read, the architectural differences between 8-bit and 16-bit MCUs are such that, for example, commands such as "DECLARE Compiler_Start_Address" to declare the initial compilation memory location or "Declare Library_Core = Off" do not work on positron24. It is not enough to insert the 'Org' directive in the source code; it is necessary to intervene on the linker file. Leaving the compiler, I find myself in an area that is quite obscure to me... what changes are necessary and how should we proceed?
Does anyone have any experience in this area?


Wimax, still no reaction.. I got so little time i need to keep it short.. I started some experiments converting my 24FJ bootloader to 33CK device, and i ended somewhere, but not sure where.. Not working sample code, but u ask something to get u started.. i have that, the start.. The end, pehaps u get there faster then me :) As is, to let u know Org works, library core = off works.. just need to make own __reset: label... Enjoy the headscratching !

'// Bootloader Without Config Write. Make Sure Config Below is what u need in target Program.
'// Boatloader will not rewrite itself, its at last Page. Some lost space, but much safer. PIC's have enough space nowadays.

Device = 33CK256MP205
Declare Xtal = 200
Declare Library_Core = Off 

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

Dim Bytes_2_Receive            As Word
Dim Bytes_2_Receive_Loop        As Word
Dim Bytes_2_Receive_Buffer[600] As Byte                    ' Buffer used for holding data
Dim CRC_Received                As Byte
Dim CRC_Calculated              As Byte                    ' Holds the CRC value
Dim Main_Byte                  As Byte
Dim TBLPAG_Received            As Byte

Dim Received_Start_Address      As Word
Dim Erased_Tot_Address          As Word = 0
Dim Page_2_Erase                As Byte

Dim Instruction_Word            As Word
Dim Instruction_Byte            As Byte

$define cIdTypePIC          0xB7 ''B7    ' The microcntroller type for the PC application
'ADD LINE IN PICCODES.INI    $B3, E, PIC24FJ w/64KB flash,    $15800, 0, 1550  , default,

''$define cBootloader_Address 0x2b000  ' Addres 15000h, veryfied with readback and HEX viewer with Intel HEX decoding.
$define cBootloader_Address 0xA5F8  ' Addres 15000h, veryfied with readback and HEX viewer with Intel HEX decoding.

$define Debug_WriteSimulation ' Comment / uncomment to Enabele with build
$define Debug_Enabled

GoTo BootloaderStart

Org cBootloader_Address

BootloaderStart:
 
  Asm
    Clr.w WREG0
    Clr.w WREG1
    Bclr.w INTCON1,#4
    Retfie
  EndAsm

  __reset:

  Asm ' Just some prepping and clearing. Just general stuff.
  ; Setup the stack
    Mov.w #0x1000,W15
    Mov.w #0x10ba,W0
    Mov.w W0,SPLIM
    Nop
  ; Clear the WREG sfrs
    Clr.w W0
    Mov.w W0,W14
    Repeat #12
    Mov.w W0,[++W14]
    Clr.w W14
  ; clearing ram For the Clear directive
    Clr.w W0
    Mov.w #0x10ba,W1
    Repeat #0x2f45
    Mov.w W0,[W1++]
    Clr.w TBLPAG
EndAsm
 
  Osc_200MHz_Init()

  PPS_Output(cOut_Pin_RP46, cOut_Fn_U1TX)
  PPS_Input(cIn_Pin_RP47, cIn_Fn_U1RX)

  U1MODEbits_UARTEN  = 1; //enable uart
  U1MODEbits_UTXEN    = 1; //transmitter enabled
  U1MODEbits_URXEN    = 1; //Receiver enabled
  Main_Byte          = U1RXREG ' USART Buffer uitlezen, zit altijd iets in na reboot en anders triggered interrupt niet.
  U1MODEL = %1000000000110000
  U1BRGL  = %0000001010001010
 
$ifdef Debug_Enabled Then 
  U2MODEbits_UARTEN  = 1; //enable uart
  U2MODEbits_UTXEN    = 1; //transmitter enabled
  U2MODEbits_URXEN    = 1; //Receiver enabled
  Main_Byte          = U2RXREG ' USART Buffer uitlezen, zit altijd iets in na reboot en anders triggered interrupt niet.
          '  5432109876543210
  U2MODEL = %1000000010110000 ' This combo = 38400 Baud
  U2BRGL  = %0000001010001010

  PPS_Output(cOut_Pin_RP49, cOut_Fn_U2TX) ' Map UART2 TX pin to RP10
  PPS_Input(cIn_Pin_RP48, cIn_Fn_U2RX)    ' Map UART2 RX pin to RP9

  U2TXREG = 10 ' Carriage return and linefeed for nice clean start.
  U2TXREG = 13
  U2TXREG = "X"
 
  TRISB.8 = 0
  LATB.8 = 1 
  ;Delay_Ms (1000)
$endif 
 
  Begin:
 
  If ReceiveByte () <> $C1 Then GoTo Bootloader_Exit ' Expect $C1
  U1TXREG = cIdTypePIC                      ' Send the type to the PC application
  U1TXREG = "E"                            ' Send the Famil to the PC application
  ReceiveByte ()
  ReceiveByte ()

  $ifdef Debug_Enabled Then
    U2TXREG = "-"
    U2TXREG = "-"
    U2TXREG = "-"
    U2TXREG = 10
    U2TXREG = 13
  $endif

Mainloop:
 
  $ifdef Debug_Enabled Then
    Toggle LATB.8
  $endif
 
  U1TXREG = "E" ' Send the Famil to the PC application
 
  Clear CRC_Calculated 

  Received_Start_Address.LowByte  = ReceiveByte ()
  Received_Start_Address.HighByte  = ReceiveByte ()
  TBLPAG_Received                  = ReceiveByte ()
  Bytes_2_Receive                  = ReceiveByte ()
  Bytes_2_Receive                  = 384
 
  ''Bytes_2_Receive.HighByte                  = ReceiveByte ()

  ''Debug_Number_Byte (Bytes_2_Receive )

  For Bytes_2_Receive_Loop = 0 To Bytes_2_Receive - 1 
    Bytes_2_Receive_Buffer[Bytes_2_Receive_Loop] = ReceiveByte ()
  Next

  CRC_Received = ReceiveByte () ' CRC_Calculated should be 0 after this byte received. If not exit. CRC_Received = only to receive byte. No calculations are done with it.
 
(*  If CRC_Calculated > 0 Then
    U1TXREG  = "N" ' Send error.
    ReceiveByte () ' Just for delay function so that CRC Failed can be transfered. Otherwise Bootloader exit also disables UART function before "N" is send.
    GoTo Bootloader_Exit
  EndIf *)
 
  $ifndef Debug_WriteSimulation Then

    If Erased_Tot_Address <= Received_Start_Address Then
      If Erased_Tot_Address = 0 Then
        Page_2_Erase = 0
      Else
        Page_2_Erase = Received_Start_Address / 2048       
      EndIf
      If Page_2_Erase < 42 Then ' 42 and up is Bootloader range, never erase..
        MCU_Code_Erase (TBLPAG_Received, Page_2_Erase)
        Erased_Tot_Address = ( Page_2_Erase * 2048 ) + 2048
      EndIf
    EndIf
 
    ; Setup a pointer to data Program Memory
    Mov TBLPAG_Received, W3 ;
    Mov W3, TBLPAG ;Initialize PM Page Boundary SFR
 
    Mov Received_Start_Address, W2 ;Initialize a register with program memory address
    Mov #Bytes_2_Receive_Buffer_0, W3 ;

    For Bytes_2_Receive_Loop = 0 To ( Bytes_2_Receive - 1 ) Step 3' -1 cause last byte = CRC.
      Instruction_Word.LowByte  = Bytes_2_Receive_Buffer[Bytes_2_Receive_Loop]
      Instruction_Word.HighByte = Bytes_2_Receive_Buffer[Bytes_2_Receive_Loop + 1]
      Instruction_Byte          = Bytes_2_Receive_Buffer[Bytes_2_Receive_Loop + 2]

      WREG3 = Instruction_Word ' Instructions are 3 byte sized. they form 1.5 words = 2 words = 2 Address space #
      WREG4 = Instruction_Byte
      TblwtL W3,[W2]            ; Write PM high byte into program latch
      TblwtH W4,[W2++]
    Next

    ; Setup NVMCON for programming one word to data Program Memory
      Mov #0x4001, W0 ;
      Mov W0, NVMCON ; Set NVMOP bits to 0011
      Disi #5 ; Disable interrupts while the KEY sequence is written
      Mov #0x55, W0 ; Write the key sequence
      Mov W0, NVMKEY
      Mov #0xAA, W0
      Mov W0, NVMKEY
      Bset NVMCON, #15 ; Start the write cycle
      Nop ; 2 NOPs required after setting WR
      Nop ;
  $endif 

  $ifdef Debug_Enabled Then
    Debug_Number_Byte (Received_Start_Address.LowByte)
    Delay_Ms (1)
    Debug_Number_Byte (Received_Start_Address.HighByte)
    Delay_Ms (1)
    Debug_Number_Byte (TBLPAG_Received )
    Delay_Ms (1)
    Debug_Number_Byte (Bytes_2_Receive )
    Delay_Ms (1)
   
    U2TXREG = 10
    U2TXREG = 13
  $endif

  GoTo Mainloop
 

Proc Osc_200MHz_Init()

  CLKDIV = $3001          ' FRCDIV FRC/1, PLLPRE 1, DOZE 1:8
  PLLFBD = 100 ''90 = 180 mhx
  OSCTUN = $00
  PLLDIV = $21            ' POST1DIV 1:2, VCODIV FVCO/4, POST2DIV 1:1
  ACLKCON1 = $0101        ' FRCSEL FRC, APLLPRE 1:1
  APLLFBD1 = $C8
  APLLDIV1 = $42          ' APOST1DIV 1:4, APOST2DIV 1:2, AVCODIV FVCO/4*)

  Write_OSCCONH($01)
  Write_OSCCONL($01)

  While OSCCONbits_OSWEN <> 0 : Wend  ' Wait for the clock switch to occur
EndProc   
   
Proc ReceiveByte (), Byte
 ; Delay_Ms(10)
  bTimeoutCounter1 = ((_xtal / 1) + 1)    'was /2 / For 20MHz => 11 => 1 second delay.. Changed for longer delay, change if needed faster booting.
Repeat1:
  Clear bTimeoutCounter2
Repeat2:
  Clear bTimeoutCounter3
Repeat3:
  If U1STAHbits_URXBE = 1 Then NotReceivedYet      ' Receive a byte from USART1
  U1STAHbits_URXBE = 1
  Result = U1RXREG                                  ' Place the read data into WREG
  CRC_Calculated = CRC_Calculated + Result                              ' Calculate CRC
 
  Return

NotReceivedYet:
  Djnz bTimeoutCounter3, Repeat3
  Djnz bTimeoutCounter2, Repeat2
  Djnz bTimeoutCounter1, Repeat1
 
 GoTo Bootloader_Exit
EndProc

Bootloader_Exit:
 
  Clear NVMCON 

  U1MODEbits_UARTEN  = 0; //enable uart
  U1MODEbits_UTXEN    = 0; //transmitter enabled
  U1MODEbits_URXEN    = 0; //Receiver enabled
 
  U2MODEbits_UARTEN  = 0; //enable uart
  U2MODEbits_UTXEN    = 0; //transmitter enabled
  U2MODEbits_URXEN    = 0; //Receiver enabled
         
  TRISA = 65535
  TRISB = 65535
  TRISC = 65535
  TRISD = 65535
 
  GoTo(cBootloader_Address) ' Jump to the start of the user program.

Proc MCU_Code_Erase ( Page As Word, Block_Nr As Byte )

  Dim Offset As Word

  MCU_Code_Erase_Offset = Block_Nr * 2048 ' Erase per 8 rows, each 64 instructions = 8 x 64 x 2 ( 1 instruction = 2 words ) = 1024 addresses

  Asm
      ; Set up NVMCON for block erase operation
      Mov #0x4042, W0 ;
      Mov W0, NVMCON ; Initialize NVMCON
      ; Init pointer to row to be ERASED
      Mov MCU_Code_Erase_Page, W0 ;
      Mov W0, TBLPAG ; Initialize PM Page Boundary SFR
      Mov MCU_Code_Erase_Offset, W0 ; Initialize in-page EA[15:0] pointer
      TblwtL W0, [W0] ; Set base address of erase block
      Disi #5 ; Block all interrupts with priority <7
      ; for next 5 instructions
      Mov #0x55, W0
      Mov W0, NVMKEY ; Write the 55 key
      Mov #0xAA, W1 ;
      Mov W1, NVMKEY ; Write the AA key
      Bset NVMCON, #15 ; Start the erase sequence
      Nop ; Insert two NOPs after the erase
      Nop ; command is asserted

  EndAsm
EndProc

$ifdef Debug_Enabled Then 
 
  Proc Debug_Number_Byte (Number As Byte)
    Dim Hundreds  As Byte
    Dim Tenths    As Byte
    Dim Singles  As Byte
   
    Hundreds = Number / 100
    Tenths = ( Number - Hundreds * 100 ) / 10
    Singles = Number - ( 100 * Hundreds ) - ( 10 * Tenths )
   
    U2TXREG = Hundreds + 48
    U2TXREG = Tenths + 48
    U2TXREG = Singles + 48
    U2TXREG = " "
  EndProc
 
  Proc Debug_Number_Word (Number As Word)
   
    Dim TentThousands As Byte
    Dim Thousands    As Byte
    Dim Hundreds      As Byte
    Dim Tenths        As Byte
    Dim Singles      As Byte
   
    TentThousands = Number / 10000
    Thousands    = Number - ( TentThousands * 10000 ) / 1000
    Hundreds      = Number - ( TentThousands * 10000 ) - ( Thousands * 1000 ) / 100
    Tenths        = Number - ( TentThousands * 10000 ) - ( Thousands * 1000 ) - ( Hundreds * 100 ) / 10
    Singles      = Number - ( TentThousands * 10000 ) - ( Thousands * 1000 ) - ( Hundreds * 100 ) - ( 10 * Tenths )
   
    U2TXREG = TentThousands + 48
    U2TXREG = Thousands    + 48
    U2TXREG = Hundreds      + 48
    U2TXREG = Tenths        + 48
    U2TXREG = Singles      + 48
    U2TXREG = " "
  EndProc
   
  Proc Delay_Ms ( Milli_Seconds As Word) ' Roughly +/- ... @ 32 mhz
    Dim Times As Word
    Dim Times2 As Word
 
    For Times = 1 To Milli_Seconds
      For Times2 = 1 To 8000
      Nop
      Nop
      Nop
      Next
    Next
   
  EndProc
$endif

Config FSEC    = BWRP_OFF, BSS_DISABLED, BSEN_OFF, GWRP_OFF, GSS_DISABLED, CWRP_OFF, CSS_DISABLED, AIVTDIS_OFF
Config FOSCSEL  = FNOSC_FRC, IESO_OFF
Config FOSC    = POSCMD_NONE, OSCIOFNC_ON, FCKSM_CSECMD, PLLKEN_ON, XTCFG_G0, XTBST_ENABLE
Config FWDT    = SWDTPS_PS2147483648, RCLKSEL_LPRC
Config FPOR    = BISTDIS_DISABLED
Config FICD    = ICS_PGD1, JTAGEN_OFF, NOBTSWP_DISABLED
Config FDMT    = DMTDIS_OFF
Config FDEVOPT  = 0xF8FF 'ALTI2C1_OFF, ALTI2C2_OFF, ALTI2C3_OFF, SMBEN_STANDARD, SPI2PIN_PPS
Config FALTREG  = CTXT1_OFF, CTXT2_OFF, CTXT3_OFF, CTXT4_OFF
Config FBOOT    = BTMODE_SINGLE