From 5c2d710bc2bb3186ecee61e36303ef27b95dddd9 Mon Sep 17 00:00:00 2001 From: Boris Honman Date: Sun, 11 Aug 2019 21:39:11 -0400 Subject: [PATCH] kind of works for writing flash. IMPORTANT ISSUE - the memory usage output given by the linker for program size used DOES NOT equal the actual flash space used when programming. INVESTIGATE: did I set a memory space that doesn't lie on a page boundary? or do I just need to increase the flash space allocated to the bootloader --- .../nbproject/configurations.xml | 11 ++- bootloader/src/VectorRemap.asm | 35 +++++++++ bootloader/src/bootloader.c | 33 +++------ bootloader/src/bootloader.h | 3 - bootloader/src/main.c | 73 ++++++++++++++++--- common_src/memory.h | 37 ++++++++++ .../nbproject/configurations.xml | 14 ++-- firmware/src/main.c | 7 +- 8 files changed, 165 insertions(+), 48 deletions(-) create mode 100644 bootloader/src/VectorRemap.asm create mode 100644 common_src/memory.h diff --git a/bootloader/clubdance_v2_bootloader.X/nbproject/configurations.xml b/bootloader/clubdance_v2_bootloader.X/nbproject/configurations.xml index 114dc98..b5b21b5 100644 --- a/bootloader/clubdance_v2_bootloader.X/nbproject/configurations.xml +++ b/bootloader/clubdance_v2_bootloader.X/nbproject/configurations.xml @@ -20,6 +20,7 @@ ../../common_src/system.c + ../../common_src/memory.h ../src/usb_events.c ../src/main.c ../src/bootloader.c + ../src/VectorRemap.asm - - - - + + + + @@ -178,6 +180,7 @@ value="Press to browse for a specific firmware version"/> + diff --git a/bootloader/src/VectorRemap.asm b/bootloader/src/VectorRemap.asm new file mode 100644 index 0000000..ab932ba --- /dev/null +++ b/bootloader/src/VectorRemap.asm @@ -0,0 +1,35 @@ +;/******************************************************************************* +;Copyright 2016 Microchip Technology Inc. (www.microchip.com) +; +;Licensed under the Apache License, Version 2.0 (the "License"); +;you may not use this file except in compliance with the License. +;You may obtain a copy of the License at +; +; http://www.apache.org/licenses/LICENSE-2.0 +; +;Unless required by applicable law or agreed to in writing, software +;distributed under the License is distributed on an "AS IS" BASIS, +;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;See the License for the specific language governing permissions and +;limitations under the License. +; +;To request to license the code under the MLA license (www.microchip.com/mla_license), +;please contact mla_licensing@microchip.com +;*******************************************************************************/ + + ;//High priority interrupt vector remapping + PSECT HiVector,class=CODE,delta=1,abs + org 0x08 + goto 0x1C08 ;Resides at 0x0008 (hardware high priority interrupt vector), and causes PC to jump to 0x1C08 upon a high priority interrupt event + + + ;//Low priority interrupt vector remapping, as well as bootloader mode absolute + ;//entry point (located at 0x001C). + PSECT LoVector,class=CODE,delta=1,abs + org 0x18 + goto 0x1C18 ;Resides at 0x0018 (hardware low priority interrupt vector), and causes PC to jump to 0x1C18 upon a low priority interrupt event + goto 0x30 ;Resides at 0x001C //Serves as absolute entry point from application program into the bootloader mode + + + + end \ No newline at end of file diff --git a/bootloader/src/bootloader.c b/bootloader/src/bootloader.c index b4c6b14..74f2125 100644 --- a/bootloader/src/bootloader.c +++ b/bootloader/src/bootloader.c @@ -152,8 +152,8 @@ unsigned char BufferedDataIndex; uint24_t ProgrammedPointer; unsigned char ConfigsLockValue; -USB_VOLATILE USB_HANDLE txHandle = 0; -USB_VOLATILE USB_HANDLE rxHandle = 0; +USB_VOLATILE USB_HANDLE txHandle; +USB_VOLATILE USB_HANDLE rxHandle; void WriteFlashBlock(void); void WriteConfigBits(void); @@ -173,7 +173,8 @@ void UserInit(void) ConfigsLockValue = 1; USBEnableEndpoint(HID_EP, USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); - rxHandle = HIDRxPacket(HID_EP, (char *)&PacketFromPC, USB_PACKET_SIZE); + rxHandle = HIDRxPacket(HID_EP, (uint8_t *)&PacketFromPC, USB_PACKET_SIZE); + txHandle = 0; } /****************************************************************************** @@ -219,7 +220,7 @@ void ProcessIO(void) { //We received a new command from the host. Copy the OUT packet from //the host into a local buffer for processing. - rxHandle = HIDRxPacket(HID_EP, (char *)&PacketFromPC, USB_PACKET_SIZE); //Also re-arms the OUT endpoint to be able to receive the next packet + rxHandle = HIDRxPacket(HID_EP, (uint8_t *)&PacketFromPC, USB_PACKET_SIZE); //Also re-arms the OUT endpoint to be able to receive the next packet //HIDRxReport((char *)&PacketFromPC, USB_PACKET_SIZE); //Also re-arms the OUT endpoint to be able to receive the next packet BootState = NOT_IDLE; //Set flag letting state machine know it has a command that needs processing. @@ -263,7 +264,7 @@ void ProcessIO(void) //Init pad bytes to 0x00... Already done after we received the QUERY_DEVICE command (just after calling HIDRxReport()). //Now send the packet to the USB host software, assuming the USB endpoint is available/ready to accept new data. - txHandle = HIDTxPacket(HID_EP, (char *)&PacketToPC, USB_PACKET_SIZE); + txHandle = HIDTxPacket(HID_EP, (uint8_t *)&PacketToPC, USB_PACKET_SIZE); BootState = IDLE; } break; @@ -279,7 +280,6 @@ void ProcessIO(void) //First erase main program flash memory for(ErasePageTracker = START_PAGE_TO_ERASE; ErasePageTracker < (unsigned int)(MAX_PAGE_TO_ERASE + 1); ErasePageTracker++) { - ClearWatchdog(); #ifdef __XC8__ TBLPTRU = 0x00; TBLPTRH = (uint8_t)((uint24_t)ErasePageTracker >> 2); @@ -390,7 +390,7 @@ void ProcessIO(void) //data over so it can get sent to the USB host software. if(!HIDTxHandleBusy(txHandle)) { - HIDTxPacket(HID_OUT_EP, (char *)&PacketToPC, USB_PACKET_SIZE); + txHandle = HIDTxPacket(HID_EP, (uint8_t *)&PacketToPC, USB_PACKET_SIZE); BootState = IDLE; } break; @@ -428,7 +428,7 @@ void ProcessIO(void) //Now actually command USB to send the packet to the host if(!HIDTxHandleBusy(txHandle)) { - HIDTxPacket(HID_OUT_EP, (char *)&PacketToPC, USB_PACKET_SIZE); + txHandle = HIDTxPacket(HID_EP, (uint8_t *)&PacketToPC, USB_PACKET_SIZE); BootState = IDLE; //Packet will be sent, go back to idle state ready for next command from host } break; @@ -509,7 +509,6 @@ void SignFlash(void) if((i % WRITE_BLOCK_SIZE) == 0) { //The write latches are full, time to program the block. - ClearWatchdog(); EECON1 = 0xA4; //Write to flash on next WR = 1 operation UnlockAndActivate(CORRECT_UNLOCK_KEY); } @@ -574,8 +573,10 @@ void WriteFlashBlock(void) //Use to write blocks of data to flash. static unsigned char CorrectionFactor; static const uint8_t* pROM; + + uint24_t romPtrAddress = ProgrammedPointer - BufferedDataIndex; - pROM = (const uint8_t*)((uint8_t)ProgrammedPointer - BufferedDataIndex); + pROM = (const uint8_t*)romPtrAddress; TBLPTRU = 0x00; TBLPTRH = (uint8_t)((uint16_t)pROM >> 8); TBLPTRL = (uint8_t)pROM; @@ -776,18 +777,6 @@ void UnlockAndActivate(unsigned char UnlockKey) EECON1bits.WREN = 0; //Good practice now to clear the WREN bit, as further protection against any accidental activation of self write/erase operations. } -//Helper function to reduce code size when built with C18. The ClrWdt() is an -//inline assembly macro, and on the C18 compiler, if you execute an inline asm -//instruction in a C function, it prevents the compiler from implementing -//optimizations to that particular function (since the compiler doesn't know what -//the user did in the inline asm). Therefore, inline asm is more efficient if -//implemented outside of large C functions, when using C18. -void ClearWatchdog(void) -{ - ClrWdt(); -} - - //Note: The ClrWdt() and "_asm tblrdpostinc _endasm" are inline assembly language //instructions. The ClearWatchdog() and TableReadPostIncrement() functions are //theoretically extraneous, since the operations being accomplished could be diff --git a/bootloader/src/bootloader.h b/bootloader/src/bootloader.h index 31419b1..b645b6b 100644 --- a/bootloader/src/bootloader.h +++ b/bootloader/src/bootloader.h @@ -29,9 +29,6 @@ void UserInit(void); void ProcessIO(void); -void ClearWatchdog(void); -void DisableUSBandExecuteLongDelay(void); - //Vector remapping/absolute address constants #define REMAPPED_APPLICATION_RESET_VECTOR 0x1C00 diff --git a/bootloader/src/main.c b/bootloader/src/main.c index 655e914..3143471 100644 --- a/bootloader/src/main.c +++ b/bootloader/src/main.c @@ -9,22 +9,75 @@ #include "usb.h" #include "bootloader.h" -void main(void) { - //UserInit(); +/* Private prototypes */ +void main(void); +void BootMain(void); + +const unsigned int FlashSignatureWord __at(APP_SIGNATURE_ADDRESS) = APP_SIGNATURE_VALUE; + +void main(void) +{ + //BootMain(); + /** + * TODO: implement hardware IO-based method for forcing entry into bootloader + */ + // normal operation: verify the firmware signature is valid. if it isn't enter + // bootloader (fw update) mode so valid firmware can be flashed +//DoFlashSignatureCheck: + //Check if the application region flash signature is valid + if(*(const unsigned int*)APP_SIGNATURE_ADDRESS == APP_SIGNATURE_VALUE) + { + //The flash signature was valid, implying the previous + //erase/program/verify operation was a success. + + //Also make sure the first WORD of program memory in the app space + //is not blank, meaning there is an application image programmed into the device. + if(*(const unsigned int*)REMAPPED_APPLICATION_RESET_VECTOR != 0xFFFF) + { + //Go ahead and jump out of bootloader mode into the application run mode + #asm + goto REMAPPED_APPLICATION_RESET_VECTOR + #endasm + } + } + //else the application image is missing or corrupt. In this case, we + //need to stay in the bootloader mode, so the user has the ability to + //try (again) to re-program a valid application image into the device. + + BootMain(); +} + +void BootMain(void) __at(0x30) +{ + //Make sure interrupts are disabled for this code (could still be on, + //if the application firmware jumped into the bootloader via software methods) + INTCON = 0x00; + + //Clear the stack pointer, in case the user application jumped into + //bootloader mode with excessive junk on the call stack + STKPTR = 0x00; + + // End of the important parts of the C initializer. This bootloader firmware does not use + // any C initialized user variables (idata memory sections). Therefore, the above is all + // the initialization that is required. + // initialize the USB framework USBDeviceInit(); USBDeviceAttach(); + // initialize the bootloader + UserInit(); + + //Execute main loop while(1) { + //Need to call USBDeviceTasks() periodically. This function takes care of + //processing non-USB application related USB packets (ex: "Chapter 9" + //packets associated with USB enumeration) USBDeviceTasks(); - // do nothing if: not connected to USB host, or the host put us in suspend state - if((USBGetDeviceState() < CONFIGURED_STATE) | USBIsDeviceSuspended()) - continue; - - // run application specific tasks - ProcessIO(); - } -} + ProcessIO(); //This is where all the actual bootloader related data transfer/self programming takes + //place see ProcessIO() function in the BootPIC[xxxx].c file. + }//end while +} \ No newline at end of file diff --git a/common_src/memory.h b/common_src/memory.h new file mode 100644 index 0000000..469c7c2 --- /dev/null +++ b/common_src/memory.h @@ -0,0 +1,37 @@ +/************************************************************************* + * Copyright (C) 2019 by Justin Byers + * + * This file is part of clubdance_v2. + * + * clubdance_v2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * clubdance_v2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with clubdance_v2. If not, see . + *************************************************************************/ + +/** + * @file memory. + * @author Justin Byers + * @date August 11, 2019 + * @brief + * + */ +#ifndef MEMORY_ +#define MEMORY_ + +#define APP_FW_MEMORY_OFFSET 0x2000 + +#define BOOTLOADER_ENTRYPOINT 0x001C + +#define APP_FW_VERSION_ADDRESS (APP_FW_MEMORY_OFFSET + 0x0016) + +#endif /* MEMORY_ */ + diff --git a/firmware/clubdance_v2.X/nbproject/configurations.xml b/firmware/clubdance_v2.X/nbproject/configurations.xml index cfca5da..3e2dab7 100644 --- a/firmware/clubdance_v2.X/nbproject/configurations.xml +++ b/firmware/clubdance_v2.X/nbproject/configurations.xml @@ -20,6 +20,7 @@ ../../common_src/system.c + ../../common_src/memory.h - + @@ -107,14 +108,14 @@ - + - + - + @@ -129,7 +130,7 @@ - + @@ -140,7 +141,7 @@ - + @@ -251,6 +252,7 @@ + ../../bootloader/clubdance_v2_bootloader.X/dist/default/production/clubdance_v2_bootloader.X.production.hex false false diff --git a/firmware/src/main.c b/firmware/src/main.c index d9e8566..f450dfa 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -22,16 +22,17 @@ * @date 6 Aug 2019 * @brief USB interface to 6-sensor DDR pads. */ +const unsigned int VersionWord __at(0x1C16) = 0x0100; #pragma warning disable 1510 #include "usb.h" #include "padhal.h" #include "dancepad.h" -#ifdef LINK_FOR_BOOTLOADER +//#ifdef LINK_FOR_BOOTLOADER // only define this if building fw to be used with the bootloader -const unsigned int VersionWord __at(0x1416) = 0x0100; -#endif + +//#endif void main(void) {