Pelrun, thank you very much for all the hard work! I appreciate you and your time that you put into this amazing piece of software! Cheers mate!
V2.1 is now released, should resolve quite a few papercuts.
I’ve not actually tested the Pico 1 build here yet (it requires changing the bulb), so let me know if you try it and it loses the plot.
@adcockm - give this a try, you can press F1 or F5 to get into the menu, it should be a lot less finicky. Also, were you using the original Lexar card or a replacement? That would have also caused the menu to fail to boot - but should also be fixed now. And it doesn’t just drop into the application anymore if the menu boot fails - it’ll end up in BOOTSEL instead. So you should at least know the boot was attempted.
I just downloaded 2.1 and tried again. Unfortunately, I am having the same issuel. I’ve tried loading the original official PicoMite 6.00.02x from ClockworkPi and MicroPython as well as Geoff’s newer PicoMite 6.000.03. I get the black screen for both versions of PicoMite and the flashing screen text for MicroPython. Sorry. Thanks for your continuing work though. If I can help in any way with testing, let me know.
Hey, this works great with my other SanDisk card that did not work before. Thank you!
I was wondering if you could ignore uf2 files that start with . or files with the hidden attribute? MacOS barfs ._?????.uf2 files into the pico?-apps folder every time I copy a UF2 in there and I need to go to a shell and manually remove them.
This isn’t something that can be directly addressed inside the bootloader - those applications are just incompatible with running inside a partition right now and will require modification.
I’ve pushed a single-line change that hides dotfiles.
Uuurgh, every time I think I know what to expect when I look at the MMBasic source code, it’s always so much worse.
Why write the same code once when you can write it fifty times across a half-dozen files? ![]()
Yeah, it’s… not good. Part of me wants to try to clean some of it up, but I know that would make future updates of the PicoCalc fork difficult since I seriously doubt any improvements would be included. There have been a few PRs submited by others, and unsurprisingly, they won’t be included.
I tried your updated bootloader with the fixes and new keyboard key checks, and I still can’t get the menu to come up (or bootsel to happen) when I hold down any of the keys after picking an option and power cycling. I’m using the Lexar card that came with the PicoCalc, but since the boot menu appears the first time and lets me select, flash, and boot into a firmware, I’m assuming the card is not the problem? I did a similar test as before, choosing the text-starter, bringing it up, then powering off, and holding any of the new buttons down when powering on and still got nothing.
Regarding PicoMite, since this is new territory for me I read up on the flash APIs and made some changes that I thought should work for the Pico2 at least. (It doesn’t even build for the Pico anymore, so I’ll need to block this new stuff out with ifdefs (which I should have done anyway to keep it clean, but I was just trying to get something working first), and then figure out what can be done to get the Pico build working after that. While WebMite and PicoMite build without errors or any unusual warnings, when I try to boot them either directly, or through the loader, they fail with a black screen. So I’m doing something incorrectly in my changes, or I’m missing something.
Any ideas on what I’m doing wrong here in PicoMite? I tried using the CFLASH_ASPACE_VALUE_STORAGE flag without any of the XIP_BASE offsets first (since that matched more closely to what had been done before), but that resulted in a similar problem where it just hung on a black screen. But switching to CFLASH_ASPACE_VALUE_RUNTIME and the offsets didn’t seem to help.
I based this on some example code here in the SDK.
diff --git a/Audio.c b/Audio.c
index 752f504..dab35f7 100644
--- a/Audio.c
+++ b/Audio.c
@@ -38,6 +38,9 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "hardware/flash.h"
+#include "pico/stdlib.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#include "MMBasic_Includes.h"
#include "Hardware_Includes.h"
#define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
@@ -1838,7 +1841,8 @@ void MIPS16 cmd_play(void) {
positionfile(WAV_fnbr,0);
uint32_t j = RoundUpK4(TOP_OF_SYSTEM_FLASH);
disable_interrupts_pico();
- flash_range_erase(j, RoundUpK4(fsize));
+ int r2 = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, RoundUpK4(fsize), NULL);
enable_interrupts_pico();
while(!FileEOF(WAV_fnbr)) {
memset(r,0,256) ;
@@ -1847,7 +1851,10 @@ void MIPS16 cmd_play(void) {
r[i] = FileGetChar(WAV_fnbr);
}
disable_interrupts_pico();
- flash_range_program(j, (uint8_t *)r, 256);
+ if (r == 0) {
+ r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + j, 256, (uint8_t *)r);
+ }
enable_interrupts_pico();
routinechecks();
j+=256;
diff --git a/Commands.c b/Commands.c
index 712c474..49a407c 100644
--- a/Commands.c
+++ b/Commands.c
@@ -37,6 +37,9 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#include "MMBasic_Includes.h"
#include "Hardware_Includes.h"
#include "hardware/flash.h"
+#include "pico/stdlib.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#include "hardware/dma.h"
#include "hardware/structs/watchdog.h"
#ifdef PICOMITE
@@ -1038,7 +1041,8 @@ void MIPS16 cmd_new(void) {
FlashLoad=0;
uSec(250000);
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
FlashWriteByte(0); FlashWriteByte(0); FlashWriteByte(0); // terminate the program in flash
FlashWriteClose();
#ifdef PICOMITEVGA
diff --git a/FileIO.c b/FileIO.c
index 266fc8e..9e5fca2 100644
--- a/FileIO.c
+++ b/FileIO.c
@@ -37,6 +37,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#include "diskio.h"
#include "pico/stdlib.h"
#include "hardware/flash.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#include "hardware/irq.h"
#include "hardware/gpio.h"
#include "pico/binary_info.h"
@@ -375,10 +377,10 @@ int __not_in_flash_func(fs_flash_prog)(const struct lfs_config *cfg, lfs_block_t
assert(off % cfg->prog_size == 0);
assert(size % cfg->prog_size == 0);
assert(block < cfg->block_count);
-
uint32_t addr = RoundUpK4(TOP_OF_SYSTEM_FLASH) + (Option.modbuff ? 1024*Option.modbuffsize : 0) + block*4096 + off;
disable_interrupts_pico();
- flash_range_program(addr, buffer, size);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + addr, size, (uint8_t *)buffer);
enable_interrupts_pico();
return 0;
}
@@ -386,8 +388,9 @@ int __not_in_flash_func(fs_flash_erase)(const struct lfs_config *cfg, lfs_block_
assert(block < cfg->block_count);
uint32_t block_addr = RoundUpK4(TOP_OF_SYSTEM_FLASH) + (Option.modbuff ? 1024*Option.modbuffsize : 0) + block*4096;
- disable_interrupts_pico();
- flash_range_erase(block_addr, BLOCK_SIZE);
+ disable_interrupts_pico();
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + block_addr, BLOCK_SIZE, NULL);
enable_interrupts_pico();
return 0;
}
@@ -530,7 +533,8 @@ void MIPS16 cmd_psram(void)
error("Invalid in program");
int j = (Option.PROG_FLASH_SIZE >> 2), i = getint(p, 1, MAXRAMSLOTS);
disable_interrupts_pico();
- flash_range_erase(PROGSTART, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + PROGSTART, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
j = (MAX_PROG_SIZE >> 2);
uSec(250000);
@@ -547,7 +551,8 @@ void MIPS16 cmd_psram(void)
{
enable_interrupts_pico();
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
FlashWriteByte(0);
FlashWriteByte(0);
FlashWriteByte(0); // terminate the program in flash
@@ -558,7 +563,8 @@ void MIPS16 cmd_psram(void)
{
for (int j = 0; j < 4096; j++)
writebuff[j] = *q++;
- flash_range_program((PROGSTART + k), writebuff, 4096);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + (PROGSTART + k), 4096, (uint8_t *)writebuff);
}
enable_interrupts_pico();
FlashLoad = 0;
@@ -607,7 +613,8 @@ void MIPS16 cmd_flash(void)
for (int i = 0; i < k; i++)
{
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + (i * MAX_PROG_SIZE);
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
}
enable_interrupts_pico();
}
@@ -620,7 +627,8 @@ void MIPS16 cmd_flash(void)
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE);
uSec(250000);
disable_interrupts_pico();
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
}
else if ((p = checkstring(cmdline, (unsigned char *)"OVERWRITE")))
@@ -632,7 +640,8 @@ void MIPS16 cmd_flash(void)
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE);
uSec(250000);
disable_interrupts_pico();
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
j = (MAX_PROG_SIZE >> 2);
uSec(250000);
@@ -649,7 +658,8 @@ void MIPS16 cmd_flash(void)
{
for (int j = 0; j < 4096; j++)
writebuff[j] = *q++;
- flash_range_program(FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE + k), writebuff, 4096);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE + k), 4096, (uint8_t *)writebuff);
}
enable_interrupts_pico();
}
@@ -735,7 +745,8 @@ void MIPS16 cmd_flash(void)
char *r = GetTempMemory(256);
uint32_t j = RoundUpK4(TOP_OF_SYSTEM_FLASH);
disable_interrupts_pico();
- flash_range_erase(j, RoundUpK4(fsize));
+ int r2 = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, RoundUpK4(fsize), NULL);
enable_interrupts_pico();
while(!FileEOF(fnbr)) {
memset(r,0,256) ;
@@ -744,7 +755,8 @@ void MIPS16 cmd_flash(void)
r[i] = FileGetChar(fnbr);
}
disable_interrupts_pico();
- flash_range_program(j, (uint8_t *)r, 256);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + j, 256, (uint8_t *)r);
enable_interrupts_pico();
routinechecks();
j+=256;
@@ -773,7 +785,8 @@ void MIPS16 cmd_flash(void)
else fsize = lfs_file_size(&lfs,FileTable[fnbr].lfsptr);
if(fsize>MAX_PROG_SIZE)error("File size % cannot exceed %",fsize,MAX_PROG_SIZE);
FlashWriteInit(i);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
int j=MAX_PROG_SIZE/4;
int *ppp=(int *)(flash_target_contents + (i - 1) * MAX_PROG_SIZE);
while(j--)if(*ppp++ != 0xFFFFFFFF){
@@ -799,7 +812,8 @@ void MIPS16 cmd_flash(void)
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE);
uSec(250000);
disable_interrupts_pico();
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
j = (MAX_PROG_SIZE >> 2);
uSec(250000);
@@ -816,7 +830,8 @@ void MIPS16 cmd_flash(void)
{
for (int j = 0; j < 4096; j++)
writebuff[j] = *q++;
- flash_range_program(FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE + k), (uint8_t *)writebuff, 4096);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((i - 1) * MAX_PROG_SIZE + k), 4096, (uint8_t *)writebuff);
}
enable_interrupts_pico();
}
@@ -827,7 +842,8 @@ void MIPS16 cmd_flash(void)
int j = (Option.PROG_FLASH_SIZE >> 2), i = getint(p, 1, MAXFLASHSLOTS);
if(Option.LIBRARY_FLASH_SIZE==MAX_PROG_SIZE && i==MAXFLASHSLOTS) error("Library is using Slot % ",MAXFLASHSLOTS);
disable_interrupts_pico();
- flash_range_erase(PROGSTART, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + PROGSTART, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
j = (MAX_PROG_SIZE >> 2);
uSec(250000);
@@ -844,7 +860,8 @@ void MIPS16 cmd_flash(void)
{
enable_interrupts_pico();
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
FlashWriteByte(0);
FlashWriteByte(0);
FlashWriteByte(0); // terminate the program in flash
@@ -855,7 +872,8 @@ void MIPS16 cmd_flash(void)
{
for (int j = 0; j < 4096; j++)
writebuff[j] = *q++;
- flash_range_program((PROGSTART + k), writebuff, 4096);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + (PROGSTART + k), 4096, (uint8_t *)writebuff);
}
enable_interrupts_pico();
FlashLoad = 0;
@@ -4542,7 +4560,8 @@ void cmd_autosave(void)
FlashLoad=0;
uSec(250000);
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
FlashWriteByte(0); FlashWriteByte(0); FlashWriteByte(0); // terminate the program in flash
FlashWriteClose();
if (*cmdline)
@@ -5164,11 +5183,13 @@ void ResetAllFlash(void)
for (int i = 0; i < MAXFLASHSLOTS + 1; i++)
{
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + (i * MAX_PROG_SIZE);
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
}
enable_interrupts_pico();
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
FlashWriteByte(0);
FlashWriteByte(0);
FlashWriteByte(0); // terminate the program in flash
@@ -5194,7 +5215,8 @@ void FlashWriteBlock(void)
int i;
uint32_t address = realflashpointer - 256;
// if(address % 32)error("Memory write address");
- flash_range_program((const uint32_t)address, (const uint8_t *)&MemWord.i64[0], 256);
+ int r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + address, 256, (uint8_t *)&MemWord.i64[0]);
for (i = 0; i < 64; i++)
MemWord.i32[i] = 0xFFFFFFFF;
}
@@ -5478,7 +5500,8 @@ void ClearSavedVars(void)
{
uSec(250000);
disable_interrupts_pico();
- flash_range_erase(FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE, SAVEDVARS_FLASH_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE, SAVEDVARS_FLASH_SIZE, NULL);
enable_interrupts_pico();
uSec(10000);
}
@@ -5486,11 +5509,15 @@ void SaveOptions(void)
{
uSec(100000);
disable_interrupts_pico();
- flash_range_erase(FLASH_TARGET_OFFSET, FLASH_ERASE_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET, FLASH_ERASE_SIZE, NULL);
enable_interrupts_pico();
uSec(10000);
disable_interrupts_pico();
- flash_range_program(FLASH_TARGET_OFFSET, (const uint8_t *)&Option, sizeof(struct option_s));
+ if (r == 0) {
+ r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET, sizeof(struct option_s), (uint8_t *)&Option);
+ }
enable_interrupts_pico();
}
/* @endcond */
diff --git a/MMBasic.c b/MMBasic.c
index 8a4d48d..d7e1e80 100644
--- a/MMBasic.c
+++ b/MMBasic.c
@@ -38,6 +38,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#include "Custom.h"
#include "Hardware_Includes.h"
#include "hardware/flash.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#ifndef PICOMITEWEB
#include "pico/multicore.h"
#endif
@@ -430,7 +432,8 @@ int MIPS16 PrepareProgramExt(unsigned char *p, int i, unsigned char **CFunPtr,
if(tkn == cmdSUB || tkn == cmdFUN /*|| tkn == cmdCFUN*/ || tkn == cmdCSUB) { // found a SUB, FUN, CFUNCTION or CSUB token
if(i >= MAXSUBFUN) {
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
int j=MAX_PROG_SIZE/4;
int *pp=(int *)(flash_progmemory);
while(j--)if(*pp++ != 0xFFFFFFFF){
diff --git a/MMBasic.h b/MMBasic.h
index 93bb975..0fa4eba 100644
--- a/MMBasic.h
+++ b/MMBasic.h
@@ -332,6 +332,22 @@ int mem_equal(unsigned char *s1, unsigned char *s2, int i);
extern int emptyarray;
typedef uint16_t CommandToken;
+#include "pico/bootrom.h"
+static inline cflash_flags_t op_prog_runtime(void) {
+ cflash_flags_t f;
+ f.flags = (CFLASH_OP_VALUE_PROGRAM << CFLASH_OP_LSB) |
+ (CFLASH_SECLEVEL_VALUE_SECURE << CFLASH_SECLEVEL_LSB) |
+ (CFLASH_ASPACE_VALUE_RUNTIME << CFLASH_ASPACE_LSB);
+ return f;
+}
+static inline cflash_flags_t op_erase_runtime(void) {
+ cflash_flags_t f;
+ f.flags = (CFLASH_OP_VALUE_ERASE << CFLASH_OP_LSB) |
+ (CFLASH_SECLEVEL_VALUE_SECURE << CFLASH_SECLEVEL_LSB) |
+ (CFLASH_ASPACE_VALUE_RUNTIME << CFLASH_ASPACE_LSB);
+ return f;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/MM_Misc.c b/MM_Misc.c
index 3739ff5..9d6a093 100644
--- a/MM_Misc.c
+++ b/MM_Misc.c
@@ -39,6 +39,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#include "hardware/adc.h"
#include "hardware/pwm.h"
#include "hardware/flash.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#include "hardware/spi.h"
#include "hardware/pio.h"
#include "hardware/pio_instructions.h"
@@ -1640,7 +1642,8 @@ void MIPS16 cmd_library(void) {
//now write the library from ram to the library flash area
// initialise for writing to the flash
FlashWriteInit(LIBRARY_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
i=MAX_PROG_SIZE/4;
int *ppp=(int *)(flash_progmemory - MAX_PROG_SIZE);
@@ -1681,7 +1684,8 @@ void MIPS16 cmd_library(void) {
if(Option.LIBRARY_FLASH_SIZE != MAX_PROG_SIZE) return;
FlashWriteInit(LIBRARY_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
i=MAX_PROG_SIZE/4;
int *ppp=(int *)(flash_progmemory - MAX_PROG_SIZE);
@@ -1774,7 +1778,8 @@ void MIPS16 cmd_library(void) {
else fsize = lfs_file_size(&lfs,FileTable[fnbr].lfsptr);
if(fsize>MAX_PROG_SIZE)error("File size % should be % or less",fsize,MAX_PROG_SIZE);
FlashWriteInit(LIBRARY_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
int i=MAX_PROG_SIZE/4;
int *ppp=(int *)(flash_progmemory - MAX_PROG_SIZE);
while(i--)if(*ppp++ != 0xFFFFFFFF){
@@ -4655,11 +4660,15 @@ tp = checkstring(cmdline, (unsigned char *)"HEARTBEAT");
FileClose(fnbr);
uSec(100000);
disable_interrupts_pico();
- flash_range_erase(FLASH_TARGET_OFFSET, FLASH_ERASE_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET, FLASH_ERASE_SIZE, NULL);
enable_interrupts_pico();
uSec(10000);
disable_interrupts_pico();
- flash_range_program(FLASH_TARGET_OFFSET, (const uint8_t *)&Option, 768);
+ if (r == 0) {
+ r = rom_flash_op(op_prog_runtime(),
+ XIP_BASE + FLASH_TARGET_OFFSET, 768, (uint8_t *)&Option);
+ }
enable_interrupts_pico();
_excep_code = RESET_COMMAND;
SoftReset();
@@ -4671,7 +4680,8 @@ tp = checkstring(cmdline, (unsigned char *)"HEARTBEAT");
uint32_t j = FLASH_TARGET_OFFSET + FLASH_ERASE_SIZE + SAVEDVARS_FLASH_SIZE + ((MAXFLASHSLOTS - 1) * MAX_PROG_SIZE);
uSec(250000);
disable_interrupts_pico();
- flash_range_erase(j, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + j, MAX_PROG_SIZE, NULL);
enable_interrupts_pico();
}
configure(tp);
diff --git a/PicoMite.c b/PicoMite.c
index 686c5d8..b8c87c2 100644
--- a/PicoMite.c
+++ b/PicoMite.c
@@ -34,6 +34,8 @@ extern "C" {
#include "hardware/watchdog.h"
#include "hardware/clocks.h"
#include "hardware/flash.h"
+#include "pico/bootrom.h"
+#include "hardware/regs/xip.h"
#include "hardware/adc.h"
#include "hardware/exception.h"
#include "MMBasic_Includes.h"
@@ -1821,7 +1823,8 @@ void sigbus(void){
MMPrintString("Error: Invalid address - resetting\r\n");
uSec(250000);
disable_interrupts_pico();
-// flash_range_erase(PROGSTART, MAX_PROG_SIZE);
+// int r = rom_flash_op(op_erase_runtime(),
+// XIP_BASE + PROGSTART, MAX_PROG_SIZE, NULL);
LoadOptions();
if(Option.NoReset==0){
Option.Autorun=0;
@@ -4675,7 +4678,8 @@ void MIPS16 SaveProgramToFlash(unsigned char *pm, int msg) {
#endif
memcpy(buf, tknbuf, STRINGSIZE); // save the token buffer because we are going to use it
FlashWriteInit(PROGRAM_FLASH);
- flash_range_erase(realflashpointer, MAX_PROG_SIZE);
+ int r = rom_flash_op(op_erase_runtime(),
+ XIP_BASE + realflashpointer, MAX_PROG_SIZE, NULL);
j=MAX_PROG_SIZE/4;
int *pp=(int *)(flash_progmemory);
while(j--)if(*pp++ != 0xFFFFFFFF){
This is basically what I use as a direct replacement for the existing flash API:
#include "hardware/flash.h"
#include "pico/bootrom.h"
int flash_erase(uintptr_t address, uint32_t size_bytes)
{
#if PICO_RP2040
flash_range_erase(address, size_bytes);
return 0;
#elif PICO_RP2350
cflash_flags_t cflash_flags = {(CFLASH_OP_VALUE_ERASE << CFLASH_OP_LSB) |
(CFLASH_SECLEVEL_VALUE_SECURE << CFLASH_SECLEVEL_LSB) |
(CFLASH_ASPACE_VALUE_RUNTIME << CFLASH_ASPACE_LSB)};
// Round up size_bytes or rom_flash_op will throw an alignment error
uint32_t size_aligned = (size_bytes + 0x1FFF) & -FLASH_SECTOR_SIZE;
return rom_flash_op(cflash_flags, address + XIP_BASE, size_aligned, NULL);
#endif
}
int flash_program(uintptr_t address, const void* buf, uint32_t size_bytes)
{
#if PICO_RP2040
flash_range_program(address, buf, size_bytes);
return 0;
#elif PICO_RP2350
cflash_flags_t cflash_flags = {(CFLASH_OP_VALUE_PROGRAM << CFLASH_OP_LSB) |
(CFLASH_SECLEVEL_VALUE_SECURE << CFLASH_SECLEVEL_LSB) |
(CFLASH_ASPACE_VALUE_RUNTIME << CFLASH_ASPACE_LSB)};
return rom_flash_op(cflash_flags, address + XIP_BASE, size_bytes, (void*)buf);
#endif
}
If you can’t even get into bootsel mode via down/F3 then that definitely points to a communication problem with the STM32. I’m going to try the other keyboard bioses on my unit and see if there’s any difference. It’s really weird that it’s happening for you and not anyone else.
I did have something similar happen to me the other day when my stm32 got into a weird state and needed a full power-off to clear it.
I’m currently running the one that’s posted here. It needed to be built, but the .bin file flashed ok and has been working with everything I’ve tried (except in this one case).
UPDATE:
I flashed the official 1.4 BIOS and my keyboard now works fine with the loader menu. All the expected keys put it into the menu at power on, and pressing down arrow got me into bootsel. So the problem is something to do with how the enhanced BIOS at the link above handles key input on power on and how that interacts with the uf2loader.
@JackCarterSmith, I have an unrelated request… Would it be possible for your BIOS to use a different keycode other than 0x91 for the power button? It’s nice to be able to use it as an extra key, but 0x91 is the same as the F1 key which already exists. Looking at the PicoMite keyboard definition code, it seems that 0x66 is what an external USB keyboard would send as “USB_HID_KEYBOARD_KEYPAD_KEYBOARD_POWER“, so that might be a good value to consider. And the PicoCalc doesn’t send it already. Anything that doesn’t collide with an existing keyboard key on the PicoCalc would be useful though.
It wasn’t my choice initially, I simply used the value in the original firmware.
I see 0x91 value for the power button and 0x81 for F1, did I misreaded something?
I’ve just pushed the last version (v0.7) with the power button support/IRQ this week. The github mirror don’t have synced yet.
I just gave uf2loader v2.1 a try on a Pico 2W! Great work on this man.
When I tried the micropython file, I got ERR: Bad UF2 file, likely because it’s not using SDK 2.2.0
But I also tried Picoware (the SDK v2.2.0 version) and got the same ERR: Bad UF2 file.
Then when I restarted the PicoCalc (with no buttons pressed), I got a black screen.
From there, I restarted again but this time held F1 during boot, and then flashed Picoware again, and this time it worked!!
No, you were correct: it’s 0x91 for power and 0x81 for F1 in the original firmware. Sorry, it was my mistake because I’ve been in the wacky world of PicoMite too long. PicoMite expects most of the keys to have different values, and inside PicoMite F1 is 0x91. In PicoMite 0x81 is the down arrow. I have no idea why they redefined everything, but to maintain compatibility with existing BAS files, I translated everything to their keycodes. And I now realize that’s exactly what I need to do here. I can convert 0x91 to 0x66 since that’s what PicoMite expects it to be.
Ah! I was looking at github, but I actually cloned from the main repo, as I used the path mentioned here. That also explains why I couldn’t find mention of the power button in the github code. I looked for it and thought I was just failing to find it.
Yup. Got the same issue when running the new BIOS, and tracked it down to a race condition. The new BIOS doesn’t start supplying keypresses until a fairly long time after power-on, and my stage3 tries to read the keyboard immediately.
I’ve got a change that reads the keyboard for 0.5s before booting to the application, and it appears to be long enough on my unit to be able to consistently get into the menu without delaying normal boot noticably. That’ll go into the next release.
Ahah! No problem!
It could have been me who misread the records because I was working on several different sets!
Yes the sync on the github don’t seem working automatically…
Thanks for the notice again!
I suppose the fix should work when you keep the Fx key pressed when powering on. And should only handle the first one if multiple key is pressed in successive order. (Fx-1 have priority on Fx if pressed in less than the polling frequency)
Something I’ve noticed: even when flashing another .uf2 (in bootloader mode via computer) the UF2 loader remained in the flash. Is that on purpose? I do think it’s useful but I also wonder if that’ll conflict with other projects.
Turns out, the NES Emulator wouldn’t run that chess game until I nuked the flash and reflashed the uf2 directly.
On Pico 2? Yes, that’s expected and actually mentioned in the readme. All the standard ways of flashing a uf2 understand and honour the partition table. You can use Picotool to erase the bootloader if you want, as an alternative to flash_nuke.
There will always be applications that need modification to work properly in the partition; we’ll get through them eventually.
On Pico 1 it doesn’t work because uf2 loader has to modify the start of the application when flashing it in order to maintain the jump to the bootloader.
Well said, thanks for the explanation ![]()
On the RP2350 only, UF2 files can also be written to the Pico in BOOTSEL mode or via Picotool as normal and will automatically be placed in the app partition.
It’s definitely a useful feature, in my opinion; I just didn’t notice it until I tried out the NES Emulator project. Great work!
