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

dsPIC30F6014A PCD Bootloader OK and App FW with No Interrupt

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



Joined: 14 Nov 2019
Posts: 11

View user's profile Send private message

dsPIC30F6014A PCD Bootloader OK and App FW with No Interrupt
PostPosted: Thu Nov 14, 2019 1:52 am     Reply with quote

I uploaded the boot loader FW and downloaded a simple application as shown below.
The result is that the normal functioning works fine, but the timer and RS232 receive interrupts do not.

Why not do interrupts?

Thank you for your help.

Please note that the bootloader code could not be attached due to many modifications.

Simple application code
Code:
#include <30F6014A.h>

/*-*-*-*-*-*-*-*-*-* preprocessor *-*-*-*-*-*-*-*-*-*-*-*-/
#fuses HS, NOWDT, NOPROTECT
#use delay(crystal = 30Mhz)
#use rs232(UART1, baud=115200, stop=1, parity=N, xmit=PIN_F3, rcv=PIN_F2, bits=8, stream=DBG_PINF3F2) 
#use rs232(UART2, baud=115200, stop=1, parity=N, xmit=PIN_F5, rcv=PIN_F4, bits=8, stream=HMI_PINF5F4) 

// "Same with LOADER_PAGES of bootloader FW"
#define LOADER_PAGES 81
#include <pcd_bootloader.h>

#define OP_LED   PIN_D12

unsigned int32 HMIBuf_Num = 0;
unsigned int8 HMI_STX_Buf[200];
unsigned int32 Timer_100ms_Count = 0;

#INT_RDA2
void HMI_Uart2_Rx_isr(void)
{
   HMI_STX_Buf[HMIBuf_Num] = getc(HMI_PINF5F4);
   HMIBuf_Num++;
   if (HMIBuf_Num >= 200) HMIBuf_Num = 0;
}


#INT_TIMER2
void  TIMER2_isr(void)
{                     
    Timer_100ms_Count++;
}


/*******************************************************
* Function: void main()
* Description: main
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-/
void main()
{
   unsigned int32 ret = 0;
   unsigned int32 tmp_Num = 5;
   

   fprintf(DBG_PINF3F2, "\r\nSimpleApplication #1");
   fprintf(DBG_PINF3F2, "\r\nSo enjoy!");

      ret = getenv("PROGRAM_MEMORY");
      fprintf(DBG_PINF3F2, "\r\nPROGRAM_MEMORY:0x%x", ret);
      ret = getenv("FLASH_ERASE_SIZE");
      fprintf(DBG_PINF3F2, "\r\nFLASH_ERASE_SIZE:0x%x", ret);
      ret = getenv("FLASH_WRITE_SIZE");
      fprintf(DBG_PINF3F2, "\r\nFLASH_WRITE_SIZE:0x%x", ret);
      ret = getenv("READ_PROGRAM");
      fprintf(DBG_PINF3F2, "\r\nREAD_PROGRAM:0x%x", ret);
      fprintf(DBG_PINF3F2, "\r\nLOADER_END:0x%x", LOADER_END);
      fprintf(DBG_PINF3F2, "\r\nLOADER_SIZE:0x%x", LOADER_SIZE);
      fprintf(DBG_PINF3F2, "\r\nLOADER_ADDR:0x%x", LOADER_ADDR);
#ifdef BOOTLOADER_AT_START
      fprintf(DBG_PINF3F2, "\r\nBOOTLOADER_AT_START defined");
#else
      fprintf(DBG_PINF3F2, "\r\nBOOTLOADER_AT_START No defined");
#endif

   setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 11718);
   enable_interrupts(INT_TIMER2);
   
   enable_interrupts(INT_RDA2);
   enable_interrupts(INTR_GLOBAL);

   while(TRUE)
   {
      if (tmp_Num != HMIBuf_Num)
      {
         fprintf(DBG_PINF3F2, "Timer1:%u\r\n", Timer_100ms_Count);
         tmp_Num = HMIBuf_Num;
         Timer_100ms_Count = 0;
      }
      else if (Timer_100ms_Count > 10)
      {
         fprintf(DBG_PINF3F2, "Timer2:%u\r\n", Timer_100ms_Count);
         if (HMIBuf_Num)
         {
            for (ret = 0; ret < HMIBuf_Num; ret++)
            {
              fprintf(DBG_PINF3F2, "Rx[%u]:0x%x\r\n", ret, HMI_STX_Buf[ret]);
            }
         }
         Timer_100ms_Count = 0;
      }
      output_toggle(OP_LED);
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Nov 14, 2019 5:09 am     Reply with quote

The fault is almost certainly that your bootloader is not correctly re-vectoring
the interrupt handling. So it is the bootloader you need to post....
benedictkim



Joined: 14 Nov 2019
Posts: 11

View user's profile Send private message

PostPosted: Thu Nov 14, 2019 6:50 pm     Reply with quote

Below is the bootloader code.
The boot loader is very complicated.
However, the download is normal and the default operation is not abnormal except for interrupt.
Please treat me well.
Thank you.

Ttelmah! thank you.
Three bootloaders / application firmware / final firmware hex files were compared.
Vertor has detected a problem with the bootloader 0x0 address and the application firmware 0x0980 address.
PCB_Bootloader did not fix it.
Where is the problem?


Code:

#include <30F6014A.h>
#include "main.h"


/******************** preprocessor ***********************/
//#fuses NOWRTB                        // OK
//#fuses HS, NOWDT, NOPROTECT, NOWRT   // OK
//#use delay(crystal = 30Mhz)
#fuses HS, NOWDT, NOPROTECT             // OK
#use delay(crystal = 30Mhz)
//#fuses NOWDT                          // OK
//#use delay(crystal = 30Mhz)

#use rs232(UART1, baud=115200, stop=1, parity=N, xmit=PIN_F3, rcv=PIN_F2, bits=8, stream=DBG_PINF3F2) 
//#use rs232(UART1, baud=115200, stop=1, parity=N, xmit=PIN_F3, rcv=PIN_F2, bits=8, timeout=10000, stream=RS232_PINF3F2) 
#use rs232(UART2, baud=115200, stop=1, parity=N, xmit=PIN_F5, rcv=PIN_F4, bits=8, stream=HMI_PINF5F4) 


/********************** define ***************************/
#define READ_BOOT_INFO   1
#define ERASE_FLASH      2
#define PROGRAM_FLASH   3
#define READ_CRC      4
#define JMP_TO_APP      5


// Data EEPROM address 0x30 status value
#define TO_APP_FW_MODE   0x41   // to application FW
 

// IO pin
#define S_SW1            PIN_G13   

// Don't touch - Fixed position
#define _bootloader
// "Same with LOADER_PAGES of application FW"
#define LOADER_PAGES 81
#include <pcd_bootloader.h>


#define APP_FLASH_BASE_ADDRESS      (LOADER_PAGES * (getenv("FLASH_ERASE_SIZE")/2))
#define APP_FLASH_END_ADDRESS         getenv("PROGRAM_MEMORY")
#define FLASH_PAGE_SIZE                  getenv("FLASH_ERASE_SIZE")


#define MAJOR_VERSION 1
#define MINOR_VERSION 0


/********************* global ****************************/
const unsigned int8 BootInfo[2] =
{
   MAJOR_VERSION,
   MINOR_VERSION
};

T_FRAME RxBuff;
T_FRAME TxBuff;

unsigned int32 Timer_100ms_Count = 0;
unsigned int1 RunApplication = FALSE;
unsigned int1 RxFrameValid = FALSE;
unsigned int16 Reply_Data_Length = 0;


/****************************************************************************
* Static table used for the table_driven implementation.
*****************************************************************************/
const unsigned int16 crc_table[16] =
{
   0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
   0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
};


/*******************************************************
* Function: void isr(void)
* Description: interrupt service routine for jump
*                    to the Applicatoin IVT
********************************************************/
#int_default
void isr(void)
{
   jump_to_isr(LOADER_END+5);
}


/*******************************************************
* Function: void main()
* Description: Jump to application FW
********************************************************/
#org LOADER_END+1,LOADER_END+5
void application(void)
{
   while(TRUE);
}


/*******************************************************
* Function: unsigned int16 CalculateCrc(unsigned int8 *data, unsigned int32 len)
* Description:  Calculates CRC for the given data and len
* Parameter: data pointer and data length
* Return: CRC
********************************************************/
unsigned int16 CalculateCrc(unsigned int8 *data, unsigned int32 len)
{
   unsigned int32 i;
   unsigned int16 crc = 0;

   while(len--)
   {
      i = (crc >> 12) ^ ((unsigned int16)*data >> 4);
      crc = crc_table[i & 0x0F] ^ (crc << 4);
      i = (crc >> 12) ^ ((unsigned int16)*data >> 0);
      crc = crc_table[i & 0x0F] ^ (crc << 4);
      data++;
   }
   return (crc & 0xFFFF);
}


/*******************************************************
* Function: void EraseFlash(void)
* Description: Erases Flash (Block Erase).
********************************************************/
void EraseFlash(void)
{
   unsigned int32 i;

   for (i = 0; i <= ((APP_FLASH_END_ADDRESS - APP_FLASH_BASE_ADDRESS)/FLASH_PAGE_SIZE); i++)
   {
      erase_program_memory(APP_FLASH_BASE_ADDRESS + (i*FLASH_PAGE_SIZE));
   }
}


/*******************************************************
* Function: unsigned int1 ExitFirmwareUpgradeMode(void)
* Description: This function returns true if firmware mode has to be exited.
********************************************************/
unsigned int1 ExitFirmwareUpgradeMode(void)
{
   static unsigned int16 buff_len = 0;
   
   if (buff_len != RxBuff.Len)
   {
      buff_len = RxBuff.Len;
      Timer_100ms_Count = 0;     
   }
   else if (Timer_100ms_Count > 100)
   {
      fprintf(DBG_PINF3F2, "RS232 Timeout\r\n");
      RunApplication = TRUE;
   }
   return RunApplication;
}


/*******************************************************
* Function: void WriteHexRecord2Flash_UART(unsigned int8* HexRecord, unsigned int16 totalHexRecLen)
* Description: Writes hex record to flash.
* Parameter: HexRecord buffer.
********************************************************/
void WriteHexRecord2Flash_UART(unsigned int8* HexRecord, unsigned int16 totalHexRecLen)
{
   static unsigned int16 h_addr = 0;

   unsigned int32 addr;
   unsigned int16 l_addr;
   unsigned int16 data_count=0;
   unsigned int16 total_count=0;
   unsigned int16  checksum_index;
   unsigned int8  data[32];
   unsigned int8  checksum, line_type;
   unsigned int8  dataidx, i;

   while(totalHexRecLen>=5) // A hex record must be atleast 5 bytes. (1 Data Len byte + 1 rec type byte+ 2 address bytes + 1 crc)
   {
      data_count = HexRecord[0 + total_count];  // Get the number of bytes from the HexRecord
      checksum_index = 1+ 2 + 1+ data_count;

      // Get the lower 16 bits of address
      l_addr = make16(HexRecord[1 + total_count], HexRecord[2 + total_count]);

      line_type = HexRecord[3 + total_count];
      addr = ((make32(h_addr,l_addr))/2);

      checksum = 0;  // Sum the bytes to find the check sum value
      for (i=0; i<(checksum_index); i++) checksum += HexRecord[i + total_count];
      checksum = 0xFF - checksum + 1;

      if (checksum != HexRecord[checksum_index + total_count])
      {
         // Checksum error
      }
      else
      {
         // If the line type is 1, then data is done being sent
         if (line_type == 1) return;
         else if (line_type == 4) h_addr = make16(HexRecord[4 + total_count], HexRecord[5 + total_count]);
         else if (line_type == 0)
         {
            if (((addr < LOADER_ADDR) || (addr > LOADER_END)) && addr < getenv("PROGRAM_MEMORY"))
            {        // Loops through all of the data and stores it in data
                     // The last 2 bytes are the check sum, hence buffidx-3
               for (i = 4,dataidx=0; i < checksum_index; i++)
               {
                  data[dataidx++] = HexRecord[i + total_count];
               }
               write_program_memory(addr, data, data_count);
            }
         }
         totalHexRecLen = totalHexRecLen - (data_count + 5);
         total_count += data_count + 5;
      }
   }
}


/*******************************************************
* Function: void HandleCommand(void)
* Description: Process the received frame and take action depending on
            the command received.
********************************************************/
void HandleCommand(void)
{
   DWORD_VAL Address;
   DWORD_VAL Length;
   WORD_VAL crc;
   unsigned int32 i;
   unsigned int8 Cmd;
   void* pFlash;

   // First byte of the data field is command.
   Cmd = RxBuff.Data[0];
   // Partially build response frame. First byte in the data field carries command.
   TxBuff.Data[0] = RxBuff.Data[0];

   // Process the command.
   switch(Cmd)
   {
      case READ_BOOT_INFO: // Read boot loader version info.
         memcpy(&TxBuff.Data[1], BootInfo, 2);
         //Set the transmit frame length.
         Reply_Data_Length = 2 + 1; // Boot Info Fields + command
         break;
      case ERASE_FLASH:
         pFlash = (void*)APP_FLASH_BASE_ADDRESS;
         for( i = 0; i <= ((APP_FLASH_END_ADDRESS - APP_FLASH_BASE_ADDRESS)/FLASH_PAGE_SIZE); i++ )
         {
            erase_program_memory(APP_FLASH_BASE_ADDRESS + (i*FLASH_PAGE_SIZE));
         }
         //Set the transmit frame length.
         Reply_Data_Length = 1; // Command
         break;
      case PROGRAM_FLASH:
         WriteHexRecord2Flash_UART(&RxBuff.Data[1], RxBuff.Len-3);   //Negate length of command and CRC RxBuff.Len.
         //Set the transmit frame length.
         Reply_Data_Length = 1; // Command
         break;
      case READ_CRC:
         // Get address from the packet.
         memcpy(&Address.v[0], &RxBuff.Data[1], sizeof(Address.Val));
         memcpy(&Length.v[0], &RxBuff.Data[5], sizeof(Length.Val));
         crc.Val = CalculateCrc((unsigned int8 *)Address.Val, Length.Val);
         memcpy(&TxBuff.Data[1], &crc.v[0], 2);

         //Set the transmit frame length.
         Reply_Data_Length = 1 + 2;   // Command + 2 bytes of CRC.
         break;
      case JMP_TO_APP:
         write_eeprom(0x30, TO_APP_FW_MODE);
         // Exit firmware upgrade mode.
         RunApplication = TRUE;
         break;
      default:
         // Nothing to do.
         break;
   }   
}


/*******************************************************
* Function: void FrameWorkTask(void)
* Description: Process the command if there is a valid fame.
********************************************************/
void FrameWorkTask(void)
{
   WORD_VAL crc;

   if(RxFrameValid)
   {
      crc.bytes.LB = RxBuff.Data[RxBuff.Len-2];
      crc.bytes.HB = RxBuff.Data[RxBuff.Len-1];
      if((CalculateCrc(RxBuff.Data, (unsigned int32)(RxBuff.Len-2)) == crc.Val) && (RxBuff.Len > 2))
      {
         // CRC matches and frame received is valid.
      }
      else return;

      // Valid frame received, process the command.
      HandleCommand();
      // Reset the flag.
      RxFrameValid = FALSE;
   }       
}


/*******************************************************
* Function: void GetTransmitFrame(void)
* Description: Gets the complete transmit frame into the "Buff".
* Return: Length of the buffer.
* Parameter: Buffer pointer.
********************************************************/
void GetTransmitFrame(void)
{
   WORD_VAL crc;
   unsigned int8 tmp_buff[255];
   unsigned int32 i;

   //There is something to transmit.
   // Calculate CRC of the frame.
   crc.Val = CalculateCrc(TxBuff.Data, (unsigned int32)Reply_Data_Length);
   TxBuff.Data[Reply_Data_Length++] = crc.bytes.LB;
   TxBuff.Data[Reply_Data_Length++] = crc.bytes.HB;

   memcpy(tmp_buff, TxBuff.Data, Reply_Data_Length);

   // Insert SOH (Indicates beginning of the frame)
   TxBuff.Data[TxBuff.Len++] = SOH;

   // Insert Data Link Escape Character.
   for(i = 0; i < Reply_Data_Length; i++)
   {
      if((tmp_buff[i] == EOT) || (tmp_buff[i] == SOH) || (tmp_buff[i] == DLE))
      {
         // EOT/SOH/DLE repeated in the data field, insert DLE.
         TxBuff.Data[TxBuff.Len++] = DLE;
      }
      TxBuff.Data[TxBuff.Len++] = tmp_buff[i];
   }

   // Mark end of frame with EOT.
   TxBuff.Data[TxBuff.Len++] = EOT;
   Reply_Data_Length = 0; // Purge this buffer, no more required.
}


/*******************************************************
* Function: void HMI_Uart2_Tx_isr(void)
* Description:  UART 2 Tx interrupt service routine for HMI
********************************************************/
#INT_TBE2
void HMI_Uart2_Tx_isr(void)
{
   static unsigned int16 tx_index = 0;

   putc(TxBuff.Data[tx_index++], HMI_PINF5F4);
   if (tx_index >= TxBuff.Len)
   {
      tx_index = TxBuff.Len = 0;
      disable_interrupts(INT_TBE2);
   }
   else enable_interrupts(INT_TBE2);
}


/*******************************************************
* Function: void UartTxTask(void)
* Description: Runs some UART routines like receive bytes and transmit bytes.
********************************************************/
void UartTxTask(void)
{
   if(Reply_Data_Length)
   {
      // Get transmit frame from frame work.
      GetTransmitFrame();
      enable_interrupts(INT_TBE2);
   }
}


/*******************************************************
* Function: void HMI_Uart2_Rx_isr(void)
* Description: interrupt service routine for jump
*                    to the Applicatoin IVT
********************************************************/
#INT_RDA2
void HMI_Uart2_Rx_isr(void)
{
   static unsigned int1 Escape = FALSE;
   unsigned int8 ch;

   ch = getc(HMI_PINF5F4);
   if(RxBuff.Len >= sizeof(RxBuff.Data)) RxBuff.Len = 0;

   switch(ch)
   {
      case SOH: //Start of header
         if(Escape)
         {
            // Received byte is not SOH, but data.
            RxBuff.Data[RxBuff.Len++] = ch;
            // Reset Escape Flag.
            Escape = FALSE;
         }
         // Received byte is indeed a SOH which indicates start of new frame.
         else RxBuff.Len = 0;
         break;
      case EOT: // End of transmission
         if(Escape)
         {
            // Received byte is not EOT, but data.
            RxBuff.Data[RxBuff.Len++] = ch;
            // Reset Escape Flag.
            Escape = FALSE;
         }
         else
         {
            // Received byte is indeed a EOT which indicates end of frame.
            // Calculate CRC to check the validity of the frame.
            if(RxBuff.Len > 1) RxFrameValid = TRUE;
         }
         break;
      case DLE: // Escape character received.
         if(Escape)
         {
            // Received byte is not ESC but data.
            RxBuff.Data[RxBuff.Len++] = ch;
            // Reset Escape Flag.
            Escape = FALSE;
         }
         // Received byte is an escape character. Set Escape flag to escape next byte.
         else Escape = TRUE;
         break;
      default: // Data field.
         RxBuff.Data[RxBuff.Len++] = ch;
         // Reset Escape Flag.
         Escape = FALSE;
         break;
   }
}


/*******************************************************
* Function: void  TIMER2_isr(void)
* Description: Timer 2 interrupt routine - 100ms
********************************************************/
#INT_TIMER2
void  TIMER2_isr(void)
{                     
    Timer_100ms_Count++;
}


/*******************************************************
* Function: void main()
* Description: main
********************************************************/
void main()
{
   TxBuff.Len = 0;
   RxBuff.Len = 0;

//   fprintf(RS232_PINF3F2, "Start Bootloader\r\n");
//   delay_ms(1000);
   fprintf(DBG_PINF3F2, "Start Bootloader\r\n");
   delay_ms(1000);

/*
   ret = getenv("PROGRAM_MEMORY");
   fprintf(DBG_RS232_F5F4, "PROGRAM_MEMORY:0x%x\r\n", ret);
   ret = getenv("FLASH_ERASE_SIZE");
   fprintf(DBG_RS232_F5F4, "FLASH_ERASE_SIZE:0x%x\r\n", ret);
   ret = getenv("FLASH_WRITE_SIZE");
   fprintf(DBG_RS232_F5F4, "FLASH_WRITE_SIZE:0x%x\r\n", ret);
   ret = getenv("READ_PROGRAM");
   fprintf(DBG_RS232_F5F4, "READ_PROGRAM:0x%x\r\n", ret);
   fprintf(DBG_RS232_F5F4, "LOADER_END:0x%x\r\n", LOADER_END);
   fprintf(DBG_RS232_F5F4, "LOADER_SIZE:0x%x\r\n", LOADER_SIZE);
   fprintf(DBG_RS232_F5F4, "LOADER_ADDR:0x%x\r\n", LOADER_ADDR);
   fprintf(DBG_RS232_F5F4, "APP_FLASH_BASE_ADDRESS:0x%x\r\n", APP_FLASH_BASE_ADDRESS);
   fprintf(DBG_RS232_F5F4, "APP_FLASH_END_ADDRESS:0x%x\r\n", APP_FLASH_END_ADDRESS);
   fprintf(DBG_RS232_F5F4, "FLASH_PAGE_SIZE:0x%x\r\n", FLASH_PAGE_SIZE);
#ifdef BOOTLOADER_AT_START
   fprintf(DBG_RS232_F5F4, "BOOTLOADER_AT_START defined\r\n");
#else
   fprintf(DBG_RS232_F5F4, "BOOTLOADER_AT_START No defined\r\n");
#endif
*/

   setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 11718);
   enable_interrupts(INT_TIMER2);

   enable_interrupts(INT_RDA2);
   enable_interrupts(INTR_GLOBAL);

   if (read_eeprom(0x30) == TO_APP_FW_MODE)
   {
      fprintf(DBG_PINF3F2, "Download JumpToApp#1\r\n");
      fprintf(HMI_PINF5F4, "Download JumpToApp#1\r\n");
      application();
   }
   fprintf(DBG_PINF3F2, "EEPROM 0x30: 0x%x\r\n", read_eeprom(0x30));
   while(!ExitFirmwareUpgradeMode()) // Be in loop till framework recieves "run application" command from PC
   {
      // Enter firmware upgrade mode. Be in loop, looking for commands from PC
      FrameWorkTask();      // Run frame work related tasks (Handling Rx frame, process frame and so on)
      UartTxTask();         // Run Uart Tx tasks
   }
 
   fprintf(DBG_PINF3F2, "Download JumpToApp#2\r\n");
   fprintf(HMI_PINF5F4, "Download JumpToApp#2\r\n");
   application();
}
benedictkim



Joined: 14 Nov 2019
Posts: 11

View user's profile Send private message

PostPosted: Thu Nov 14, 2019 11:24 pm     Reply with quote

Interrupts were resolved by changing the order in the source phase.
Thank you.
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