|
|
View previous topic :: View next topic |
Author |
Message |
OA_mattm
Joined: 15 Feb 2017 Posts: 5
|
Example PCD bootloader doesn't work PIC 24 |
Posted: Wed Feb 15, 2017 2:05 pm |
|
|
PIC: 24FJ256GB206
CCS version:
IDE Version 5.062
PCD Version 5.062
I'm attempting to use the ex_pcd_bootloader.c program in PICC\Examples and no matter what I try, my application will not start.
I can confirm that the load_program() function in loader_pcd.c is in-fact receiving and properly parsing the application hex because of some debugging printf()s I put in; however, I don't know how to confirm that it is properly writing it to the flash. The only symptom is that I cannot get the application to start.
Is the bootloader perhaps loading the wrong start address for my application, and that's why my application won't start?
Here is my source code for the bootloader:
Code: |
//#define DSPIC33FJ
//#define DSPIC30F
//#define PIC24FJ
#define PIC24FJ_REV2
//#define PIC24HJ
//#define PIC24EP
#if defined(DSPIC33FJ)
#include <33FJ128GP706.h>
#fuses NOWDT
#use delay(crystal=12MHz)
#use rs232(BAUD=9600,UART2,errors)
#define PUSH_BUTTON PIN_B2
#elif defined(DSPIC30F)
#include <30F4012.h>
#fuses NOWDT
#use delay(crystal=20M)
#use rs232(BAUD=9600,UART1A,errors)
#define PUSH_BUTTON PIN_B1
#elif defined(PIC24FJ)
#include <24FJ128GA006.h>
#fuses NOWDT
#use delay(crystal=20MHz)
#use rs232(BAUD=9600,UART1,errors)
#define PUSH_BUTTON PIN_F6
#elif defined(PIC24FJ_REV2)
#include <24FJ256GB206.h>
#fuses NOWDT
#use delay(internal=32000000)
#pin_select U1TX=PIN_D10
#pin_select U1RX=PIN_D11
#use rs232(UART1, baud=115200, stream=STREAM_CONTROL,ERRORS,DISABLE_INTS)
//#use rs232(BAUD=9600,UART1,errors)
#define PUSH_BUTTON PIN_E0
#elif defined(PIC24HJ)
#include <24HJ128GP306.h>
#fuses NOWDT
#use delay(crystal=20MHz)
#use rs232(Baud=9600,UART1,errors)
#define PUSH_BUTTON PIN_F6
#elif defined(PIC24EP)
#include <24ep256gp206.h>
#fuses NOWDT
#use delay(crystal=20MHz)
#pin_select U1TX = PIN_A4
#pin_select U1RX = PIN_A9
#use rs232(Baud=9600,UART1,errors)
#define PUSH_BUTTON PIN_C3
#endif
#define _bootloader
//#define BOOTLOADER_MODE2X
#include <pcd_bootloader.h>
#include "loader_pcd.c"
#org APPLICATION_START
void application(void)
{
while(TRUE);
}
void main(void)
{
int inchar = 0;
fprintf(STREAM_CONTROL, "P\r\n");
inchar = fgetc(STREAM_CONTROL);
if(inchar == 'U')
{
delay_ms(140); // wait for PLL
// Let the user know it is ready to accept a download
fprintf(STREAM_CONTROL, "W\r\n");
// Load the program
load_program();
}
else
{
fprintf(STREAM_CONTROL, "X\r\n");
application();
}
}
#int_default
void isr(void)
{
jump_to_isr(LOADER_END+5);
}
|
Here is the source for the application I am trying to load:
Code: |
#include <24FJ256GB206.h>
#device ADC=10
#fuses FRC_PLL, NOWDT, PROTECT,OSCIO
#use delay(internal=32000000)
#pin_select U1TX=PIN_D10
#pin_select U1RX=PIN_D11
#use rs232(UART1, baud=115200, stream=STREAM_CONTROL,ERRORS,DISABLE_INTS)
#include <stdio.h>
void main()
{
fprintf(STREAM_CONTROL, "Starting\r\n");
while (1)
{
delay_ms(1000);
fprintf(STREAM_CONTROL, "Looping\r\n");
}
}
|
and here is the compiled hex for my dummy application:
Code: |
:080000003E02040000000000B4
:100400005420EF00C3202000008041001040BA00BB
:100410000160EF00000006005374000061720000EC
:10042000746900006E6700000D0A00000000000003
:100430005420EF0043222000008041001040BA0009
:100440000160EF00000006004C6F00006F700000BC
:10045000696E0000670D00000A0000000000E00067
:100460004220AF00040037007B3E0900000000007E
:100470000000E900FCFF3A00000006000FF827002A
:10048000F0FF270020A0B7000000000081E0A800D6
:100490000600FC0021742000620420007305200087
:1004A000824878008348780042C7A900C0F0230042
:1004B000A4A6B70000302000C2A6B7000600FC00CA
:1004C0002174200062042000730520008248780017
:1004D0008348780042C7A80004022000243A88001C
:1004E0000028EF00040028000411880004402000C8
:1004F000141188002062A800240220004411880002
:10050000E224EF00E424EF00E624EF00EA24EF0009
:10051000EC24EF000228EF00010020000100780029
:100520000160EF0000020200000000008100E8000E
:100530002322AF00FEFF370024A2B7009000200066
:100540000008E600F5FF3700803E20002E02020082
:100550000000000001002000010078000160EF00B1
:1005600018020200000000008100E8002322AF0012
:10057000FEFF370024A2B700800020000008E6003C
:10058000F5FF3700A4020400000000000040FE0058
:020000040005F5
:1057F000FFFF00FFFFFC00FFD39900FF7F1F00FFAA
:00000001FF
;PIC24FJ256GB206
;CRC=092E CREATED="14-Feb-17 17:17"
|
I also wrote the following python code for sending the application from my computer to the PIC:
Code: |
import serial
import time
import sys
import string
ser = serial.Serial('COM20', 115200, timeout=0)
f = open("test.hex", "r")
mylist = []
lines = f.readlines()
f.close()
for i in range(len(lines)):
mylist.append(lines[i].replace('\n', '\r'))
lines = mylist
print(lines)
time.sleep(1)
for line in lines:
if line[0] == ':':
ser.write(line)
time.sleep(0.05)
response = ser.read(64)
print(response)
ser.close()
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Wed Feb 15, 2017 2:58 pm |
|
|
I might be just missing it, but I don't see where you included the bootloader header in your application code. The bootloader code correctly has it, but I don't see it in the application. That file is necessary in both the bootloader and the application file so that memory is properly placed.
Did you try the example file for the bootloader in the example's directory? |
|
|
OA_mattm
Joined: 15 Feb 2017 Posts: 5
|
|
Posted: Wed Feb 15, 2017 3:50 pm |
|
|
jeremiah wrote: | I might be just missing it, but I don't see where you included the bootloader header in your application code. The bootloader code correctly has it, but I don't see it in the application. That file is necessary in both the bootloader and the application file so that memory is properly placed.
Did you try the example file for the bootloader in the example's directory? |
I knew it was something simple. You are correct, I did not include it in the application code. Now my application loads correctly
Here is the new application code:
Code: |
#include <24FJ256GB206.h>
#device ADC=10
#fuses FRC_PLL, NOWDT, PROTECT,OSCIO
#use delay(internal=32000000)
#pin_select U1TX=PIN_D10
#pin_select U1RX=PIN_D11
#use rs232(UART1, baud=115200, stream=STREAM_CONTROL,ERRORS,DISABLE_INTS)
#include <stdio.h>
#include <pcd_bootloader.h>
void main()
{
fprintf(STREAM_CONTROL, "Starting\r\n");
while (1)
{
delay_ms(1000);
fprintf(STREAM_CONTROL, "Looping\r\n");
}
}
|
And the new application hex file:
Code: |
:081000003A0A040000000000A0
:0813F8005420EF0083A0200047
:10140000008041001040BA000160EF0000000600BB
:101410005374000061720000746900006E67000080
:101420000D0A0000000000005420EF0003A220007D
:10143000008041001040BA000160EF00000006008B
:101440004C6F00006F700000696E0000670D0000B7
:101450000A0000000000E0004220AF000400370056
:101460007B3E0900000000000000E900FCFF3A009C
:10147000000006000FF82700F0FF270020A0B700AB
:101480000000000081E0A8000600FC00217420009C
:1014900062042000730520008248780083487800A9
:1014A00042C7A900C0F02300A4A6B7000030200066
:1014B000C2A6B7000600FC002174200062042000D0
:1014C00073052000824878008348780042C7A8004E
:1014D00004022000243A88000028EF0004002800BD
:1014E0000411880004402000141188002062A80024
:1014F0002402200044118800E224EF00E424EF00DD
:10150000E624EF00EA24EF00EC24EF000228EF00CD
:1015100001002000010078000160EF00FC090200DA
:10152000000000008100E8002322AF00FEFF37002A
:1015300024A2B700900020000008E600F5FF370065
:10154000803E20002A0A0200000000000100200066
:10155000010078000160EF00140A020000000000A2
:101560008100E8002322AF00FEFF370024A2B7006D
:10157000800020000008E600F5FF3700A00A040004
:08158000000000000040FE0025
:020000040005F5
:1057F000FFFF00FFFFFC00FFD39900FF7F1F00FFAA
:00000001FF
;PIC24FJ256GB206
;CRC=28F4 CREATED="15-Feb-17 13:39"
|
|
|
|
OA_mattm
Joined: 15 Feb 2017 Posts: 5
|
|
Posted: Wed Feb 15, 2017 4:26 pm |
|
|
Actually now, in my actual application (not just the dummy application that I posted to get the bootloader working), none of my interrupts work. Do I need to modify the linker scripts to get that going? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1345
|
|
Posted: Wed Feb 15, 2017 4:35 pm |
|
|
Can you whittle it down to a small example application (That is compilable) where an interrupt doesn't work? Just a basic main with one interrupt. Verify that doesn't work and post the code.
Theoretically, the contents of pcd_bootloader.h and your #int_default in the bootloader should handle the interrupts, assuming you haven't modified them in an odd way. |
|
|
OA_mattm
Joined: 15 Feb 2017 Posts: 5
|
|
Posted: Wed Feb 15, 2017 4:56 pm |
|
|
jeremiah wrote: | Can you whittle it down to a small example application (That is compilable) where an interrupt doesn't work? Just a basic main with one interrupt. Verify that doesn't work and post the code.
Theoretically, the contents of pcd_bootloader.h and your #int_default in the bootloader should handle the interrupts, assuming you haven't modified them in an odd way. |
This is a very heavily boiled down version of my application that I have confirmed does not have working interrupts when put in through the bootloader, but still prints "Starting Program" at the beginning just fine.
Code: |
#include <24FJ256GB206.h>
#device ADC=10
//#fuses FRC_PLL, WDT, PROTECT,OSCIO,
#fuses FRC_PLL, NOWDT, PROTECT,OSCIO,
//#fuses NOWDT, NOPROTECT,OSCIO,
#use delay(internal=32000000)
#pin_select U1TX=PIN_D10
#pin_select U1RX=PIN_D11
//#use rs232(baud=38400, UART1,PARITY=N,BITS=8,)
#use rs232(UART1, baud=115200, stream=STREAM_CONTROL,ERRORS,DISABLE_INTS)
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <pcd_bootloader.h>
//These buffers must be volatile to prevent the compiler from possibly optimizing out the memset() calls in main()
volatile char RawCommand[64]; ///< The raw, unprocessed command recieved from the UART
volatile char ProcessCommand[64]; ///< The command that is to be processed in CommandProcess()
volatile int inchar = 0; ///< Temporary variable for storing the latest character recieved from the UART
int charptr = 0; ///< Variable for keeping track of the number of characters in the RawCommand[] array
int CommandReceived = 0; ///< Flag to indicate if a command has been recieved over serial. SerialInputISR() sets this flag, and main() clears it.
/**
* @brief Interrupt service routine for serial input
*/
#int_RDA
void SerialInputISR()
{
//Get the latest character from the command input UART
inchar = fgetc(STREAM_CONTROL);
//Copy that character to the next spot in the command input
RawCommand[charptr] = (char) inchar & 0xFF;
//If a carriage return is detected, then we know we are at the end of the command
if (inchar == 13) {
//End of command, copy RawCommand to ProcessCommand to be processed in CommandProcess
strncpy(ProcessCommand, RawCommand, charptr);
CommandReceived=1;
charptr = 0;
return;
}
//Increment the count of the number of recieved characters
charptr++;
//Impose an artificial limit of 64 characters on the command
if (charptr > 63) {
charptr = 0;
}
return;
}
/**
* @brief Processes a command recieved in the SerialInputISR().
*
* When a command is recieved from UART1, it is copied to the gobal variable ProcessCommand
* This function parses the command in the ProcessCommand variable, and takes the appropriate
* action according to the command.
*/
void CommandProcess(void)
{
char stest[10];
char* locptr;
//Test for a query command
strcpy(stest, "$Q");
locptr = strstr(ProcessCommand, stest);
if (locptr > 0) {
fprintf(STREAM_CONTROL, "Query command detected\r\n");
return;
} //end $Q if statement
//Catch-all for an unrecognized command
fprintf(STREAM_CONTROL, "Illegal Command $RLY [%s]\r\n", ProcessCommand);
}
void main()
{
fprintf(STREAM_CONTROL, "Starting Program");
//Enable serial interrupt
enable_interrupts(INT_RDA);
enable_interrupts(INTR_GLOBAL);
//Zero the ProcessCommand and RawCommand buffers
memset(ProcessCommand, 0x00, sizeof(ProcessCommand));
memset(RawCommand, 0x00, sizeof(RawCommand));
//Infinite loop, do this forever
while (1) {
//Check to see if we've recieved a command from the RDA interrupt
if (CommandReceived == 1) {
CommandReceived = 0;
CommandProcess();
//Zero the ProcessCommand and RawCommand buffers
memset(ProcessCommand, 0x00, sizeof(ProcessCommand));
memset(RawCommand, 0x00, sizeof(RawCommand));
} //end CommandReceived if statement
} //end while (1)
} //end main()
|
|
|
|
OA_mattm
Joined: 15 Feb 2017 Posts: 5
|
|
Posted: Wed Feb 15, 2017 5:16 pm |
|
|
Actually, nevermind. Sorry to waste your time. My interrupts are working now with the exact code I posted. I made a change to the bootloader as an experiment and forgot to change it back.
You have been extremely helpful. My boss will be very happy we have this working now. |
|
|
|
|
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
|