Big release commit for firmware v2.3.0
Put bunch of notes in Readme.txt on how to update device firmware to v2.3 using dfusedemo. Anyone with a device currently in their hands will want to update to this latest version using the dfusedemo instructions there. Or the AVR instructions if you have an old kazzo. For devices shipping after Dec 1st 2018 I will be flashing this latest v2.3 firmware which has it's own firmware updater so the INLretro host software can easily and seamlessly update the firmware for you without any external software, switch or jumper operation on the PCB. This update also includes some power functions in the bootloader dictionary. Can now make direct read/write access to the entire ARM memory space. Maybe I'll add this to the AVR someday..? Having this previously would have actually allowed me to bootstrap a switchless bootloader without dfuse.. ahh well... Also turned the watchdog timer on for the STM32 build finally. Requires refreshing every ~1sec, currently only done in the main. Added application versioning to address 0x08000800 in the binary. Couldn't get the linker script to do this for me for some reason. So for now I just manually put it in the binary file. The fwupdate.lua script has a lot more checks now. Uses the new bootloader dict functions to dump device firmware and make sure all looks good before it starts erasing firmware. Haven't done much testing with the current AVR build. Got a report there was a problem with UNROM flashing, will have to check that out. Done with the firmware for awhile now hopefully. Need to clean up some things with the main program & inlretro.lua script. Start making better use of some recent contributions by several gracious people. Maybe I'll get going on gameboy, GBA, & sega soon.. Got a ton of NESmaker devices to push out the door now with this latest build. So might be slow for a bit..
This commit is contained in:
parent
ff8495455c
commit
54e3e6bf3c
328
Readme.txt
328
Readme.txt
|
|
@ -1,3 +1,27 @@
|
||||||
|
|
||||||
|
===================================
|
||||||
|
INSTALLING DEVICE DRIVERS:
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Plug the device into a USB port.
|
||||||
|
|
||||||
|
Open a windows file explorer and navigate to:
|
||||||
|
INL-retro-progdump\WindowsDriverPackage
|
||||||
|
|
||||||
|
In that folder there's a "InstallDriver.exe" application.
|
||||||
|
Double click it to run it.
|
||||||
|
|
||||||
|
Windows should ask if you want to allow it to make changes to your PC, say YES.
|
||||||
|
|
||||||
|
Click next in the wizard, it should install the drivers to your PC.
|
||||||
|
|
||||||
|
If it worked properly you'll get a "install successful" page, click FINISH.
|
||||||
|
|
||||||
|
In windows you should be able to see "INLretro-prog" listed in "devices and printers" from
|
||||||
|
the control panel.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
===================================
|
===================================
|
||||||
RUNNING THE HOST APPLICATION:
|
RUNNING THE HOST APPLICATION:
|
||||||
===================================
|
===================================
|
||||||
|
|
@ -24,13 +48,309 @@ If the device errors out, or is not responding you may have to press the RESET b
|
||||||
USB connector on the INLretro programmer/dumper to reset the device, and try again.
|
USB connector on the INLretro programmer/dumper to reset the device, and try again.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
===================================
|
===================================
|
||||||
UPDATING DEVICE FIRMWARE
|
UPDATING DEVICE FIRMWARE
|
||||||
===================================
|
===================================
|
||||||
This is done via USB using STmicro DfuSe:
|
|
||||||
|
|
||||||
|
----------------------------------------------------------
|
||||||
|
STM32 ARM based device versions "INLretro" V2.0 and later
|
||||||
|
----------------------------------------------------------
|
||||||
|
If you purchased your device in 2018 or later you have this version
|
||||||
|
This includes devices aquired with NESmaker kits.
|
||||||
|
|
||||||
|
|
||||||
|
0) DO I NEED TO FOLLOW THESE STEPS?
|
||||||
|
|
||||||
|
Devices sold Oct 2018 or earlier shipped with firmware v2.1 or v2.2
|
||||||
|
These builds did not include a 'switchless' USB firmware updater.
|
||||||
|
So you will need to update to v2.3 or later using STmicro DfuSeDemo.
|
||||||
|
Alternatively if you somehow bricked your device with any firmware,
|
||||||
|
you can use STmicro's DfuSeDemo to easily recover it via USB.
|
||||||
|
|
||||||
|
Once upgraded to firmware v2.3.0 or later, you shouldn't need to use
|
||||||
|
the DfuSeDemo to upgrade your device's firmware anymore. The INLretro
|
||||||
|
host software is capable of updating the device's firmware on builds
|
||||||
|
v2.3.0 or later.
|
||||||
|
|
||||||
|
INLretro devices purchased in Nov 2018 were shipped with a mix of firmware versions.
|
||||||
|
INLretro devices purchased in Dec 2018 and later ship with firmware version
|
||||||
|
v2.3.0 or later.
|
||||||
|
Kickstarter NESmaker kits with the large fancy "NES" enclosure shipped with v2.1
|
||||||
|
All other Kickstarter NESmaker kits used the smaller v2.0N PCB and
|
||||||
|
shipped with v2.3.0
|
||||||
|
|
||||||
|
I'm working on updating the INLretro host software to report which
|
||||||
|
firmware version your device is using to take out the guess work.
|
||||||
|
Once this is done the command prompt will report which build version
|
||||||
|
you have. Updating from v2.3.0 to later versions will be pretty easy
|
||||||
|
as the host application will ask you if you'd like to let it update
|
||||||
|
the firmware version for you. In that case you can ignore these DfuSeDemo
|
||||||
|
instructions unless you somehow brick your device. Or maybe you make
|
||||||
|
your own firmware builds and use the Dfu file manager to create your
|
||||||
|
own .dfu builds that may or may not be compatible with the switchless
|
||||||
|
firmware updater.
|
||||||
|
|
||||||
|
So at this point I'm assuming you need/want to use the DfuSeDemo
|
||||||
|
to update your device because it has firmware v2.2 or earlier, or you
|
||||||
|
bricked your device, etc.
|
||||||
|
|
||||||
|
|
||||||
|
1) GET THE SOFTWARE
|
||||||
|
|
||||||
|
Go to the st.com link below. At the bottom there's a "GET SOFTWARE"
|
||||||
|
section, download the STSW-STM32080 item. This is written for v3.0.6
|
||||||
https://www.st.com/en/development-tools/stsw-stm32080.html
|
https://www.st.com/en/development-tools/stsw-stm32080.html
|
||||||
|
|
||||||
Detailed instructions to come, will update this section with the next firmware update.
|
Alternatively you can save the hassle of creating an STmicro account
|
||||||
|
by downloading directly from the following link if you would like:
|
||||||
|
https://www.dropbox.com/s/gwcvd3dqwkbzsv9/en.stsw-stm32080.zip?dl=0
|
||||||
|
|
||||||
|
|
||||||
|
2) INSTALL THE SOFTWARE
|
||||||
|
|
||||||
|
As far as I know this application is windows only. You will probably
|
||||||
|
have to run it in a virtual machine if you're on linux/windows. If
|
||||||
|
this is a big problem I can look into creating my own dfuse application
|
||||||
|
that runs on linux/mac. This should be a one time thing, so I'm hoping
|
||||||
|
gaining access to a windows machine isn't too much to ask..
|
||||||
|
|
||||||
|
Extract the .zip downloaded in step 1. Click next, select users, etc..
|
||||||
|
Click install and let it make the changes to your PC.
|
||||||
|
Once complete it should give you an option to launch it.
|
||||||
|
|
||||||
|
|
||||||
|
3) LAUNCH DFUSEDEMO
|
||||||
|
|
||||||
|
You can probably find it in the start menu searching "dfusedemo"
|
||||||
|
It didn't give me any choices on install path and put it here:
|
||||||
|
C:\Program Files (x86)\STMicroelectronics\Software\DfuSe v3.0.6\Bin
|
||||||
|
From that folder you can create shortcuts of dfusedemo to your desktop
|
||||||
|
If you think you may like to make your own firmware builds and want
|
||||||
|
to convert your hex/bin files to .dfu you can use the DFU file manager
|
||||||
|
in the same installation folder as dfusedemo.
|
||||||
|
|
||||||
|
|
||||||
|
4) GET THE INLRETRO INTO DFU MODE
|
||||||
|
|
||||||
|
At this point chances are there's nothing listed under
|
||||||
|
"Available DFU Devices", it takes some steps to get the programmer
|
||||||
|
in DFU mode so the dfusedemo application can find & communicate to it.
|
||||||
|
|
||||||
|
This step varies slightly depending on your exact device & when you
|
||||||
|
purchased it.
|
||||||
|
|
||||||
|
-PCB VERSION 2.0 purchase prior to Dec 2018
|
||||||
|
If your device shipped with firmware v2.1 or v2.2
|
||||||
|
I soldered a "BL/RUN" switch to aid in this process.
|
||||||
|
|
||||||
|
The switch is next to the USB socket, place it in "BL" nearest
|
||||||
|
the USB socket. Then plug the USB cable into your PC. If it
|
||||||
|
was already plugged in, just replug it, or hit the RESET button
|
||||||
|
soldered right next to the BL/RUN switch.
|
||||||
|
|
||||||
|
-PCB VERSION 2.0 purchased Dec 2018 or later
|
||||||
|
or the big NES enclosure from NESmaker kickstarter
|
||||||
|
You may not have a BL/RUN switch. Unplug the USB cable.
|
||||||
|
Get a tweezers, paperclip, or something conductive like that.
|
||||||
|
There are 5 holes in the PCB edge with "RUN" and "BL" on either side
|
||||||
|
Ignore the bigger outer 2 holes. Short the center hole to the small
|
||||||
|
hole next to it closest to the BL label (and USB connector)
|
||||||
|
Plug the USB cable in while those two pads are shorted together.
|
||||||
|
It might help to have a freind plug in the USB cable while you short the pins.
|
||||||
|
Once it's plugged in you don't have to keep the pins shorted anymore.
|
||||||
|
|
||||||
|
-PCB VERSION 2.0N smaller device with NES Connector alone
|
||||||
|
These are the majority of the basic NESmaker kickstarter kits.
|
||||||
|
You really shouldn't be going through this process unless you
|
||||||
|
bricked your device or I personally instructed you to do so.
|
||||||
|
Reason being is had an error with the PCB BL/RUN switch.
|
||||||
|
I specifically released the switchless firmware updater in time
|
||||||
|
to avoid you from going through this trouble. All V2.0N PCBs
|
||||||
|
shipped with firmware v2.3.0 or later and thus don't need dfusedemo
|
||||||
|
to update.
|
||||||
|
If you're still here, with PCB v2.0N dated "AUG2018" get a tweezers
|
||||||
|
or something like a metal paperclip.
|
||||||
|
On the top corner of the PCB there's a place for a "BL/RUN" switch.
|
||||||
|
I didn't solder it on though, and the silk is backwards.
|
||||||
|
Ignore the bigger outer 2 holes. Short the center hole to the small
|
||||||
|
hole next to it closest to the RUN label (and USB connector).
|
||||||
|
Plug in the USB cable with those pads shorted together.
|
||||||
|
It might help to have a freind plug in the USB cable while you short the pins.
|
||||||
|
Once it's plugged in you don't have to keep the pins shorted anymore.
|
||||||
|
|
||||||
|
-Other PCB versions: there are none at this time... (12/1/2018)
|
||||||
|
If you've got a PCB that says v1.1, v1.2, v1.3, or v1.4 on the bottom
|
||||||
|
You're in the wrong place. None of these steps will work for you.
|
||||||
|
Go down a little to the instructions:
|
||||||
|
"AVR based devices versions "KAZZO" V1.4 and eariler"
|
||||||
|
|
||||||
|
|
||||||
|
5) PERFORM THE UPDATE
|
||||||
|
|
||||||
|
The device should be in DFU mode now from the step above.
|
||||||
|
|
||||||
|
With the device is in DFU mode the dfusedemo application should
|
||||||
|
list it under available devices as "STM Device in DFU Mode"
|
||||||
|
You can also see it listed in windows "devices & printers" as
|
||||||
|
"STM32 BOOTLOADER". If you see "INL Retro-Prog" the device isn't
|
||||||
|
in DFU mode, try this step again..
|
||||||
|
|
||||||
|
-Choose Button
|
||||||
|
Choose the right Choose button! There are 2 "Choose" buttons.
|
||||||
|
Naturally, you'll probably select the wrong one...
|
||||||
|
CLICK THE "Choose" button in the BOTTOM CENTER in the
|
||||||
|
"Upgrade or Verify Action" section.
|
||||||
|
|
||||||
|
The Choose button will popup an Open window, navigate to
|
||||||
|
INL-retro-progdump\firmware\DFU_release folder
|
||||||
|
|
||||||
|
-Load .dfu file
|
||||||
|
Select the proper .dfu file:
|
||||||
|
All versions publicly released are here, sort by date and select
|
||||||
|
the latest one that matches your PCB version.
|
||||||
|
|
||||||
|
If your PCB is big and square (v2.0) select the one that
|
||||||
|
starts with INLretro6 (currently INLretro6_PCBv2_0_FWv2_03_0.dfu)
|
||||||
|
|
||||||
|
If your PCB is smaller and only has place for NES connector
|
||||||
|
select the one that starts with "INL_NES"
|
||||||
|
(currently INL_NES_PCBv2_0N_FWv2_03_0.dfu)
|
||||||
|
|
||||||
|
If you're following these instructions later down the road
|
||||||
|
I've probably got later versions you should be using.
|
||||||
|
Just make sure the PCB version of the name matches what's printed
|
||||||
|
in silk screen on the bottom of your PCB. In the end it's easy
|
||||||
|
to change if you select the wrong one. Or the firmware updater
|
||||||
|
will fix it for you once you've got it unbricked.
|
||||||
|
|
||||||
|
-Optional settings
|
||||||
|
You can check the "Verify after download" box just above the
|
||||||
|
Choose button, it will verify the flash after programming.
|
||||||
|
You can also check the "Optimize Upgrade duration" but it really
|
||||||
|
doesn't matter, it only takes a couple seconds anyway..
|
||||||
|
|
||||||
|
-Upgrade
|
||||||
|
Click the "Upgrade" button just to the right of that "Choose"
|
||||||
|
button you just used.
|
||||||
|
|
||||||
|
NOTE! You WILL GET A WARNING POPUP, it's expected!
|
||||||
|
Click "Yes" to the warning: "Your device was plugged in DFU mode.
|
||||||
|
"So it is impossible to make sure this file is correct for this device."
|
||||||
|
"Continue however?"
|
||||||
|
|
||||||
|
CLICK YES.
|
||||||
|
|
||||||
|
-Watch the status bar
|
||||||
|
It should click across a few times and say
|
||||||
|
"Target 00: Verify successful!" or just
|
||||||
|
"Target 00: Upgrade successful!" depending on if you chose
|
||||||
|
to verify or not in the optional step.
|
||||||
|
|
||||||
|
If you have problems, make sure the device is in DFU mode
|
||||||
|
and appears in windows "devices & printers" as "STM32 BOOTLOADER"
|
||||||
|
before trying to upgrade. Please contact me if you're
|
||||||
|
having problems.
|
||||||
|
|
||||||
|
-Exit DFU mode
|
||||||
|
If you have a BL/RUN switch, place it back in RUN
|
||||||
|
Unplug the USB cable and plug it back in.
|
||||||
|
You should see "INL Retro-Prog" in devices & printers
|
||||||
|
and the device should be running the latest firmware now!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------------------------------
|
||||||
|
AVR based devices versions "KAZZO" V1.4 and eariler
|
||||||
|
----------------------------------------------------------
|
||||||
|
If you purchased your device in 2017 or earlier you have this version
|
||||||
|
This should also apply if you made your own kazzo based on the open
|
||||||
|
source design. Although I can't assure this software works with
|
||||||
|
any of those versions, especially versions with something besides
|
||||||
|
the atmega164.
|
||||||
|
|
||||||
|
These devices sold by Infinite NES Lives included a bootloader to
|
||||||
|
update the flash via USB.
|
||||||
|
|
||||||
|
There are effectively 3 main versions of firmware that run on your device:
|
||||||
|
|
||||||
|
A) original kazzo firmware created by naruko that is needed to use
|
||||||
|
anago/unagi dumping software. See old instructions to get that running
|
||||||
|
if you want it. You're in the wrong place.
|
||||||
|
|
||||||
|
B) INL released firmware for use with "INL-retro prog v1.0beta" this
|
||||||
|
was effectively my "version 1" release of firmware & software.
|
||||||
|
It wasn't very good, but got the job done for far too many years.
|
||||||
|
I don't recommend using that old firmware & software anymore
|
||||||
|
You'll be able to use the latest software and firmware
|
||||||
|
provided here instead.
|
||||||
|
|
||||||
|
C) INLretro v2 firmare & software, the reason you're here, and
|
||||||
|
the software & firmware included with this download/project.
|
||||||
|
Upgrading the firmware is similar to previously, but here's
|
||||||
|
a quick run through to get you going with the latest firmware
|
||||||
|
that's required in order to use this INLretro software.
|
||||||
|
|
||||||
|
|
||||||
|
You're here because you want to install option C from above
|
||||||
|
Smart choice...
|
||||||
|
|
||||||
|
|
||||||
|
1) GET THE SOFTWARE
|
||||||
|
|
||||||
|
The bootloader software is already included with this project/download
|
||||||
|
which you're reading this file from. It also doesn't require installation.
|
||||||
|
These instructions are for windows, but you can build the bootloader to
|
||||||
|
work on linux/mac as well.
|
||||||
|
|
||||||
|
|
||||||
|
2) PUT DEVICE IN BOOTLOADER MODE
|
||||||
|
|
||||||
|
Place the BL/RUN switch in the BL position. Plug in the USB cable, or
|
||||||
|
Hit the RESET button on the PCB.
|
||||||
|
|
||||||
|
The device should now be in bootloader mode. Look in windows "devices
|
||||||
|
and printers" and you should see "HIDBoot". If not, try this step again.
|
||||||
|
The next steps won't work if you still see "INLRetro-Prog" "kazzo" or something
|
||||||
|
like that..
|
||||||
|
|
||||||
|
|
||||||
|
3) UPDATE THE FIRMWARE
|
||||||
|
|
||||||
|
In a windows file explorer navigate to:
|
||||||
|
|
||||||
|
INL-retro-progdump\avr_bootloader
|
||||||
|
|
||||||
|
You should see a file in that folder named:
|
||||||
|
|
||||||
|
"click to load v1 INLkazzo with INLretro v2.bat"
|
||||||
|
|
||||||
|
Double click on that file to run it.
|
||||||
|
|
||||||
|
If you didn't get the device in HIDBoot properly you'll probably see a message like:
|
||||||
|
"Error opening HIDBoot device: The specified device was not found"
|
||||||
|
Go back and retry step 2, this step only works if you got step 2 working properly
|
||||||
|
|
||||||
|
If you were successful you'll see a message like this:
|
||||||
|
|
||||||
|
Page size = 128 (0x80)
|
||||||
|
Device size = 16384 (0x4000); 14336 bytes remaining
|
||||||
|
Uploading 13312 (0x3400) bytes starting at 0 (0x0)
|
||||||
|
0x03380 ... 0x03400
|
||||||
|
|
||||||
|
C:\Users\...\INL-retro-progdump\avr_bootloader>pause
|
||||||
|
Press any key to continue . . .
|
||||||
|
|
||||||
|
Hit the any key, or just close that popup window, you've updated the firmware!
|
||||||
|
|
||||||
|
|
||||||
|
4) EXIT BOOTLOADER MODE
|
||||||
|
|
||||||
|
Place the BL/RUN switch in RUN
|
||||||
|
You should see "INL Retro-Prog" in devices & printers
|
||||||
|
and the device should be running the latest firmware ready to use the latest software!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -82,7 +402,7 @@ need to have libusb-dev installed can check by typing "libusb-config" in termina
|
||||||
will present usage options if installed on your system
|
will present usage options if installed on your system
|
||||||
if not installed should report so with suggestion for apt-get:
|
if not installed should report so with suggestion for apt-get:
|
||||||
sudo apt-get install libusb-dev
|
sudo apt-get install libusb-dev
|
||||||
then just run 'make' should build sucessfully
|
then just run 'make' should build successfully
|
||||||
|
|
||||||
With the bootloader commandline app built, the firmware can be loaded
|
With the bootloader commandline app built, the firmware can be loaded
|
||||||
onto the INL retro-programmer via USB:
|
onto the INL retro-programmer via USB:
|
||||||
|
|
@ -169,7 +489,7 @@ Requires you to have an avr programmer to reflash atmega164a mcu
|
||||||
Helpful to download more recent version of avrdude than included with WinAVR.
|
Helpful to download more recent version of avrdude than included with WinAVR.
|
||||||
Download latest version with mingw32.zip from following link:
|
Download latest version with mingw32.zip from following link:
|
||||||
http://download.savannah.gnu.org/releases/avrdude/
|
http://download.savannah.gnu.org/releases/avrdude/
|
||||||
unzip and copy paste both avrdude.exe and avrdude.conf to C:\WinAVR-20100110\bin directory
|
nzip and copy paste both avrdude.exe and avrdude.conf to C:\WinAVR-20100110\bin directory
|
||||||
Assuming the recent build still doesn't support atmega164a..
|
Assuming the recent build still doesn't support atmega164a..
|
||||||
You'll also have to add a definition for atmega164a in the avrdude.conf file
|
You'll also have to add a definition for atmega164a in the avrdude.conf file
|
||||||
Copy paste the atmega324P section and rename it atmega164A
|
Copy paste the atmega324P section and rename it atmega164A
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
commandline\bootloadHID.exe -r ..\firmware\build_avr\avr_kazzo.hex
|
||||||
|
pause
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -30,7 +30,7 @@ help:
|
||||||
hex: $(BUILD)/$(PROJ).hex
|
hex: $(BUILD)/$(PROJ).hex
|
||||||
|
|
||||||
program: $(BUILD)/$(PROJ).hex
|
program: $(BUILD)/$(PROJ).hex
|
||||||
../bootloader/commandline/bootloadHID -r $<
|
../avr_bootloader/commandline/bootloadHID -r $<
|
||||||
|
|
||||||
dir:
|
dir:
|
||||||
mkdir -p $(BUILD)
|
mkdir -p $(BUILD)
|
||||||
|
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -97,7 +97,7 @@ SECTIONS
|
||||||
/* when created there was about 132 Bytes of free space here */
|
/* when created there was about 132 Bytes of free space here */
|
||||||
|
|
||||||
/* fwupdate main needs to be in a fixed location */
|
/* fwupdate main needs to be in a fixed location */
|
||||||
. = 0x0780;
|
. = 0x0770;
|
||||||
*(.fw_up_main)
|
*(.fw_up_main)
|
||||||
|
|
||||||
/* when created there was about 32Bytes free space here */
|
/* when created there was about 32Bytes free space here */
|
||||||
|
|
@ -107,7 +107,11 @@ SECTIONS
|
||||||
|
|
||||||
. = 0x0800; /*update the location counter to the 3rd KByte */
|
. = 0x0800; /*update the location counter to the 3rd KByte */
|
||||||
|
|
||||||
/* reset handler fixed to 0x08000800
|
*(.appver) /* 4 Bytes characters ie: "AV01" */
|
||||||
|
/* can't get this to work right now, just manually add to binary before releasing.. */
|
||||||
|
|
||||||
|
. = 0x0804;
|
||||||
|
/* reset handler fixed to 0x08000804
|
||||||
* that way the vector table should always be accurate */
|
* that way the vector table should always be accurate */
|
||||||
*(.reset_handler)
|
*(.reset_handler)
|
||||||
|
|
||||||
|
|
@ -184,7 +188,7 @@ SECTIONS
|
||||||
*(.rodata*)
|
*(.rodata*)
|
||||||
|
|
||||||
*(.eh_frame*)
|
*(.eh_frame*)
|
||||||
} > FLASH
|
} > FLASH = 0xFF /* fill with 0xFF 'erased' */
|
||||||
|
|
||||||
.ARM.extab :
|
.ARM.extab :
|
||||||
{
|
{
|
||||||
|
|
@ -268,7 +272,16 @@ SECTIONS
|
||||||
*(.fastrun) /*Placing functions in .fastrun section in RAM */
|
*(.fastrun) /*Placing functions in .fastrun section in RAM */
|
||||||
/* This kind of breaks arm-none-eabi-size look at .map file __data_end__ for actual data size*/
|
/* This kind of breaks arm-none-eabi-size look at .map file __data_end__ for actual data size*/
|
||||||
/* Really size is just combining text & data together */
|
/* Really size is just combining text & data together */
|
||||||
|
/* use a function attr like the following:
|
||||||
|
* #define RAMFUNC __attribute__ ((section (".fastrun"), noinline, noclone))
|
||||||
|
* RAMFUNC void myramfunction(){ code executes from ram }
|
||||||
|
* or for assembly functions: .section ".ramfunctions"
|
||||||
|
* the noinline is important so your function doesn't get inline optimized into
|
||||||
|
* or so that clones of your function don't end up in different places/sections
|
||||||
|
* whatever flash code is exectuting it. However if you have a ram functions
|
||||||
|
* calling other ram functions you may not need noinline and can benefit from
|
||||||
|
* it's optimization
|
||||||
|
* /
|
||||||
|
|
||||||
*(.jcr)
|
*(.jcr)
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|
|
||||||
|
|
@ -25,29 +25,109 @@
|
||||||
* Rtn: SUCCESS if opcode found, error if opcode not present or other problem.
|
* Rtn: SUCCESS if opcode found, error if opcode not present or other problem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t addrh;
|
uint16_t addrh;
|
||||||
|
uint16_t *addr_ptr;
|
||||||
|
|
||||||
|
typedef void (*pFunction)(void);
|
||||||
|
|
||||||
uint8_t bootload_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata )
|
uint8_t bootload_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata )
|
||||||
{
|
{
|
||||||
|
#define RD_LEN 0
|
||||||
|
#define RD0 1
|
||||||
|
#define RD1 2
|
||||||
|
#define RD2 3
|
||||||
|
#define RD3 4
|
||||||
|
|
||||||
|
#define BYTE_LEN 1
|
||||||
|
#define HWORD_LEN 2
|
||||||
|
#define WORD_LEN 4
|
||||||
|
|
||||||
|
pFunction JumpToApplication;
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
#ifdef STM_CORE
|
#ifdef STM_CORE
|
||||||
case JUMP_BL: jump_to_bootloader(); break;
|
//case JUMP_BL: jump_to_bootloader(); break;
|
||||||
//device won't respond after this point so actually expect an error to result
|
//device won't respond after this point so actually expect an error to result
|
||||||
|
|
||||||
case LOAD_ADDRH: addrh = operand; break;
|
case LOAD_ADDRH: addrh = operand; break;
|
||||||
case JUMP_ADDR: jump2addr((addrh<<16) | (operand)); break;
|
|
||||||
|
case JUMP_ADDR: //jump2addr((addrh<<16) | (operand)); break;
|
||||||
|
JumpToApplication = (void (*)(void)) ((addrh<<16|operand)); //Base of flash
|
||||||
|
//JumpToApplication = (void (*)(void)) (*((uint32_t *) ((0x1FFFC400 + 4)))); //jump to vector
|
||||||
|
JumpToApplication();
|
||||||
|
break;
|
||||||
//device may not respond depending on the address/function being jumped to
|
//device may not respond depending on the address/function being jumped to
|
||||||
|
|
||||||
case PREP_FWUPDATE: //while we are directly jumping to fwupdate section
|
case PREP_FWUPDATE:
|
||||||
//it should be okay if it's in a fixed location
|
//while we are directly jumping to fwupdate section
|
||||||
return fwupdate_forever(); break;
|
//it should be okay since it's in a fixed location
|
||||||
//this function hijacked the stack frame to steal execution
|
return fwupdate_forever(); break;
|
||||||
//after returing from the current USB ISR
|
//this function hijacked the stack frame to steal execution
|
||||||
//it returns SUCCESS/ERR depending on if it found and modified
|
//after returing from the current USB ISR
|
||||||
//the stack frame successfully
|
//it returns SUCCESS if it found and modified
|
||||||
//leaves main application code for good
|
//the stack frame successfully
|
||||||
//will respond to usb interrupts, but are directed to fwupdater
|
//if it didn't find the stack frame it probably exceeded SRAM
|
||||||
|
//space and caused a hardfault.
|
||||||
|
//Once the USB ISR is completed, exectution left main application code for good
|
||||||
|
//will respond to usb interrupts, but are directed to fwupdater
|
||||||
|
|
||||||
|
case SET_PTR_HI:
|
||||||
|
addr_ptr = (uint16_t*) ((((uint32_t)addr_ptr) & 0x0000FFFF) | (operand<<16));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SET_PTR_LO:
|
||||||
|
addr_ptr = (uint16_t*) ((((uint32_t)addr_ptr) & 0xFFFF0000) | (operand));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GET_PTR:
|
||||||
|
//update ptr with offset
|
||||||
|
rdata[RD_LEN] = WORD_LEN;
|
||||||
|
rdata[RD0] = (uint32_t)addr_ptr;
|
||||||
|
rdata[RD1] = ((uint32_t)addr_ptr)>>8;
|
||||||
|
rdata[RD2] = ((uint32_t)addr_ptr)>>16;
|
||||||
|
rdata[RD3] = ((uint32_t)addr_ptr)>>24;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RD_PTR_OFFSET:
|
||||||
|
//use offset from current pointer but don't change it
|
||||||
|
rdata[RD_LEN] = HWORD_LEN;
|
||||||
|
rdata[RD0] = addr_ptr[operand];
|
||||||
|
rdata[RD1] = (addr_ptr[operand])>>8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WR_PTR_OFFSET:
|
||||||
|
//use offset from current pointer but don't change it
|
||||||
|
addr_ptr[miscdata] = operand;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RD_PTR_OFF_UP:
|
||||||
|
//update ptr with offset
|
||||||
|
addr_ptr += operand;
|
||||||
|
rdata[RD_LEN] = HWORD_LEN;
|
||||||
|
rdata[RD0] = *addr_ptr;
|
||||||
|
rdata[RD1] = (*addr_ptr)>>8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WR_PTR_OFF_UP:
|
||||||
|
//update ptr with miscdata
|
||||||
|
addr_ptr += miscdata;
|
||||||
|
//write operand to address that's being pointed to
|
||||||
|
*addr_ptr = operand;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//can't get this to go where I want 0x08000800
|
||||||
|
//so for now I'll just put it there manually post-build
|
||||||
|
//can use the pointer to read 4bytes at 0x08000800
|
||||||
|
//which is the begining of application code space
|
||||||
|
//should include ascii "AV00" with the digits for version
|
||||||
|
// case GET_APP_VER:
|
||||||
|
// rdata[RD_LEN] = WORD_LEN;
|
||||||
|
// rdata[RD0] = app_version[0];
|
||||||
|
// rdata[RD1] = app_version[1];
|
||||||
|
// rdata[RD2] = app_version[2];
|
||||||
|
// rdata[RD3] = app_version[3];
|
||||||
|
// break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//opcode doesn't exist
|
//opcode doesn't exist
|
||||||
return ERR_UNKN_BOOTLOAD_OPCODE;
|
return ERR_UNKN_BOOTLOAD_OPCODE;
|
||||||
|
|
@ -58,58 +138,58 @@ uint8_t bootload_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void jump_to_bootloader()
|
//void jump_to_bootloader()
|
||||||
{
|
//{
|
||||||
|
//
|
||||||
#ifdef STM_INL6
|
//#ifdef STM_INL6
|
||||||
// 070C6 jump to: 0x1FFFC519
|
//// 070C6 jump to: 0x1FFFC519
|
||||||
// 070RB jump to: 0x1FFFCBC1
|
//// 070RB jump to: 0x1FFFCBC1
|
||||||
|
//
|
||||||
|
//
|
||||||
asm(
|
// asm(
|
||||||
//"ldr pc, boot_addr\n\t"
|
// //"ldr pc, boot_addr\n\t"
|
||||||
// "ldr r0, =0x12345678\n\t"
|
//// "ldr r0, =0x12345678\n\t"
|
||||||
// "mov r0, r0\n\t"
|
//// "mov r0, r0\n\t"
|
||||||
// "mov r0, r0\n\t"
|
//// "mov r0, r0\n\t"
|
||||||
//".p2align 2\n\t"
|
// //".p2align 2\n\t"
|
||||||
//"boot_addr:\n\t"
|
// //"boot_addr:\n\t"
|
||||||
//".word 0x1FFFC519"
|
// //".word 0x1FFFC519"
|
||||||
"ldr r0, [pc, #8]\n\t"// @ remember pc is 8 bytes ahead
|
// "ldr r0, [pc, #8]\n\t"// @ remember pc is 8 bytes ahead
|
||||||
"mov r13, r0\n\t" //load main stack pointer
|
// "mov r13, r0\n\t" //load main stack pointer
|
||||||
"ldr r0, [pc, #8]\n\t"// @ remember pc is 8 bytes ahead
|
// "ldr r0, [pc, #8]\n\t"// @ remember pc is 8 bytes ahead
|
||||||
//"mov lr, r0\n\t"
|
// //"mov lr, r0\n\t"
|
||||||
//"bx lr \n\t"// @ function return
|
// //"bx lr \n\t"// @ function return
|
||||||
//"bkpt\n\t"
|
// //"bkpt\n\t"
|
||||||
"mov r0, r0\n\t"
|
// "mov r0, r0\n\t"
|
||||||
//"mov pc, r0\n\t"
|
// //"mov pc, r0\n\t"
|
||||||
"bx r0\n\t"
|
// "bx r0\n\t"
|
||||||
//"bootaddr\n\t"//
|
// //"bootaddr\n\t"//
|
||||||
//".word 0x1FFFC519" //070C6
|
// //".word 0x1FFFC519" //070C6
|
||||||
".p2align 2\n\t"
|
// ".p2align 2\n\t"
|
||||||
".word 0x20001278\n\t" //C6 MSP @ reset
|
// ".word 0x20001278\n\t" //C6 MSP @ reset
|
||||||
// ".word 0x00010002\n\t"
|
//// ".word 0x00010002\n\t"
|
||||||
//".word 0x00030004\n\t"
|
// //".word 0x00030004\n\t"
|
||||||
//".word 0x1FFFC519\n\t" //C6 AN2606
|
// //".word 0x1FFFC519\n\t" //C6 AN2606
|
||||||
".word 0x1FFFCAC5\n\t" //C6 BL reset vector
|
// ".word 0x1FFFCAC5\n\t" //C6 BL reset vector
|
||||||
//".word 0x1FFFCBC1\n\t" //stlink PC when connecting with BL grounded
|
// //".word 0x1FFFCBC1\n\t" //stlink PC when connecting with BL grounded
|
||||||
//".word 0x1FFFC919\n\t" //best guess based on C6
|
// //".word 0x1FFFC919\n\t" //best guess based on C6
|
||||||
//".word 0x1FFFCBC1\n\t" //bootloader reset vector
|
// //".word 0x1FFFCBC1\n\t" //bootloader reset vector
|
||||||
".word 0x00050006\n\t"
|
// ".word 0x00050006\n\t"
|
||||||
".word 0x00070008\n\t"
|
// ".word 0x00070008\n\t"
|
||||||
// ".word 0x1FFFC919\n\t"
|
//// ".word 0x1FFFC919\n\t"
|
||||||
// ".word 0x1FFFC919\n\t"
|
//// ".word 0x1FFFC919\n\t"
|
||||||
// ".word 0x1FFFC919\n\t"
|
//// ".word 0x1FFFC919\n\t"
|
||||||
// ".word 0x1FFFC919\n\t"
|
//// ".word 0x1FFFC919\n\t"
|
||||||
// ".word 0x1FFFC919\n\t"
|
//// ".word 0x1FFFC919\n\t"
|
||||||
".word 0x1FFFC919"
|
// ".word 0x1FFFC919"
|
||||||
//".word 0x1FFFCBC1"
|
// //".word 0x1FFFCBC1"
|
||||||
);
|
// );
|
||||||
bootaddr:
|
//bootaddr:
|
||||||
asm(
|
// asm(
|
||||||
".word 0xDEADBEEF"
|
// ".word 0xDEADBEEF"
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
#endif
|
//#endif
|
||||||
|
//
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,39 @@ int main(void)
|
||||||
|
|
||||||
#ifdef STM_CORE
|
#ifdef STM_CORE
|
||||||
|
|
||||||
|
//INDEPENDENT WATCH DOG TIMER
|
||||||
|
//has it's own clock circuit so even if the main clock fails the WDT
|
||||||
|
//will keep running, it's not as accurate as the System Window WDT
|
||||||
|
//but we don't care about accuracy for our needs.
|
||||||
|
//
|
||||||
|
//I can't make sense of the window option, so let's not bother with it..
|
||||||
|
//
|
||||||
|
//Configuring the IWDG when the window option is disabled
|
||||||
|
// When the window option it is not used, the IWDG can be configured as follows:
|
||||||
|
// 1.Enable the IWDG by writing 0x0000 CCCC in the IWDG_KR register.
|
||||||
|
#define wdt_enable() IWDG->KR = 0x0000CCCC
|
||||||
|
wdt_enable();
|
||||||
|
// 2. Enable register access by writing 0x00005555 in the IWDG_KR register.
|
||||||
|
IWDG->KR = 0x00005555;
|
||||||
|
//After this point the IWDG timer can NEVER be shut off, except via reset..
|
||||||
|
// 3. Write the IWDG prescaler by programming IWDG_PR from 0 to 7.
|
||||||
|
// default is zero divider / 4
|
||||||
|
// 40Khz clock input to prescaler
|
||||||
|
// divided by 4 = 10Khz
|
||||||
|
IWDG->PR = 2; // divided by 16 = 2.5Khz
|
||||||
|
// 4. Write the reload register (IWDG_RLR).
|
||||||
|
//12bit value that gets loaded into WDcounter each time counter is refreshed
|
||||||
|
//10Khz clock -> 1sec, need a value of 10,000 = 0x2710 too big
|
||||||
|
//12bit counter has max value of 4095
|
||||||
|
//2.5Khz clock -> 1sec, need value of 2500 ~= 2560 = 0xA00
|
||||||
|
IWDG->RLR = 0x0A00;
|
||||||
|
// 5. Wait for the registers to be updated (IWDG_SR = 0x00000000).
|
||||||
|
while( IWDG->SR ) { /* forever */ }
|
||||||
|
// 6. Refresh the counter value with IWDG_RLR (IWDG_KR = 0x0000 AAAA)
|
||||||
|
#define wdt_reset() IWDG->KR = 0x0000AAAA
|
||||||
|
wdt_reset();
|
||||||
|
//call this function atleast once a second to keep the device from resetting
|
||||||
|
|
||||||
//remap system memory (including vector table)
|
//remap system memory (including vector table)
|
||||||
// SYSCFG->CFGR1 = 0x00000002; //boot value (BOOT1:0 = 0b10
|
// SYSCFG->CFGR1 = 0x00000002; //boot value (BOOT1:0 = 0b10
|
||||||
// SYSCFG->CFGR1 = 0x00000001; //map sysmem bootloader to 0x00000000
|
// SYSCFG->CFGR1 = 0x00000001; //map sysmem bootloader to 0x00000000
|
||||||
|
|
@ -115,7 +148,6 @@ int main(void)
|
||||||
//setup user switch as input
|
//setup user switch as input
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//intialize i/o and LED to pullup state
|
//intialize i/o and LED to pullup state
|
||||||
|
|
@ -145,10 +177,10 @@ int main(void)
|
||||||
//=================
|
//=================
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
#ifdef AVR_CORE
|
|
||||||
//pet the watch doggie to keep him happy
|
//pet the watch doggie to keep him happy
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
|
|
||||||
|
#ifdef AVR_CORE
|
||||||
//must call at regular intervals no longer than 50msec
|
//must call at regular intervals no longer than 50msec
|
||||||
//keeps 8Byte EP buffer moving from what I understand
|
//keeps 8Byte EP buffer moving from what I understand
|
||||||
usbPoll();
|
usbPoll();
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ FWUPDATE_NOIN uint16_t usb_fwupdate_setup(uint8_t data[8])
|
||||||
static uint16_t rv16[RETURN_BUFF_SIZE/2];
|
static uint16_t rv16[RETURN_BUFF_SIZE/2];
|
||||||
uint8_t *rv = (uint8_t*)rv16;
|
uint8_t *rv = (uint8_t*)rv16;
|
||||||
|
|
||||||
|
|
||||||
//create a usbMsgPtr variable from the stack which we can use convienently
|
//create a usbMsgPtr variable from the stack which we can use convienently
|
||||||
//but then at end of the function we'll need to copy the value over to usb_buff usbMsgPtr_H/L
|
//but then at end of the function we'll need to copy the value over to usb_buff usbMsgPtr_H/L
|
||||||
usbMsgPtr_t usbMsgPtr;
|
usbMsgPtr_t usbMsgPtr;
|
||||||
|
|
@ -277,9 +278,10 @@ FWUPDATE_NOIN uint8_t usb_fwupdate_write(uint8_t *data, uint8_t len)
|
||||||
//and it shouldn't change
|
//and it shouldn't change
|
||||||
FWUPMAIN uint8_t fwupdate_forever()
|
FWUPMAIN uint8_t fwupdate_forever()
|
||||||
{
|
{
|
||||||
|
|
||||||
//need to turn off any interrupt sources except USB
|
//need to turn off any interrupt sources except USB
|
||||||
|
|
||||||
//TODO turn off WDT
|
//Cannot turn off the WDT not possible! We must keep petting him!
|
||||||
|
|
||||||
//update usb function pointers to fwupdate functions
|
//update usb function pointers to fwupdate functions
|
||||||
//this file is compiled at same time as the the setup/write functions
|
//this file is compiled at same time as the the setup/write functions
|
||||||
|
|
@ -378,10 +380,15 @@ FWUPMAIN uint8_t fwupdate_forever()
|
||||||
//if fwupdate is done, intitate system reset
|
//if fwupdate is done, intitate system reset
|
||||||
//maybe it's safer to have the user do this by unpluggig the device..?
|
//maybe it's safer to have the user do this by unpluggig the device..?
|
||||||
|
|
||||||
|
//pet watchdog
|
||||||
|
IWDG->KR = 0x0000AAAA;
|
||||||
|
|
||||||
//Couldn't get this to work for some reason...
|
//Couldn't get this to work for some reason...
|
||||||
//if (usbfuncwrite == RESETME ) {
|
// if (usbfuncwrite == RESETME ) {
|
||||||
// SCB->AIRCR = 0x05FA0004;
|
// SCB->AIRCR = 0x05FA0004;
|
||||||
//}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
asm( "b fwupdateloop\n"
|
asm( "b fwupdateloop\n"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,15 @@ USBDESC const uint8_t device_desc[DEVICE_DESC_LEN] = {
|
||||||
// 12 bcdDevice 2 BCD Device Release Number
|
// 12 bcdDevice 2 BCD Device Release Number
|
||||||
//0x00, 0x02, early development version
|
//0x00, 0x02, early development version
|
||||||
//0x01, 0x02, //first public release 7SEP2018
|
//0x01, 0x02, //first public release 7SEP2018
|
||||||
0x02, 0x02, //second public release 16NOV2018
|
//0x02, 0x02, //second public release 16NOV2018
|
||||||
|
0x03, 0x02, //third public release 30NOV2018
|
||||||
|
//v2.3 is first to contain switchless USB firmware updates
|
||||||
|
//application version numbers also included in this release
|
||||||
|
//application version are meant to tack onto end of usb version
|
||||||
|
//application version 0 is being released with this build
|
||||||
|
//so we'll be at v2.3.0 application versions is expected to
|
||||||
|
//increment while maintaining usb/fwupater v2.3
|
||||||
|
|
||||||
// 14 iManufacturer 1 Index Index of Manufacturer String Descriptor
|
// 14 iManufacturer 1 Index Index of Manufacturer String Descriptor
|
||||||
0x01,
|
0x01,
|
||||||
// 15 iProduct 1 Index Index of Product String Descriptor
|
// 15 iProduct 1 Index Index of Product String Descriptor
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,13 @@ local fwupdate = {}
|
||||||
|
|
||||||
-- import required modules
|
-- import required modules
|
||||||
local dict = require "scripts.app.dict"
|
local dict = require "scripts.app.dict"
|
||||||
|
local help = require "scripts.app.help"
|
||||||
|
|
||||||
-- file constants
|
-- file constants
|
||||||
|
|
||||||
-- local functions
|
-- local functions
|
||||||
|
|
||||||
|
|
||||||
local function erase_main()
|
local function erase_main()
|
||||||
|
|
||||||
--dict.fwupdate("ERASE_1KB_PAGE", 2) --page 0 & 1 (first 2KByte) are forbidden
|
--dict.fwupdate("ERASE_1KB_PAGE", 2) --page 0 & 1 (first 2KByte) are forbidden
|
||||||
|
|
@ -40,47 +43,47 @@ end
|
||||||
|
|
||||||
local function update_firmware(newbuild)
|
local function update_firmware(newbuild)
|
||||||
|
|
||||||
print("updating")
|
local error = false
|
||||||
|
|
||||||
|
|
||||||
--open new file first, don't bother continuing if can't find it.
|
--open new file first, don't bother continuing if can't find it.
|
||||||
file = assert(io.open(newbuild, "rb"))
|
file = assert(io.open(newbuild, "rb"))
|
||||||
|
|
||||||
--TODO verify the first 2KByte match, don't continue if not..
|
--TODO read the fwupdater & app version from the provided file
|
||||||
|
--compare to current device and determine if they're compatible
|
||||||
|
--test let's tinker with SRAM
|
||||||
|
dict.bootload("SET_PTR_HI", 0x0800)
|
||||||
|
dict.bootload("SET_PTR_LO", 0x0800) --application version 0x08000800 "AV00"
|
||||||
|
local av = dict.bootload("RD_PTR_OFFSET")
|
||||||
|
local ver = dict.bootload("RD_PTR_OFFSET",1)
|
||||||
|
local avstring = string.format("%s%s%s%s", string.char(av&0x00FF), string.char(av>>8),
|
||||||
|
string.char(ver&0x00FF), string.char(ver>>8))
|
||||||
|
|
||||||
--enter fwupdate mode
|
if avstring == "AV00" then
|
||||||
dict.bootload("PREP_FWUPDATE")
|
print("application version:", avstring)
|
||||||
|
else
|
||||||
|
print("app version", avstring, "unknown, may need to update to firmware v2.3 or later using STmicro dfuse")
|
||||||
|
end
|
||||||
|
|
||||||
--now the device will only respond to FWUPDATE dictionary commands
|
|
||||||
|
--verify the first 2KByte match, don't continue if not..
|
||||||
|
--use the bootload dictionary to complete this
|
||||||
|
--want to wait to enter firmware updater
|
||||||
|
|
||||||
--erase 30KByte of application code
|
--set bootloader 16bit pointer to start of flash
|
||||||
erase_main()
|
dict.bootload("SET_PTR_HI", 0x0800)
|
||||||
|
dict.bootload("SET_PTR_LO", 0x0000)
|
||||||
--Set FLASH->AR to beginging of application section
|
local offset = 0 --first read has no offset
|
||||||
--this can be done be re-erasing it..
|
|
||||||
--maybe we could have skipped page 2 in erase_main
|
|
||||||
--or have erase_main count down..
|
|
||||||
dict.fwupdate("ERASE_1KB_PAGE", 2)
|
|
||||||
rv = dict.fwupdate("GET_FLASH_ADDR")
|
|
||||||
print("flash addr:", string.format("%X", rv) )
|
|
||||||
print("\n");
|
|
||||||
|
|
||||||
--advance the file past first 2KByte
|
--advance the file past first 2KByte
|
||||||
local buffsize = 1
|
local buffsize = 1
|
||||||
local byte, data
|
local byte, data
|
||||||
local byte_num = 0
|
local byte_num = 0
|
||||||
for byte in file:lines(buffsize) do
|
|
||||||
data = string.unpack("B", byte, 1)
|
|
||||||
--print(string.format("%X", data))
|
|
||||||
byte_num = byte_num + 1
|
|
||||||
if byte_num == 2048 then break end
|
|
||||||
end
|
|
||||||
|
|
||||||
local offset = 0
|
|
||||||
local readdata
|
local readdata
|
||||||
local data_l
|
local data_l
|
||||||
buffsize = 1 --2 bytes at a time
|
|
||||||
print("Writting half word at at time, but it's not much data..")
|
print("Verifing first 2KByte of updater..")
|
||||||
while byte_num < (32*1024) do
|
while byte_num < (2*1024) do
|
||||||
|
|
||||||
--read next byte from the file and convert to binary
|
--read next byte from the file and convert to binary
|
||||||
--gotta be a better way to read a half word (16bits) at a time but don't care right now...
|
--gotta be a better way to read a half word (16bits) at a time but don't care right now...
|
||||||
|
|
@ -90,99 +93,125 @@ local function update_firmware(newbuild)
|
||||||
else
|
else
|
||||||
--should only have to make this check for lower byte
|
--should only have to make this check for lower byte
|
||||||
--binary file should be even
|
--binary file should be even
|
||||||
print("end of file")
|
print("There's a problem, file provided is smaller than 2KB fwupdater..")
|
||||||
|
--TODO test this
|
||||||
|
error = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
byte_str = file:read(buffsize)
|
byte_str = file:read(buffsize)
|
||||||
data = string.unpack("B", byte_str, 1)
|
data = string.unpack("B", byte_str, 1)
|
||||||
data = (data<<8)+data_l
|
data = (data<<8)+data_l
|
||||||
-- print("writting:", string.format("%X", data), "addr:", string.format("%X", byte_num))
|
|
||||||
|
|
||||||
if( (byte_num % (4*1024)) == 0 ) then
|
if (true) then
|
||||||
print("flashing KB", byte_num/1024)
|
--both these options work, but the later is limited to reading 64KByte space
|
||||||
|
readdata = dict.bootload("RD_PTR_OFF_UP", offset)
|
||||||
|
--readdata = dict.bootload("RD_PTR_OFFSET", byte_num>>1) --shift by one 16bit read
|
||||||
|
|
||||||
|
-- print("read data:", string.format("%X", readdata) )
|
||||||
|
if readdata ~= data then
|
||||||
|
print("\n\nERROR!!!! verifying byte number", help.hex(byte_num),
|
||||||
|
" to flash expected:", help.hex(data), "was:", help.hex(readdata))
|
||||||
|
print("exiting because it's not safe to proceed...")
|
||||||
|
print("no changes to device flash were made\n\n")
|
||||||
|
|
||||||
|
error = true
|
||||||
|
break
|
||||||
|
--else
|
||||||
|
-- print("verified byte number", help.hex(byte_num),
|
||||||
|
-- " of flash ", help.hex(data), help.hex(readdata))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--write the data
|
|
||||||
dict.fwupdate("WR_HWORD", data, offset)
|
|
||||||
|
|
||||||
-- if (verify) then
|
|
||||||
-- readdata = dict.fwupdate("READ_FLASH", byte_num, 0x00)
|
|
||||||
-- print("read data:", string.format("%X", rv) )
|
|
||||||
-- if readdata ~= data then
|
|
||||||
-- print("ERROR flashing byte number", byte_num, " to flash ", data, readdata)
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
offset = 1 --this is zero for first byte, but one for all others..
|
offset = 1 --this is zero for first byte, but one for all others..
|
||||||
byte_num = byte_num + 2
|
byte_num = byte_num + 2
|
||||||
end
|
end
|
||||||
--]]
|
|
||||||
|
|
||||||
-- dict.fwupdate("WR_HWORD", 0xCC33, 0x00)
|
if (not error) then
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
print("\nSuccessfully verified first 2KB of provided file")
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
print("matches the device's firmware updater section\n")
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
end
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
|
||||||
-- print("\n");
|
--enter fwupdate mode
|
||||||
-- print("\n");
|
dict.bootload("PREP_FWUPDATE")
|
||||||
--
|
|
||||||
-- dict.fwupdate("WR_HWORD", 0x1111, 0x01)
|
--now the device will only respond to FWUPDATE dictionary commands
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
--erase 30KByte of application code
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
if (not error) then
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
erase_main()
|
||||||
-- print("\n");
|
end
|
||||||
--
|
|
||||||
-- dict.fwupdate("WR_HWORD", 0x2222, 0x01)
|
--Set FLASH->AR to beginging of application section
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
--this can be done be re-erasing it..
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
--maybe we could have skipped page 2 in erase_main
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
--or have erase_main count down..
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
if (not error) then
|
||||||
-- print("\n");
|
dict.fwupdate("ERASE_1KB_PAGE", 2)
|
||||||
--
|
print("flash addr:", help.hex(dict.fwupdate("GET_FLASH_ADDR")))
|
||||||
-- dict.fwupdate("WR_HWORD", 0x4444, 0x02)
|
print("\n");
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
end
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
offset = 0 --first write has no offset
|
||||||
-- print("\n");
|
|
||||||
--
|
if (not error) then
|
||||||
-- dict.fwupdate("WR_HWORD", 0x7777, 0x03)
|
print("Updating device main application flash..")
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
while byte_num < (32*1024) do
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
--read next byte from the file and convert to binary
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
--gotta be a better way to read a half word (16bits) at a time but don't care right now...
|
||||||
-- print("\n");
|
byte_str = file:read(buffsize)
|
||||||
--
|
if byte_str then
|
||||||
-- dict.fwupdate("WR_HWORD", 0xAAAA, 0x10)
|
data_l = string.unpack("B", byte_str, 1)
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
else
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
--should only have to make this check for lower byte
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
--binary file should be even
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
print("end of file")
|
||||||
-- print("\n");
|
break
|
||||||
--
|
end
|
||||||
-- dict.fwupdate("WR_HWORD", 0xBBBB, 0x20)
|
byte_str = file:read(buffsize)
|
||||||
-- rv = dict.fwupdate("GET_FLASH_ADDR")
|
data = string.unpack("B", byte_str, 1)
|
||||||
-- print("flash addr:", string.format("%X", rv) )
|
data = (data<<8)+data_l
|
||||||
-- rv = dict.fwupdate("GET_FLASH_DATA")
|
|
||||||
-- print("flash data:", string.format("%X", rv) )
|
if( (byte_num % (4*1024)) == 0 ) then
|
||||||
-- print("\n");
|
print("flashing KB", byte_num/1024)
|
||||||
--
|
end
|
||||||
---- dict.fwupdate("LOCK_FLASH")
|
|
||||||
--
|
--print("writting:", string.format("%X", data), "addr:", string.format("%X", byte_num))
|
||||||
-- rv = dict.fwupdate("READ_FLASH", 0x0000, 0x00)
|
|
||||||
-- print("read data:", string.format("%X", rv) )
|
--write the data
|
||||||
--
|
dict.fwupdate("WR_HWORD", data, offset)
|
||||||
-- rv = dict.fwupdate("READ_FLASH", 0x053e, 0x00)
|
|
||||||
-- print("read data:", string.format("%X", rv) )
|
if (true) then
|
||||||
--
|
readdata = dict.fwupdate("READ_FLASH", byte_num, 0x00)
|
||||||
-- rv = dict.fwupdate("READ_FLASH", 0x791a, 0x00)
|
-- print("read data:", string.format("%X", readdata) )
|
||||||
-- print("read data:", string.format("%X", rv) )
|
if readdata ~= data then
|
||||||
|
print("\n\nERROR!!!! flashing byte number", help.hex(byte_num),
|
||||||
|
" to flash expected:", help.hex(data), "was:", help.hex(readdata))
|
||||||
|
print("exiting before causing more damage...\n\n")
|
||||||
|
error = true
|
||||||
|
break
|
||||||
|
--else
|
||||||
|
-- print("verified byte number", help.hex(byte_num),
|
||||||
|
-- " to flash ", help.hex(data), help.hex(readdata))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
offset = 1 --this is zero for first write, but one for all others..
|
||||||
|
byte_num = byte_num + 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (not error) then
|
||||||
|
print("\nSuccessfully updated the device firmware!")
|
||||||
|
end
|
||||||
|
|
||||||
--close file
|
--close file
|
||||||
assert(file:close())
|
assert(file:close())
|
||||||
print("\n\n DONE updating flash. \n\n Reseting device \n\n IGNORE the error that comes next.. \n\n")
|
|
||||||
|
|
||||||
|
print("\n\n DONE, Reseting device \n\n IGNORE the errors that comes next.. \n\n")
|
||||||
|
|
||||||
|
--TODO maybe don't reset if we got an error, allow for correction while fwupdate still has control..?
|
||||||
dict.fwupdate("RESET_DEVICE")
|
dict.fwupdate("RESET_DEVICE")
|
||||||
|
|
||||||
--write build to flash
|
--write build to flash
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ function main ()
|
||||||
-- =====================================================
|
-- =====================================================
|
||||||
-- USERS: set cart_console to the to point to the mapper script you would like to use here.
|
-- USERS: set cart_console to the to point to the mapper script you would like to use here.
|
||||||
-- =====================================================
|
-- =====================================================
|
||||||
--local cart_console = "NES" --includes Famicom
|
local cart_console = "NES" --includes Famicom
|
||||||
--local cart_console = "SNES"
|
--local cart_console = "SNES"
|
||||||
--local cart_console = "SEGA"
|
--local cart_console = "SEGA"
|
||||||
--local cart_console = "N64"
|
--local cart_console = "N64"
|
||||||
|
|
@ -148,7 +148,14 @@ function main ()
|
||||||
|
|
||||||
--Firmware update testing
|
--Firmware update testing
|
||||||
|
|
||||||
fwupdate.update_firmware("../firmware/build_stm/inlretro_stm.bin")
|
--active development path (based on makefile in use)
|
||||||
|
--fwupdate.update_firmware("../firmware/build_stm/inlretro_stm.bin")
|
||||||
|
|
||||||
|
--released INL6 path (big square boards)
|
||||||
|
fwupdate.update_firmware("../firmware/build_stm6/inlretro_stm_AV00.bin")
|
||||||
|
|
||||||
|
--released INL_N path (smaller NESmaker boards)
|
||||||
|
--fwupdate.update_firmware("../firmware/build_stmn/inlretro_stm_AV00.bin")
|
||||||
|
|
||||||
|
|
||||||
-- debug = true
|
-- debug = true
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,76 @@
|
||||||
// BOOTLOAD DICTIONARY
|
// BOOTLOAD DICTIONARY
|
||||||
//
|
//
|
||||||
// opcodes contained in this dictionary must be implemented in firmware/source/bootload.c
|
// opcodes contained in this dictionary must be implemented in firmware/source/bootload.c
|
||||||
|
// these opcodes are currently only defined for STM32 devices
|
||||||
|
// AVR devices use their own dedicated & entirely separate bootloader handled via switch
|
||||||
//
|
//
|
||||||
//=============================================================================================
|
//=============================================================================================
|
||||||
//=============================================================================================
|
//=============================================================================================
|
||||||
|
|
||||||
|
|
||||||
//BOOTLOAD opcodes
|
//BOOTLOAD opcodes
|
||||||
#define JUMP_BL 1 //jump to the bootloader
|
|
||||||
|
|
||||||
#define LOAD_ADDRH 2 //upper address of jump
|
//could never get this to work so just going to cut it out
|
||||||
|
//#define JUMP_BL 1 //jump to the bootloader
|
||||||
|
|
||||||
|
#define LOAD_ADDRH 2 //upper address half word used for various functions
|
||||||
#define JUMP_ADDR 3 //jump to address upper 16bit provided previous opcode
|
#define JUMP_ADDR 3 //jump to address upper 16bit provided previous opcode
|
||||||
|
|
||||||
#define PREP_FWUPDATE 4 //leave main application and sets up for fwupdate
|
#define PREP_FWUPDATE 4 //leave main application and sets up for fwupdate
|
||||||
|
|
||||||
|
|
||||||
|
// POINTER READ/WRITE ACCESS
|
||||||
|
// With great power comes great responsibility
|
||||||
|
// these opcodes perform direct read/write access of the STM32 address space
|
||||||
|
// you can litterally read/write any address
|
||||||
|
// accessing restricted areas will cause hardfaults
|
||||||
|
// don't think it's really possible to brick the device using any of these
|
||||||
|
// worst case you could corrupt flash if you halfway know what you're doing
|
||||||
|
// so long as you don't mess up the option bytes to disable the BOOT pin
|
||||||
|
// you'll be able to recover the device using bootloader jumper/switch
|
||||||
|
// via stmicro dfuse demo
|
||||||
|
|
||||||
|
// this could actually be pretty handy for mcu debugging.
|
||||||
|
// allowing for reading of registers, memory, etc between dictionary calls
|
||||||
|
//
|
||||||
|
// TODO for this use including AVR support is actually a good idea
|
||||||
|
// but need to be extra careful there as bricking an AVR could
|
||||||
|
// permanently brick it to where not even an AVR programmer could save it
|
||||||
|
// atleast the mcu socketed.. Bricking it would be difficult to do accidentally.
|
||||||
|
// More of a concern if one were tinkering with fuses and such.
|
||||||
|
// Don't feel like learning the AVR memory map enough to add this support
|
||||||
|
// at the moment. Perhaps much of the ARM code will compile and work fine
|
||||||
|
// on the AVR..?
|
||||||
|
|
||||||
|
//operand provides 16bit value for RD/WR commands below
|
||||||
|
#define SET_PTR_HI 5
|
||||||
|
#define SET_PTR_LO 6
|
||||||
|
#define GET_PTR 7 //RL=6
|
||||||
|
|
||||||
|
//ALL OFFSETS ARE INTERPRETED AT POSITIVE UNSIGNED!
|
||||||
|
//read 16bit value from memory location being pointed to
|
||||||
|
//operand provides offset from current pointer, but doesn't modify the pointer
|
||||||
|
#define RD_PTR_OFFSET 8 //RL=4 0-error, 1-len, 2-LSB, 3-MSB
|
||||||
|
//operand provides 16bit value to be written, miscdata provides offset
|
||||||
|
#define WR_PTR_OFFSET 9
|
||||||
|
|
||||||
|
//operand provides 16bit offset which is added to ptr before access
|
||||||
|
//then reads from that address
|
||||||
|
#define RD_PTR_OFF_UP 10 //RL=4 0-error, 1-len, 2-LSB, 3-MSB
|
||||||
|
|
||||||
|
//miscdata provide 8bit offset which is added to ptr before access
|
||||||
|
//operand is the 16bit value which is written to memory location being pointed to
|
||||||
|
#define WR_PTR_OFF_UP 11
|
||||||
|
|
||||||
|
//application code version
|
||||||
|
//this is updated more frequently than the USB firmware version
|
||||||
|
//#define GET_APP_VER 12 //RL=3 0-error, 1-len, 2-version
|
||||||
|
//just set pointer to 0x08000800 and read 4 bytes for now
|
||||||
|
|
||||||
|
//APPLICATION VERSION NUMBERS
|
||||||
|
//#define APP_VERSION "AV00" //released with usb firmware v2.3
|
||||||
|
//main update was addition of usb firmware updater
|
||||||
|
//also added the bootloader pointer memory access
|
||||||
|
//include ram functions & starting to have NES flash algos return data
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue