CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DSPIC33EP512GP502 -- PCD v5.115 compiler - Bootloader issue

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Marco27293



Joined: 09 May 2020
Posts: 128

View user's profile Send private message

DSPIC33EP512GP502 -- PCD v5.115 compiler - Bootloader issue
PostPosted: Thu Feb 20, 2025 1:55 pm     Reply with quote

Hi,
I'm using this bootloader code. It seems to work fine.
Code:

///////////////////////////////////////////////////////////////////////////
////                      EX_PCD_BOOTLOADER.C                          ////
////                                                                   ////
////  This program is an example standalone bootloader.                ////
////                                                                   ////
////  This program must be loaded into a target chip using a device    ////
////  programmer.  Afterwards this program may be used to load new     ////
////  versions of the application program.                             ////
////                                                                   ////
////  This bootloader is designed to detect a pushbutton low on reset. ////
////  It will then use the RS232 link to download a new program.       ////
////  Otherwise the application program is started.                    ////
////                                                                   ////
////  Use an RS232 link and the SIOW.EXE program to load a new HEX     ////
////  file into the target chip. See example EX_PCD_BOOTLOAD.C.        ////
////                                                                   ////
////  Uncomment the define BOOTLOADER_MODE2X to use an alternate       ////
////  bootloader that receives each line in the hex file twice and     ////
////  compares them before acknowledging the line and writing it to    ////
////  the target chip's memory.  This mode only works with the         ////
////  CCS_BOOTLOADER.exe program, add MODE2X to the command line to    ////
////  use this mode.                                                   ////
////                                                                   ////
////  The config bits will be write protected, in software, by the     ////
////  rom_modify() function.  To allow config bits to change then      ////
////  you need to #define ROM_WRITE_CAN_MODIFY_CONFIG_BITS             ////
////                                                                   ////
////  Depending on the PIC the bootloader is being built for or if     ////
////  changes are made to the code the bootloader may not fit in the   ////
////  program memory set a side for it by default for this example.    ////
////  If that happens the size set aside for the bootloader can be     ////
////  changed by defining LOADER_PAGES to the number of erase pages    ////
////  to set aside for it before the pcd_bootloader.h is included,     ////
////  this define must be made in both the bootloader and application  ////
////  programs for the bootloader to work correctly.                   ////
////                                                                   ////
////  This example will work with the PCD compiler.  Change the        ////
////  device, clock, push button, and RS232 pins for your hardware if  ////
////  needed.                                                          ////
///////////////////////////////////////////////////////////////////////////
////         (C) Copyright 1996,2021 Custom Computer Services          ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
////                                                                   ////
////                     http://www.ccsinfo.com                        ////
///////////////////////////////////////////////////////////////////////////

// see explanation above
//#define ROM_WRITE_CAN_MODIFY_CONFIG_BITS
#include <33EP512GP502.h>
#FUSES NOPROTECT                                                              // Allow a Programmer device (eg. Pickit) to read Microcontroller firmware
#FUSES NOIOL1WAY                                                              // Used to enable peripheral deselection (useful to reduce power-consumption )
#use delay(internal=20MHz,clock_out)

#define UART_2_TX           PIN_B11                                              // DsPIC UART2 TX
#define UART_2_RX           PIN_B12                                              // DsPIC UART2 RX
#PIN_SELECT U2TX=UART_2_TX
#PIN_SELECT U2RX=UART_2_RX
#use rs232(uart2,baud=115200,PARITY=N, BITS=8, ERRORS, stream=SPECTRUM)

#define _bootloader
#define BOOTLOADER_MODE2X
#define BOOTLOADER_STREAM SPECTRUM
#define LOADER_PAGES 5
#include <pcd_bootloader.h>
#include <loader_pcd.c>


void main(void)
{
   delay_ms(140); // wait for PLL
   char ans='0';
   do
   {
      ans=fgetc(SPECTRUM);
   }
   while(ans!='A'&&ans!='K'&&ans!='!');
   
   if(ans=='!')
   {
      fputc('!',SPECTRUM);
      load_program();
   }
   else if(ans=='K')
   {
      fputc('K',SPECTRUM);
   }
   goto_address(APPLICATION_START); // Salta all'applicazione se non deve entrare in modalità bootloader
}

#int_default
void isr(void)
{
   jump_to_isr(APPLICATION_ISR_START);
}

It seems to work fine, it loads correctly an application but I'm experiencing a strange issue related to INT_EXT1:
Code:

#INT_EXT1                                                                 
void MCP346_manager()
{
         
   switch(sample_num)
   {
      case 16384:
      {
         disable_interrupts(INT_EXT1);
         clear_interrupt(INT_EXT1);
            sample_num++;
      }
      break;
      
      default:
      {
         clear_interrupt(INT_EXT1);
            // 1. SPI Read ADC
         input_buffer[shift] = make16(spi_read(0xFF),spi_read(0xFF));
         // 2. Aggiorna l'indice del buffer circolare (utilizzando maschera per efficienza)
         shift = (shift + 1) & TAP_MASK;
         // 3. Aggiorna la somma parziale per il passo corrente
         switch(sample_num&7)
         {
            case 0:
            {
               acc_sum += _mul(fir[0],  input_buffer[(shift - 0) & TAP_MASK  ]);
               acc_sum += _mul(fir[1],  input_buffer[(shift - 1) & TAP_MASK ]);
               acc_sum += _mul(fir[2],  input_buffer[(shift - 2) & TAP_MASK ]);
               acc_sum += _mul(fir[3],  input_buffer[(shift - 3) & TAP_MASK ]);
            }
            break;
            case 1:
            {
                acc_sum += _mul(fir[4],  input_buffer[(shift - 4) & TAP_MASK ]);
               acc_sum += _mul(fir[5],  input_buffer[(shift - 5) & TAP_MASK ]);
               acc_sum += _mul(fir[6],  input_buffer[(shift - 6) & TAP_MASK ]);
               acc_sum += _mul(fir[7],  input_buffer[(shift - 7) & TAP_MASK ]);
            }
            break;
            case 2:
            {
                    acc_sum += _mul(fir[8],  input_buffer[(shift - 8) & TAP_MASK ]);
               acc_sum += _mul(fir[9],  input_buffer[(shift - 9) & TAP_MASK ]);
               acc_sum += _mul(fir[10], input_buffer[(shift - 10)& TAP_MASK ]);
               acc_sum += _mul(fir[11], input_buffer[(shift - 11)& TAP_MASK]);
            }
            break;
            case 3:
            {
               acc_sum += _mul(fir[12], input_buffer[(shift - 12)& TAP_MASK ]);
               acc_sum += _mul(fir[13], input_buffer[(shift - 13)& TAP_MASK ]);
               acc_sum += _mul(fir[14], input_buffer[(shift - 14)& TAP_MASK ]);
               acc_sum += _mul(fir[15], input_buffer[(shift - 15)& TAP_MASK ]);
            }
            break;
            case 4:
            {
                    acc_sum += _mul(fir[16], input_buffer[(shift - 16)& TAP_MASK ]);
               acc_sum += _mul(fir[17], input_buffer[(shift - 17)& TAP_MASK ]);
               acc_sum += _mul(fir[18], input_buffer[(shift - 18)& TAP_MASK ]);
               acc_sum += _mul(fir[19], input_buffer[(shift - 19)& TAP_MASK ]);
            }
            break;
            case 5:
            {
                    acc_sum += _mul(fir[20], input_buffer[(shift - 20)& TAP_MASK ]);
               acc_sum += _mul(fir[21], input_buffer[(shift - 21)& TAP_MASK ]);
               acc_sum += _mul(fir[22], input_buffer[(shift - 22)& TAP_MASK ]);
               acc_sum += _mul(fir[23], input_buffer[(shift - 23)& TAP_MASK ]);
            }
            break;
            case 6:
            {
                    acc_sum += _mul(fir[24], input_buffer[(shift - 24)& TAP_MASK ]);
               acc_sum += _mul(fir[25], input_buffer[(shift - 25)& TAP_MASK ]);
               acc_sum += _mul(fir[26], input_buffer[(shift - 26)& TAP_MASK ]);
               acc_sum += _mul(fir[27], input_buffer[(shift - 27)& TAP_MASK ]);
            }
            break;
            case 7:
            {
                    acc_sum += _mul(fir[28], input_buffer[(shift - 28)& TAP_MASK ]);
               acc_sum += _mul(fir[29], input_buffer[(shift - 29)& TAP_MASK ]);
               acc_sum += _mul(fir[30], input_buffer[(shift - 30)& TAP_MASK ]);
               acc_sum += _mul(fir[31], input_buffer[(shift - 31)& TAP_MASK ]);
   
               samples32[sample_num>>3] =(acc_sum);
               acc_sum = 0;
            }
            break;
         }
         // 4. Incrementa il contatore dei campioni acquisiti
         sample_num++;
      }
      break;
   }
}


This ISR is defined in the application.
It is used to sample and filter data from ADC connected to DSPIC via SPI1.
The problem is: when I execute the standalone application without bootloader all is fine and I'am able to sample data at the required Fsampling.
When the application is embedded with the bootloader part the isr still works but I reach exactly Fsampling/2.

The Fuses and clock for bootloader and application are the same:

Code:

#use delay(internal=20MHz,clock_out)

//From LST:

Configuration Fuses:
   Word  3L: FFCF   ICSP1 NOJTAG NODEBUG
          H: 0000 
   Word  4L: FFFF   NOALTI2C1 NOALTI2C2 WDTWIN_25%
          H: 0000 
   Word  5L: FF7F   WPOSTS16 WPRES128 PLLWAIT WINDIS NOWDT
          H: 0000 
   Word  6L: FFDF   NOPR NOOSCIO NOIOL1WAY
          H: 0000 
   Word  7L: FFF9   FRC_PLL IESO
          H: 0000 
   Word  8L: FFFF   NOWRT NOPROTECT
          H: 0000 
   Word  9L: FFFF 
          H: 0000 
   Word 10L: FFFF 
          H: 0000 


Could you help me to find the problem cause ?

The ADC is configured by this driver:

Code:

//-----------------------------MCP346x Driver.C-------------------------------//
#ifndef __MCP346_C
#define __MCP346_C

#include "MCP346.h"

//-----------------------------Foos Definitions-------------------------------//

//MCP346 Utility implemented via SPI
unsigned int16 MCP346_Spi_Util(unsigned int8 mode)
{   
   unsigned int8  MSB=0,LSB=0,LOCK=0,ADC_REG_CHECK=0,ADC_SETTING_SUM=0;
   
   output_bit(SPI1_PIN_SELECT,1);
   output_bit(SPI1_PIN_SELECT,0);
   
   switch(mode){

        case _full_reset:
         spi_read(0b01111000);         //full reset      
        break;
      
      case _start_adc:
         spi_read(0b01101000);         //start conversion   
        break;
      
      case _single_read:
         spi_read(0b01000001);         //Static Read ADCDATA register
         MSB=spi_read(0xFF);
         LSB=spi_read(0xFF);
         output_bit(SPI1_PIN_SELECT,1);
         return make16(MSB,LSB);
      break;
      
      case _read_lock:
         spi_read(0b01110101);         //read lock
         LOCK=spi_read(0xFF);
         output_bit(SPI1_PIN_SELECT,1);
         return (unsigned int16)(LOCK);
      break;
      
      case _config_lock:
         spi_read(0b01110110);         //Incremental write lock register
         spi_read(0xA5);
      break;
      
      case _config_adc:
          spi_read(0b01000110);         //Incremental write starting at 0x01 config0
         spi_read(0b11000010);         //Config0 external clock without output,Standby mode
         spi_read(0b00001000);         //Config1 MCLK
         spi_read(0b10101011);         //Config2
         spi_read(0b11000000);         //Config3, 16 bit format data
         spi_read(0b01110010);         //IRQ
         spi_read(0b00010000);         //MUX select channel CH1 - CH0
      break;   
      
      case _read_adc:
          spi_read(0b01000111);         //Incremental read starting at 0x01 config0
         ADC_REG_CHECK=spi_read(0xFF);         //Config0 external clock without output,Conversion mode
         ADC_REG_CHECK ^= 0b11000010;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         ADC_REG_CHECK=spi_read(0xFF);         //Config1 MCLK
         ADC_REG_CHECK ^= 0b00001000;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         ADC_REG_CHECK=spi_read(0xFF);         //Config2
         ADC_REG_CHECK ^= 0b10101011;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         ADC_REG_CHECK=spi_read(0xFF);         //Config3, 16 bit format data
         ADC_REG_CHECK ^= 0b11000000;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         ADC_REG_CHECK=spi_read(0xFF);         //IRQ
         ADC_REG_CHECK ^= 0b01110010;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         ADC_REG_CHECK=spi_read(0xFF);         //MUX select channel CH1 - CH0
         ADC_REG_CHECK ^= 0b00010000;
         ADC_SETTING_SUM+=ADC_REG_CHECK;
         output_bit(SPI1_PIN_SELECT,1);
         if(ADC_SETTING_SUM==0)
            return MCP_SUCCESS;
         else
            return MCP_FAILURE;
      break;   
    }
   
   output_bit(SPI1_PIN_SELECT,1);
   return MCP_SUCCESS;
}

//MCP346 Restart
void MCP346_Restart()
{
    delay_ms(50);
   MCP346_Spi_Util(_full_reset);
   delay_ms(50);
   do
   {
      MCP346_Spi_Util(_config_lock);
      delay_ms(50);
   }
   while(MCP346_Spi_Util(_read_lock) != MCP_LOCK);    
   delay_ms(50);
   do
   {
      MCP346_Spi_Util(_config_adc);
      delay_ms(50);
   }
   while(MCP346_Spi_Util(_read_adc) != MCP_SUCCESS);
   delay_ms(50);
   MCP346_Spi_Util(_start_adc);
}


#endif

Changing driver options I'am able to reach correct Fsampling, but WHY must be a mismatch in registers configurations between application standalone and Boootloader+application ?

Nothing changes in my code except for application:

#define LOADER_PAGES 5
#include <pcd_bootloader.h>

they are commented in standalone project...
Ttelmah



Joined: 11 Mar 2010
Posts: 19700

View user's profile Send private message

PostPosted: Fri Feb 21, 2025 3:53 am     Reply with quote

Hmm.
That is odd.
One comment, you don't need the clear_interrupt lines in your interrupt
handler. Unless you compile an interrupt with the setting 'NOCLEAR', the
interrupt is always cleared when the handler exits. So you are potentially
clearing the interrupt twice.
Your remark on the NOIOL1WAY setting is wrong. This is what allows
your main code to have #PIN_SELECT lines that work. The power control
options are separate to this.
Using the bootloader, adds a tiny extra delay in handling the interrupts.
This can be avoided on chips that support the alternate interrupt vector
table, by using this. Look at the AIVT bootloader and boatload examples.
Check that the fuse settings given by the compile when boot loading, match
those you get from the bootloader. You show one set, but not the other.
Are there any other interrupts in use?.
Just a silly thing to try. Compile both the bootloader and the application
with #OPT 0
There was a problem around your compiler version with the default
optimisation making some interrupts not work properly. I'm wondering
if you might be experiencing this.
Marco27293



Joined: 09 May 2020
Posts: 128

View user's profile Send private message

PostPosted: Fri Feb 21, 2025 6:16 am     Reply with quote

Thank you Ttelmah,
I'll try #OPT 0 ASAP.

Meanwhile some clarifications:
- Fuses match between bootloader and application (No change)
- No other interrupt required or used

I looked AIVT bootloader and bootload examples in pcd compiler folder.
But seems that chip dspic33ep512gp502 I'm using dors not supporto the required Fuses...

How can I use alternate interrupt Vector on this chip ?

Any workaround or fix ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19700

View user's profile Send private message

PostPosted: Fri Feb 21, 2025 7:39 am     Reply with quote

Unfortunately it looks like your chip does not support this.

As a coment, the interrupt handling with the bootloader present will have
one extra ijump instruction before being handled. Now you have several things
that could be optimised better, so these might make the difference.
Don't use a switch for handling the single first test. Just test if and else for
the other code. Get rid of the clear interrupts as already mentioned and
the handling speed will probably be as good.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group