forked from Mirrors/usk
revert some previous optimization changes, implement *proper* GRB to RGB conversion. these changes were on my mind for a while but they should fix error code display as well as have less jank error code indicators. rehius' usk was used as 'base' in this instance.
This commit is contained in:
parent
9cce154f9c
commit
9e2544dbe3
8 changed files with 147 additions and 190 deletions
|
|
@ -103,7 +103,7 @@ int led_pin()
|
||||||
return PIN_LED_ITSY;
|
return PIN_LED_ITSY;
|
||||||
default:
|
default:
|
||||||
return PIN_LED_WS;
|
return PIN_LED_WS;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int pwr_pin()
|
int pwr_pin()
|
||||||
|
|
@ -115,7 +115,7 @@ int pwr_pin()
|
||||||
return PIN_LED_PWR_ITSY;
|
return PIN_LED_PWR_ITSY;
|
||||||
default:
|
default:
|
||||||
return 31;
|
return 31;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int scl_pin()
|
int scl_pin()
|
||||||
|
|
@ -131,7 +131,7 @@ int scl_pin()
|
||||||
return PIN_SCL_SQC;
|
return PIN_SCL_SQC;
|
||||||
default:
|
default:
|
||||||
return PIN_SCL_WS;
|
return PIN_SCL_WS;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int sda_pin()
|
int sda_pin()
|
||||||
|
|
@ -147,7 +147,7 @@ int sda_pin()
|
||||||
return PIN_SDA_SQC;
|
return PIN_SDA_SQC;
|
||||||
default:
|
default:
|
||||||
return PIN_SDA_WS;
|
return PIN_SDA_WS;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int gli_pin()
|
int gli_pin()
|
||||||
|
|
@ -161,7 +161,7 @@ int gli_pin()
|
||||||
return PIN_GLI_PICO;
|
return PIN_GLI_PICO;
|
||||||
default:
|
default:
|
||||||
return PIN_GLI_WS;
|
return PIN_GLI_WS;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_pico()
|
bool is_pico()
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ bool wait_for_boot(int timeout_ms) {
|
||||||
else if (last_word == 0x51000000 && word == 0x0055) //read block 0
|
else if (last_word == 0x51000000 && word == 0x0055) //read block 0
|
||||||
{
|
{
|
||||||
// OLED models sometimes need more time between block 0 and block 1
|
// OLED models sometimes need more time between block 0 and block 1
|
||||||
// original was 100ms, increased to 250ms for (hopefully) better OLED compatibility
|
// original was 100ms, increased to 250ms for better OLED compatibility
|
||||||
tio_full = make_timeout_time_ms(250);
|
tio_full = make_timeout_time_ms(250);
|
||||||
was_read_zero = true;
|
was_read_zero = true;
|
||||||
} else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only
|
} else if (was_read_zero && last_word == 0x4D000200 && word == 0x00B1) // read status - erista only
|
||||||
|
|
@ -67,12 +67,11 @@ bool wait_for_boot(int timeout_ms) {
|
||||||
last_word = word;
|
last_word = word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// properly clean up all state machines before retrying
|
|
||||||
// original deinit only disabled SM 0 and 1, but SM 2 (G_DAT0_SM) was left running
|
|
||||||
|
|
||||||
pio_set_sm_mask_enabled(pio1, 0x7, false); // disable SM 0, 1, AND 2 (0x7 = 0b111)
|
// properly clean up all state machines before retrying
|
||||||
|
// SM 2 (G_DAT0_SM) must also be disabled (0x7 = 0b111 covers SM 0, 1, and 2)
|
||||||
|
pio_set_sm_mask_enabled(pio1, 0x7, false);
|
||||||
|
|
||||||
// clean up GPIO pins
|
// clean up GPIO pins
|
||||||
for (int i = PIN_CLK; i <= PIN_DAT; i++)
|
for (int i = PIN_CLK; i <= PIN_DAT; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -81,7 +80,7 @@ bool wait_for_boot(int timeout_ms) {
|
||||||
gpio_disable_input_output(i);
|
gpio_disable_input_output(i);
|
||||||
}
|
}
|
||||||
gpio_deinit(gli_pin());
|
gpio_deinit(gli_pin());
|
||||||
|
|
||||||
// only halt with error if all retries are exhausted
|
// only halt with error if all retries are exhausted
|
||||||
if (retry == BOOT_DETECT_MAX_RETRIES - 1) {
|
if (retry == BOOT_DETECT_MAX_RETRIES - 1) {
|
||||||
if (was_read_zero) {
|
if (was_read_zero) {
|
||||||
|
|
@ -93,10 +92,10 @@ bool wait_for_boot(int timeout_ms) {
|
||||||
halt_with_error(3, 3);
|
halt_with_error(3, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// small delay before retrying to let hardware settle
|
// small delay before retrying to let hardware settle
|
||||||
sleep_ms(50);
|
sleep_ms(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
config.h
2
config.h
|
|
@ -1,7 +1,7 @@
|
||||||
#include "hardware/flash.h"
|
#include "hardware/flash.h"
|
||||||
#define OFFSET_DIV 8
|
#define OFFSET_DIV 8
|
||||||
#define OFFSET_MIN 6200
|
#define OFFSET_MIN 6200
|
||||||
#define OFFSET_MAX 6950
|
#define OFFSET_MAX 6900
|
||||||
|
|
||||||
#define VER_HI 2
|
#define VER_HI 2
|
||||||
#define VER_LO 81
|
#define VER_LO 81
|
||||||
|
|
|
||||||
9
glitch.c
9
glitch.c
|
|
@ -65,8 +65,7 @@ void init_glitch_pio() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void deinit_glitch_pio() {
|
void deinit_glitch_pio() {
|
||||||
// original code only disabled SM 0 and 1 (mask 0x3 = 0b011)
|
// SM 2 (G_DAT0_SM) is also used, so all 3 state machines need to be disabled (0x7 = 0b111)
|
||||||
// SM 2 (G_DAT0_SM) is also used, so all 3 (mask 0x7 = 0b111) need to be disabled
|
|
||||||
pio_set_sm_mask_enabled(pio1, 0x7, false);
|
pio_set_sm_mask_enabled(pio1, 0x7, false);
|
||||||
for (int i = PIN_CLK; i <= PIN_DAT; i++)
|
for (int i = PIN_CLK; i <= PIN_DAT; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -136,14 +135,14 @@ int do_glitch(int delay, int width, int total_ms, int after_ms) {
|
||||||
|
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
|
|
||||||
// Green pulsing implementation.
|
// Blue pulsing implementation.
|
||||||
void inc_tries()
|
void inc_tries()
|
||||||
{
|
{
|
||||||
tries += 1;
|
tries += 1;
|
||||||
if(tries & 1)
|
if(tries & 1)
|
||||||
put_pixel(PIX_g);
|
put_pixel(PIX_b);
|
||||||
else
|
else
|
||||||
put_pixel(PIX_gre);
|
put_pixel(PIX_blu);
|
||||||
}
|
}
|
||||||
|
|
||||||
// random() for glitch offset array generation
|
// random() for glitch offset array generation
|
||||||
|
|
|
||||||
169
main.c
169
main.c
|
|
@ -21,23 +21,24 @@
|
||||||
|
|
||||||
bool write_payload();
|
bool write_payload();
|
||||||
|
|
||||||
// optimized: increased voltage for better stability at higher clock
|
// overclock to 200 MHz
|
||||||
void init_system() {
|
void init_system() {
|
||||||
vreg_set_voltage(VREG_VOLTAGE_1_30);
|
vreg_set_voltage(VREG_VOLTAGE_1_30);
|
||||||
set_sys_clock_khz(200000, true);
|
set_sys_clock_khz(200000, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filled within "fast check" on eMMC init
|
||||||
extern uint8_t cid_buf[17];
|
extern uint8_t cid_buf[17];
|
||||||
|
|
||||||
void rewrite_payload()
|
void rewrite_payload()
|
||||||
{
|
{
|
||||||
put_pixel(PIX_whi);
|
put_pixel(PIX_whi);
|
||||||
write_payload();
|
write_payload();
|
||||||
put_pixel(PIX_gre);
|
put_pixel(PIX_blu);
|
||||||
|
// used to automatically rewrite payload when eMMC/console changes
|
||||||
init_config(cid_buf + 1);
|
init_config(cid_buf + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: reduced timeout and combined checks
|
|
||||||
bool safe_test_voltage(int pin, float target, float range)
|
bool safe_test_voltage(int pin, float target, float range)
|
||||||
{
|
{
|
||||||
gpio_enable_input_output(pin);
|
gpio_enable_input_output(pin);
|
||||||
|
|
@ -49,28 +50,34 @@ bool safe_test_voltage(int pin, float target, float range)
|
||||||
return voltage >= (target - range) && voltage <= (target + range);
|
return voltage >= (target - range) && voltage <= (target + range);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: reduced timeout from 2500ms to 1500ms, faster convergence
|
// test all ADC pins
|
||||||
void self_test()
|
void self_test()
|
||||||
{
|
{
|
||||||
absolute_time_t tio_time = make_timeout_time_ms(1500);
|
absolute_time_t tio_time = make_timeout_time_ms(2500);
|
||||||
adc_init();
|
adc_init();
|
||||||
uint8_t check_mask = 0; // bit flags: 0=rst, 1=cmd, 2=d0
|
bool rst_ok = false, cmd_ok = false, d0_ok = false, clk_ok = false;
|
||||||
|
while (!time_reached(tio_time)) {
|
||||||
while (!time_reached(tio_time) && check_mask != 0x07) {
|
if (!rst_ok)
|
||||||
if (!(check_mask & 0x01))
|
rst_ok |= safe_test_voltage(PIN_RST, 1.8f, 0.2f);
|
||||||
check_mask |= safe_test_voltage(PIN_RST, 1.8f, 0.2f) ? 0x01 : 0;
|
if (!cmd_ok)
|
||||||
if (!(check_mask & 0x02))
|
cmd_ok |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f);
|
||||||
check_mask |= safe_test_voltage(PIN_CMD, 1.8f, 0.2f) ? 0x02 : 0;
|
if (!d0_ok)
|
||||||
if (!(check_mask & 0x04))
|
d0_ok |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f);
|
||||||
check_mask |= safe_test_voltage(PIN_DAT, 1.8f, 0.2f) ? 0x04 : 0;
|
if (rst_ok && cmd_ok && d0_ok)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if(!rst_ok)
|
||||||
if(!(check_mask & 0x01))
|
{
|
||||||
halt_with_error(0, 2);
|
halt_with_error(0, 2);
|
||||||
if(!(check_mask & 0x02))
|
}
|
||||||
|
if(!cmd_ok)
|
||||||
|
{
|
||||||
halt_with_error(1, 2);
|
halt_with_error(1, 2);
|
||||||
if(!(check_mask & 0x04))
|
}
|
||||||
|
if(!d0_ok)
|
||||||
|
{
|
||||||
halt_with_error(2, 2);
|
halt_with_error(2, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool was_self_reset;
|
extern bool was_self_reset;
|
||||||
|
|
@ -79,125 +86,89 @@ int main()
|
||||||
{
|
{
|
||||||
// stop watchdog
|
// stop watchdog
|
||||||
*(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
|
*(uint32_t*)(0x40058000 + 0x3000) = (1 << 30);
|
||||||
|
// init reset, mosfet and LED
|
||||||
// init board detection
|
|
||||||
detect_board();
|
detect_board();
|
||||||
|
|
||||||
// clocks & voltage
|
// clocks & voltage
|
||||||
init_system();
|
init_system();
|
||||||
|
|
||||||
// fuses counter
|
// fuses counter
|
||||||
init_fuses();
|
init_fuses();
|
||||||
|
|
||||||
// LED & glitch & emmc PIO
|
// LED & glitch & emmc PIO
|
||||||
upload_pio();
|
upload_pio();
|
||||||
|
|
||||||
if (is_tiny())
|
if (is_tiny())
|
||||||
{
|
{
|
||||||
gpio_put(led_pin(), 0);
|
gpio_put(led_pin(), 0);
|
||||||
sleep_us(50); // optimized: reduced from 100us
|
sleep_us(100);
|
||||||
put_pixel(0);
|
put_pixel(0);
|
||||||
sleep_us(50); // optimized: reduced from 100us
|
sleep_us(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if this is the very first start
|
// check if this is the very first start
|
||||||
if (watchdog_caused_reboot() && boot_try == 0)
|
if (watchdog_caused_reboot() && boot_try == 0)
|
||||||
halt_with_error(1, 1);
|
{
|
||||||
|
halt_with_error(1, 1);
|
||||||
|
}
|
||||||
// is chip reset required
|
// is chip reset required
|
||||||
bool force_button = detect_by_pull(1, 0, 1);
|
bool force_button = detect_by_pull(1, 0, 1);
|
||||||
|
|
||||||
// start LED
|
// start LED
|
||||||
put_pixel(PIX_gre);
|
put_pixel(PIX_blu);
|
||||||
|
|
||||||
// test pins
|
// test pins
|
||||||
self_test();
|
self_test();
|
||||||
|
|
||||||
// wait till the CPU has proper power & started reading the eMMC
|
// wait till the CPU has proper power & started reading the eMMC
|
||||||
wait_for_boot(2490);
|
wait_for_boot(2500);
|
||||||
|
|
||||||
// ensure the BCT has not been overwritten by system update
|
// ensure the BCT has not been overwritten by system update
|
||||||
bool force_check = fast_check();
|
bool force_check = fast_check();
|
||||||
was_self_reset = force_button || !is_configured(cid_buf + 1);
|
was_self_reset = force_button || !is_configured(cid_buf + 1);
|
||||||
|
|
||||||
// perform payload rewrite if required
|
// perform payload rewrite if required
|
||||||
if (!force_check || was_self_reset) {
|
if (!force_check || was_self_reset) {
|
||||||
rewrite_payload();
|
rewrite_payload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the glitch trigger for Mariko
|
// setup the glitch trigger for Mariko
|
||||||
if (mariko) {
|
if (mariko) {
|
||||||
pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
|
pio1->instr_mem[gtrig_pio_offset + 4] = pio_encode_nop();
|
||||||
pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
|
pio1->instr_mem[gtrig_pio_offset + 5] = pio_encode_nop();
|
||||||
}
|
}
|
||||||
|
// start from some default width
|
||||||
// optimized: start with slightly lower width for faster convergence
|
int width = 150;
|
||||||
int width = 140;
|
|
||||||
bool glitched = false;
|
bool glitched = false;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
for (int full_try = 0; full_try < 2; full_try++) {
|
||||||
// optimized: removed outer loop since it just repeats rewrite_payload
|
// try saved records
|
||||||
// try saved records first
|
for (int y = 0; (y < 2) && !glitched; y++) {
|
||||||
for (int y = 0; (y < 2) && !glitched; y++) {
|
int max_weight = -1;
|
||||||
int max_weight = -1;
|
while (1) {
|
||||||
while (1) {
|
offset = find_best_record(&max_weight);
|
||||||
offset = find_best_record(&max_weight);
|
if (offset == -1)
|
||||||
if (offset == -1)
|
break;
|
||||||
break;
|
// try glitch
|
||||||
// optimized: reduced attempts from 3 to 2 for faster iteration
|
|
||||||
glitched = glitch_try_offset(offset, &width, 2);
|
|
||||||
if (glitched)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try random offsets if saved records failed
|
|
||||||
if (!glitched) {
|
|
||||||
for(int z = 0; (z < 2) && !glitched; z++) {
|
|
||||||
prepare_random_array();
|
|
||||||
for(int y = 0; y < OFFSET_CNT; y++)
|
|
||||||
{
|
|
||||||
offset = offsets_array[y];
|
|
||||||
// optimized: reduced attempts from 4 to 3
|
|
||||||
glitched = glitch_try_offset(offset, &width, 3);
|
glitched = glitch_try_offset(offset, &width, 3);
|
||||||
if (glitched)
|
if (glitched)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!glitched) {
|
||||||
|
for(int z = 0; (z < 2) && !glitched; z++) {
|
||||||
// if still not glitched, try one more time with payload rewrite
|
prepare_random_array();
|
||||||
if (!glitched) {
|
for(int y = 0; y < OFFSET_CNT; y++)
|
||||||
rewrite_payload();
|
{
|
||||||
|
offset = offsets_array[y];
|
||||||
// one more attempt with saved records
|
glitched = glitch_try_offset(offset, &width, 4);
|
||||||
int max_weight = -1;
|
if (glitched)
|
||||||
for (int y = 0; (y < 3) && !glitched; y++) {
|
break;
|
||||||
offset = find_best_record(&max_weight);
|
}
|
||||||
if (offset == -1)
|
}
|
||||||
break;
|
}
|
||||||
glitched = glitch_try_offset(offset, &width, 2);
|
if (glitched) {
|
||||||
|
if ((count_fuses() & 1) != boot_slot)
|
||||||
|
{
|
||||||
|
// finish update / rollback
|
||||||
|
burn_fuse();
|
||||||
|
}
|
||||||
|
add_boot_record(offset);
|
||||||
|
halt_with_error(0, 1);
|
||||||
|
}
|
||||||
|
if (full_try == 0) {
|
||||||
|
rewrite_payload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glitched) {
|
|
||||||
// ensure all glitching operations are complete
|
|
||||||
sleep_us(100);
|
|
||||||
// force success LED display
|
|
||||||
put_pixel(0); // clear any previous LED state
|
|
||||||
sleep_ms(50);
|
|
||||||
put_pixel(PIX_whi); // show white success
|
|
||||||
sleep_ms(200); // longer delay to ensure visibility
|
|
||||||
|
|
||||||
if ((count_fuses() & 1) != boot_slot)
|
|
||||||
{
|
|
||||||
// finish update / rollback
|
|
||||||
burn_fuse();
|
|
||||||
}
|
|
||||||
add_boot_record(offset);
|
|
||||||
halt_with_error(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempts limit
|
// attempts limit
|
||||||
halt_with_error(7, 3);
|
halt_with_error(7, 3);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
misc.c
65
misc.c
|
|
@ -10,14 +10,13 @@
|
||||||
|
|
||||||
extern int ws_pio_offset;
|
extern int ws_pio_offset;
|
||||||
|
|
||||||
// optimized: reduced timing constants for faster error signaling
|
#define BLINK_TIME 700
|
||||||
#define BLINK_TIME 500
|
|
||||||
#define SHORT_TIME ( BLINK_TIME * 2 / 10 )
|
#define SHORT_TIME ( BLINK_TIME * 2 / 10 )
|
||||||
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
|
#define SHORT_PAUSE_TIME ((BLINK_TIME - SHORT_TIME) / 2)
|
||||||
#define LONG_TIME ( BLINK_TIME * 8 / 10 )
|
#define LONG_TIME ( BLINK_TIME * 8 / 10 )
|
||||||
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
|
#define LONG_PAUSE_TIME ((BLINK_TIME - LONG_TIME) / 2)
|
||||||
#define PAUSE_BETWEEN 1500
|
#define PAUSE_BETWEEN 2000
|
||||||
#define PAUSE_BEFORE 500
|
#define PAUSE_BEFORE 750
|
||||||
#define CODE_REPEATS 3
|
#define CODE_REPEATS 3
|
||||||
|
|
||||||
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
|
#define GPIO_OD PADS_BANK0_GPIO0_OD_BITS
|
||||||
|
|
@ -26,7 +25,6 @@ extern int ws_pio_offset;
|
||||||
|
|
||||||
typedef void nopar();
|
typedef void nopar();
|
||||||
|
|
||||||
// optimized: streamlined power down sequence
|
|
||||||
void __not_in_flash_func(zzz)() {
|
void __not_in_flash_func(zzz)() {
|
||||||
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
|
*(uint32_t*)(0x4000803C + 0x3000) = 1; // go to 12 MHz
|
||||||
uint32_t * vreg = (uint32_t*)0x40064000;
|
uint32_t * vreg = (uint32_t*)0x40064000;
|
||||||
|
|
@ -34,27 +32,30 @@ void __not_in_flash_func(zzz)() {
|
||||||
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
|
*(uint32_t*)0x40060000 = 0x00d1e000; // disable rosc
|
||||||
vreg[0] = 1; // lowest possible power
|
vreg[0] = 1; // lowest possible power
|
||||||
*(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
|
*(uint32_t*)0x40024000 = 0x00d1e000; // disable xosc
|
||||||
while(1) __asm volatile("wfi"); // optimized: use WFI to save more power
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: combined loop for faster execution
|
|
||||||
void finish_pins_except_leds() {
|
void finish_pins_except_leds() {
|
||||||
for(int pin = 0; pin <= 29; pin++) {
|
for(int pin = 0; pin <= 29; pin += 1) {
|
||||||
if (pin == led_pin() || pin == pwr_pin())
|
if (pin == led_pin() || pin == pwr_pin())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
|
if (pin == PIN_GLI_PICO || pin == PIN_GLI_XIAO || pin == PIN_GLI_WS || pin == PIN_GLI_ITSY)
|
||||||
|
{
|
||||||
gpio_pull_down(pin);
|
gpio_pull_down(pin);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
gpio_disable_pulls(pin);
|
gpio_disable_pulls(pin);
|
||||||
|
}
|
||||||
gpio_disable_input_output(pin);
|
gpio_disable_input_output(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish_pins_leds() {
|
void finish_pins_leds() {
|
||||||
if (!is_tiny())
|
if (!is_tiny())
|
||||||
|
{
|
||||||
gpio_disable_input_output(led_pin());
|
gpio_disable_input_output(led_pin());
|
||||||
|
}
|
||||||
gpio_disable_input_output(pwr_pin());
|
gpio_disable_input_output(pwr_pin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,62 +66,50 @@ void halt_with_error(uint32_t err, uint32_t bits)
|
||||||
pio_set_sm_mask_enabled(pio1, 0xF, false);
|
pio_set_sm_mask_enabled(pio1, 0xF, false);
|
||||||
set_sys_clock_khz(48000, true);
|
set_sys_clock_khz(48000, true);
|
||||||
vreg_set_voltage(VREG_VOLTAGE_0_95);
|
vreg_set_voltage(VREG_VOLTAGE_0_95);
|
||||||
|
|
||||||
if (bits != 1)
|
if (bits != 1)
|
||||||
{
|
{
|
||||||
put_pixel(0);
|
put_pixel(0);
|
||||||
sleep_ms(PAUSE_BEFORE);
|
sleep_ms(PAUSE_BEFORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int j = 0; j < CODE_REPEATS; j++)
|
for(int j = 0; j < CODE_REPEATS; j++)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < bits; i++)
|
for(int i = 0; i < bits; i++)
|
||||||
{
|
{
|
||||||
bool is_long = err & (1 << (bits - i - 1));
|
bool is_long = err & (1 << (bits - i - 1));
|
||||||
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
|
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
|
||||||
|
|
||||||
bool success = bits == 1 && is_long == 0;
|
bool success = bits == 1 && is_long == 0;
|
||||||
put_pixel(success ? PIX_whi : PIX_red);
|
if (success)
|
||||||
|
put_pixel(PIX_whi);
|
||||||
|
else
|
||||||
|
put_pixel(PIX_red);
|
||||||
sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
|
sleep_ms(is_long ? LONG_TIME : success ? SHORT_TIME * 2 : SHORT_TIME);
|
||||||
put_pixel(0);
|
put_pixel(0);
|
||||||
|
|
||||||
if (i != bits - 1 || j != CODE_REPEATS - 1)
|
if (i != bits - 1 || j != CODE_REPEATS - 1)
|
||||||
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
|
sleep_ms(is_long ? LONG_PAUSE_TIME : SHORT_PAUSE_TIME);
|
||||||
if (i == bits - 1 && j != CODE_REPEATS - 1)
|
if (i == bits - 1 && j != CODE_REPEATS - 1)
|
||||||
sleep_ms(PAUSE_BETWEEN);
|
sleep_ms(PAUSE_BETWEEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// first write case, do not repeat this kind of error code
|
// first write case, do not repeat this kind of error code
|
||||||
if (bits == 1)
|
if (bits == 1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_pins_leds();
|
finish_pins_leds();
|
||||||
zzz();
|
zzz();
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: reduced LED delays for faster startup
|
void put_pixel(uint32_t pixel_grb)
|
||||||
void put_pixel(uint32_t pixel_rgb)
|
|
||||||
{
|
{
|
||||||
static bool led_enabled = false;
|
static bool led_enabled = false;
|
||||||
|
|
||||||
if (is_pico())
|
if (is_pico())
|
||||||
{
|
{
|
||||||
gpio_init(led_pin());
|
gpio_init(led_pin());
|
||||||
if (pixel_rgb) {
|
if (pixel_grb) {
|
||||||
gpio_set_dir(led_pin(), true);
|
gpio_set_dir(led_pin(), true);
|
||||||
gpio_put(led_pin(), 1);
|
gpio_put(led_pin(), 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t red = (pixel_rgb >> 16) & 0xFF;
|
|
||||||
uint8_t green = (pixel_rgb >> 8) & 0xFF;
|
|
||||||
uint8_t blue = pixel_rgb & 0xFF;
|
|
||||||
uint32_t pixel_grb = (green << 16) | (red << 8) | blue;
|
|
||||||
|
|
||||||
ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
|
ws2812_program_init(pio0, 3, ws_pio_offset, led_pin(), 800000, true);
|
||||||
|
|
||||||
if (!led_enabled && pwr_pin() != 31)
|
if (!led_enabled && pwr_pin() != 31)
|
||||||
{
|
{
|
||||||
led_enabled = true;
|
led_enabled = true;
|
||||||
|
|
@ -128,41 +117,39 @@ void put_pixel(uint32_t pixel_rgb)
|
||||||
gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
|
gpio_set_drive_strength(pwr_pin(), GPIO_DRIVE_STRENGTH_12MA);
|
||||||
gpio_set_dir(pwr_pin(), true);
|
gpio_set_dir(pwr_pin(), true);
|
||||||
gpio_put(pwr_pin(), 1);
|
gpio_put(pwr_pin(), 1);
|
||||||
sleep_us(100); // optimized: reduced from 200us
|
sleep_us(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
|
pio_sm_put_blocking(pio0, 3, pixel_grb << 8u);
|
||||||
sleep_us(30); // optimized: reduced from 50us
|
sleep_us(50);
|
||||||
pio_sm_set_enabled(pio0, 3, false);
|
pio_sm_set_enabled(pio0, 3, false);
|
||||||
|
|
||||||
if (!is_tiny())
|
if (!is_tiny())
|
||||||
|
{
|
||||||
gpio_init(led_pin());
|
gpio_init(led_pin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: direct register access
|
|
||||||
void gpio_disable_input_output(int pin)
|
void gpio_disable_input_output(int pin)
|
||||||
{
|
{
|
||||||
uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply
|
uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
|
||||||
*(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
|
*(uint32_t*)(pad_reg + 0x2000) = GPIO_OD;
|
||||||
*(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
|
*(uint32_t*)(pad_reg + 0x3000) = GPIO_IE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_enable_input_output(int pin)
|
void gpio_enable_input_output(int pin)
|
||||||
{
|
{
|
||||||
uint32_t pad_reg = 0x4001c000 + 4 + (pin << 2); // optimized: Use shift instead of multiply
|
uint32_t pad_reg = 0x4001c000 + 4 + pin*4;
|
||||||
*(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
|
*(uint32_t*)(pad_reg + 0x3000) = GPIO_OD;
|
||||||
*(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
|
*(uint32_t*)(pad_reg + 0x2000) = GPIO_IE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimized: reduced delays for faster reset cycles
|
|
||||||
void reset_cpu() {
|
void reset_cpu() {
|
||||||
gpio_enable_input_output(PIN_RST);
|
gpio_enable_input_output(PIN_RST);
|
||||||
gpio_pull_up(PIN_RST);
|
gpio_pull_up(PIN_RST);
|
||||||
sleep_us(800); // optimized: reduced from 1000us
|
sleep_us(1000);
|
||||||
gpio_init(PIN_RST);
|
gpio_init(PIN_RST);
|
||||||
gpio_set_dir(PIN_RST, true);
|
gpio_set_dir(PIN_RST, true);
|
||||||
sleep_us(1800); // decreased slightly for button detection stability
|
sleep_us(2000);
|
||||||
gpio_deinit(PIN_RST);
|
gpio_deinit(PIN_RST);
|
||||||
gpio_disable_pulls(PIN_RST);
|
gpio_disable_pulls(PIN_RST);
|
||||||
gpio_disable_input_output(PIN_RST);
|
gpio_disable_input_output(PIN_RST);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
misc.h
11
misc.h
|
|
@ -1,8 +1,9 @@
|
||||||
#define PIX_gre 0x16537e
|
#define RGB(r, g, b) (((g) << 16) | ((r) << 8) | (b))
|
||||||
#define PIX_red 0xc90000
|
|
||||||
#define PIX_whi 0xff9200
|
|
||||||
|
|
||||||
#define PIX_g 0x6fa8dc
|
#define PIX_blu RGB(0x16, 0x53, 0x7e) // blue (glitching)
|
||||||
|
#define PIX_b RGB(0x6f, 0xa8, 0xdc) // light blue dim (glitch pulse)
|
||||||
|
#define PIX_whi RGB(0xff, 0x92, 0x00) // amber/yellow (success + comparison)
|
||||||
|
#define PIX_red RGB(0xc9, 0x00, 0x00) // red (error codes)
|
||||||
|
|
||||||
void put_pixel(uint32_t pixel_grb);
|
void put_pixel(uint32_t pixel_grb);
|
||||||
|
|
||||||
|
|
@ -14,4 +15,4 @@ void gpio_enable_input_output(int pin);
|
||||||
|
|
||||||
void finish_pins_except_leds();
|
void finish_pins_except_leds();
|
||||||
|
|
||||||
void reset_cpu();
|
void reset_cpu();
|
||||||
54
payload.c
54
payload.c
|
|
@ -81,7 +81,7 @@ extern bool mariko;
|
||||||
|
|
||||||
static inline uint16_t crc_itu_t_byte(uint16_t crc, const uint8_t data)
|
static inline uint16_t crc_itu_t_byte(uint16_t crc, const uint8_t data)
|
||||||
{
|
{
|
||||||
return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
|
return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
|
uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
|
||||||
|
|
@ -91,9 +91,9 @@ uint16_t crc_itu_t(uint16_t crc, const uint8_t *buffer, size_t len)
|
||||||
{
|
{
|
||||||
crc_prepare_table();
|
crc_prepare_table();
|
||||||
}
|
}
|
||||||
while (len--)
|
while (len--)
|
||||||
crc = crc_itu_t_byte(crc, *buffer++);
|
crc = crc_itu_t_byte(crc, *buffer++);
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void zzz();
|
extern void zzz();
|
||||||
|
|
@ -108,18 +108,18 @@ uint16_t payload_crc()
|
||||||
|
|
||||||
int crc7(uint8_t *buffer, int size)
|
int crc7(uint8_t *buffer, int size)
|
||||||
{
|
{
|
||||||
uint8_t crc = 0;
|
uint8_t crc = 0;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
uint8_t c = buffer[i];
|
uint8_t c = buffer[i];
|
||||||
for (int j = 0; j < 8; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
crc <<= 1;
|
crc <<= 1;
|
||||||
if ((crc ^ c) & 0x80)
|
if ((crc ^ c) & 0x80)
|
||||||
crc ^= 9;
|
crc ^= 9;
|
||||||
c <<= 1;
|
c <<= 1;
|
||||||
}
|
}
|
||||||
crc &= 0x7Fu;
|
crc &= 0x7Fu;
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __time_critical_func(cmd_write)(uint8_t cmd, uint32_t argument)
|
void __time_critical_func(cmd_write)(uint8_t cmd, uint32_t argument)
|
||||||
|
|
@ -130,9 +130,9 @@ void __time_critical_func(cmd_write)(uint8_t cmd, uint32_t argument)
|
||||||
pio_sm_set_out_pins(pio0, SM_OUT, PIN_CMD, 1);
|
pio_sm_set_out_pins(pio0, SM_OUT, PIN_CMD, 1);
|
||||||
pio_sm_set_enabled(pio0, SM_OUT, true);
|
pio_sm_set_enabled(pio0, SM_OUT, true);
|
||||||
|
|
||||||
data[0] = cmd | 0x40;
|
data[0] = cmd | 0x40;
|
||||||
*(uint32_t *) &data[1] = __builtin_bswap32(argument);
|
*(uint32_t *) &data[1] = __builtin_bswap32(argument);
|
||||||
data[5] = (crc7(data, 5) << 1) | 1;
|
data[5] = (crc7(data, 5) << 1) | 1;
|
||||||
uint32_t fifo[3];
|
uint32_t fifo[3];
|
||||||
fifo[0] = 0xFFCF0000 | (data[0] << 8) | data[1];
|
fifo[0] = 0xFFCF0000 | (data[0] << 8) | data[1];
|
||||||
fifo[1] = __builtin_bswap32(*(uint32_t*)(data + 2));
|
fifo[1] = __builtin_bswap32(*(uint32_t*)(data + 2));
|
||||||
|
|
@ -151,7 +151,7 @@ bool __time_critical_func(dat_write)()
|
||||||
pio_sm_set_out_pins(pio0, SM_OUT, PIN_DAT, 1);
|
pio_sm_set_out_pins(pio0, SM_OUT, PIN_DAT, 1);
|
||||||
pio_sm_set_enabled(pio0, SM_OUT, true);
|
pio_sm_set_enabled(pio0, SM_OUT, true);
|
||||||
uint8_t * buffer = data_buf;
|
uint8_t * buffer = data_buf;
|
||||||
uint16_t crc = crc_itu_t(0, buffer, 512);
|
uint16_t crc = crc_itu_t(0, buffer, 512);
|
||||||
uint32_t words[130];
|
uint32_t words[130];
|
||||||
int size_bits = 514 * 8 + 2;
|
int size_bits = 514 * 8 + 2;
|
||||||
words[0] = ((size_bits ^ 0xFFFF) << 16) | (buffer[0] << 7) | (buffer[1] >> 1);
|
words[0] = ((size_bits ^ 0xFFFF) << 16) | (buffer[0] << 7) | (buffer[1] >> 1);
|
||||||
|
|
@ -413,13 +413,13 @@ uint32_t mmc_init_table[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool mmc_initialize() {
|
bool mmc_initialize() {
|
||||||
if (!init_op_cond()) {
|
if (!init_op_cond()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!cmd_exec_cid()) {
|
if (!cmd_exec_cid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < sizeof(mmc_init_table)/sizeof(mmc_init_table[0]); i += 4)
|
for (int i = 0; i < sizeof(mmc_init_table)/sizeof(mmc_init_table[0]); i += 4)
|
||||||
{
|
{
|
||||||
uint32_t res= 0;
|
uint32_t res= 0;
|
||||||
if (!simple_cmd_exec_with_ret(mmc_init_table[i], mmc_init_table[i+1], &res)) {
|
if (!simple_cmd_exec_with_ret(mmc_init_table[i], mmc_init_table[i+1], &res)) {
|
||||||
|
|
@ -495,9 +495,9 @@ extern int boot_slot;
|
||||||
uint8_t temp_buf[512];
|
uint8_t temp_buf[512];
|
||||||
|
|
||||||
struct fw_header {
|
struct fw_header {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define fw_slot_0 ((struct fw_header *) (XIP_BASE + 0x10000))
|
#define fw_slot_0 ((struct fw_header *) (XIP_BASE + 0x10000))
|
||||||
|
|
@ -713,7 +713,7 @@ void prepare_mariko_bct()
|
||||||
* drops writes to BctNormalMain (offset 0x0000) and BctSafeMain (offset 0x4000)
|
* drops writes to BctNormalMain (offset 0x0000) and BctSafeMain (offset 0x4000)
|
||||||
* when it detects the modchip's custom public key fill pattern (0x59, 0x69...) in those
|
* when it detects the modchip's custom public key fill pattern (0x59, 0x69...) in those
|
||||||
* slots. this is by design for AutoRCM preservation, but it means that after a firmware
|
* slots. this is by design for AutoRCM preservation, but it means that after a firmware
|
||||||
* update via syscfw, UpdateBootImages successfully writes the new BCT to BctNormalSub (0x8000) and BctSafeSub (0xC000),
|
* update via syscfw, UpdateBootImages successfully writes the new BCT to BctNormalSub (0x8000) and BctSafeSub (0xC000),
|
||||||
* but the writes to BctNormalMain and BctSafeMain are discarded. the result is that Main slots still hold the modchip
|
* but the writes to BctNormalMain and BctSafeMain are discarded. the result is that Main slots still hold the modchip
|
||||||
* synthetic/fake BCT while Sub slots have the new firmware's real BCT.
|
* synthetic/fake BCT while Sub slots have the new firmware's real BCT.
|
||||||
*
|
*
|
||||||
|
|
@ -799,4 +799,4 @@ void write_payload() {
|
||||||
stop_mmc();
|
stop_mmc();
|
||||||
if (!is_space_bl && !is_command && !was_self_reset)
|
if (!is_space_bl && !is_command && !was_self_reset)
|
||||||
halt_with_error(0, 0);
|
halt_with_error(0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue