kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Use rescue DP to always get driver into a known state before load, boot via watchdog, better logging from driver.
rodzic
da36b0ad32
commit
2e8632f2b6
|
@ -16,7 +16,7 @@ namespace pimoroni {
|
|||
gpio_init(VSYNC);
|
||||
gpio_set_dir(VSYNC, GPIO_IN);
|
||||
|
||||
swd_load_program(section_addresses, section_data, section_data_len, sizeof(section_addresses) / sizeof(section_addresses[0]));
|
||||
swd_load_program(section_addresses, section_data, section_data_len, sizeof(section_addresses) / sizeof(section_addresses[0]), 0x20000001, 0x15004000, true);
|
||||
|
||||
ram.init();
|
||||
write_header(0);
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -87,7 +87,7 @@ static void idle() {
|
|||
pio_sm_put_blocking(pio0, pio_sm, 0);
|
||||
}
|
||||
|
||||
static bool connect(bool first = true) {
|
||||
static bool connect(bool first = true, uint core = 0) {
|
||||
if (first) {
|
||||
pio_prog = &swd_raw_write_program;
|
||||
pio_offset = pio_add_program(pio0, &swd_raw_write_program);
|
||||
|
@ -138,7 +138,7 @@ static bool connect(bool first = true) {
|
|||
wait_for_idle();
|
||||
pio0_hw->irq = 1;
|
||||
pio_sm_put_blocking(pio0, pio_sm, 0x19);
|
||||
pio_sm_put_blocking(pio0, pio_sm, 0x01002927);
|
||||
pio_sm_put_blocking(pio0, pio_sm, 0x01002927 | (core << 28));
|
||||
|
||||
printf("Read ID\n");
|
||||
uint id;
|
||||
|
@ -148,7 +148,7 @@ static bool connect(bool first = true) {
|
|||
}
|
||||
printf("Received ID: %08x\n", id);
|
||||
|
||||
if (id != 0x0bc12477) return false;
|
||||
if (core != 0xf && id != 0x0bc12477) return false;
|
||||
|
||||
printf("Abort\n");
|
||||
if (!write_cmd(0x01, 0x1E)) {
|
||||
|
@ -179,13 +179,28 @@ static bool connect(bool first = true) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (core != 0xf) {
|
||||
printf("Setup memory access\n");
|
||||
if (!write_cmd(0x23, 0xA2000052)) {
|
||||
printf("Memory access setup failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Halt CPU\n");
|
||||
if (!write_reg(0xe000edf0, 0xA05F0003)) {
|
||||
printf("Halt failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!write_cmd(0x29, 0x00000001)) {
|
||||
printf("Clear reset failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
idle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -193,24 +208,23 @@ static bool load(uint address, const uint* data, uint len_in_bytes) {
|
|||
printf("Loading %d bytes at %08x\n", len_in_bytes, address);
|
||||
idle();
|
||||
|
||||
printf("Halt CPU\n");
|
||||
if (!write_reg(0xe000edf0, 0xA05F0003)) {
|
||||
printf("Halt failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
idle();
|
||||
|
||||
constexpr uint BLOCK_SIZE = 1024;
|
||||
for (uint i = 0; i < len_in_bytes; i += BLOCK_SIZE) {
|
||||
uint block_len_in_words = std::min(BLOCK_SIZE >> 2, (len_in_bytes - i) >> 2);
|
||||
uint block_len_in_words = std::min((BLOCK_SIZE - (address & (BLOCK_SIZE - 1))) >> 2, len_in_bytes >> 2);
|
||||
for (uint i = 0; i < len_in_bytes; ) {
|
||||
if (!write_block(address + i, &data[i >> 2], block_len_in_words)) {
|
||||
printf("Block write failed\n");
|
||||
return false;
|
||||
}
|
||||
i += block_len_in_words << 2;
|
||||
block_len_in_words = std::min(BLOCK_SIZE >> 2, (len_in_bytes - i) >> 2);
|
||||
}
|
||||
|
||||
for (uint j = 0; j < len_in_bytes; j += 4) {
|
||||
#ifdef FULL_VERIFY
|
||||
for (uint j = 0; j < len_in_bytes; j += 4)
|
||||
#else
|
||||
uint j = 0;
|
||||
#endif
|
||||
{
|
||||
uint check_data;
|
||||
if (!read_reg(address + j, check_data)) {
|
||||
printf("Read failed\n");
|
||||
|
@ -227,18 +241,23 @@ static bool load(uint address, const uint* data, uint len_in_bytes) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool start(uint pc = 0x20000001) {
|
||||
static bool start(uint pc, uint sp) {
|
||||
idle();
|
||||
|
||||
// Start from boot address, which can be read from ROM at 0x4
|
||||
uint rom_pc, rom_sp;
|
||||
read_reg(0x0, rom_sp);
|
||||
read_reg(0x4, rom_pc);
|
||||
|
||||
printf("Set PC\n");
|
||||
if (!write_reg(0xe000edf8, pc) ||
|
||||
if (!write_reg(0xe000edf8, rom_pc) ||
|
||||
!write_reg(0xe000edf4, 0x1000F))
|
||||
{
|
||||
printf("Failed to set PC\n");
|
||||
return false;
|
||||
}
|
||||
printf("Set SP\n");
|
||||
if (!write_reg(0xe000edf8, 0x15004000) || //0x20042000) ||
|
||||
if (!write_reg(0xe000edf8, rom_sp) ||
|
||||
!write_reg(0xe000edf4, 0x1000D))
|
||||
{
|
||||
printf("Failed to set SP\n");
|
||||
|
@ -246,12 +265,21 @@ static bool start(uint pc = 0x20000001) {
|
|||
}
|
||||
idle();
|
||||
|
||||
#if 1
|
||||
// If a PC has been given, go through watchdog boot sequence to start there
|
||||
if (pc != 0) {
|
||||
uint watchdog_data[4] = {0xb007c0d3, 0x4ff83f2d ^ pc, sp, pc};
|
||||
printf("Setup watchdog\n");
|
||||
if (!write_block(0x4005801c, watchdog_data, 4)) {
|
||||
printf("Failed to setup watchdog for reset\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
uint data;
|
||||
write_reg(0xe000edf4, 0x0000F);
|
||||
idle();
|
||||
read_reg(0xe000edf8, data);
|
||||
printf("Set PC to %08x\n", data);
|
||||
printf("PC is %08x\n", data);
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
write_reg(0xe000edf4, i);
|
||||
|
@ -265,7 +293,6 @@ static bool start(uint pc = 0x20000001) {
|
|||
printf("WD%d is %08x\n", i, data);
|
||||
}
|
||||
#endif
|
||||
//write_reg(0x40010008, 0xC000);
|
||||
|
||||
printf("Start CPU\n");
|
||||
if (!write_reg(0xe000edf0, 0xA05F0001)) {
|
||||
|
@ -275,12 +302,34 @@ static bool start(uint pc = 0x20000001) {
|
|||
|
||||
idle();
|
||||
wait_for_idle();
|
||||
//sleep_us(100);
|
||||
|
||||
#if 0
|
||||
sleep_ms(10);
|
||||
|
||||
connect(false);
|
||||
printf("Halt CPU\n");
|
||||
if (!write_reg(0xe000edf0, 0xA05F0003)) {
|
||||
printf("Halt failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
write_reg(0xe000edf4, i);
|
||||
idle();
|
||||
read_reg(0xe000edf8, data);
|
||||
printf("R%d is %08x\n", i, data);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
read_reg(0x4005801c + 4*i, data);
|
||||
printf("WD%d is %08x\n", i, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool swd_load_program(const uint* addresses, const uint** data, const uint* data_len_in_bytes, uint num_sections) {
|
||||
bool swd_load_program(const uint* addresses, const uint** data, const uint* data_len_in_bytes, uint num_sections, uint pc = 0x20000001, uint sp = 0x20042000, bool use_xip_as_ram = false) {
|
||||
gpio_init(2);
|
||||
gpio_init(3);
|
||||
gpio_disable_pulls(2);
|
||||
|
@ -288,13 +337,27 @@ bool swd_load_program(const uint* addresses, const uint** data, const uint* data
|
|||
|
||||
printf("Connecting\n");
|
||||
|
||||
bool ok = connect();
|
||||
|
||||
printf("Connected %s\n", ok ? "OK" : "Fail");
|
||||
bool ok = connect(true, 0xf);
|
||||
printf("Reset %s\n", ok ? "OK" : "Fail");
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ok = connect(false, 0);
|
||||
|
||||
printf("Connected core 0 %s\n", ok ? "OK" : "Fail");
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (use_xip_as_ram) {
|
||||
printf("Disable XIP\n");
|
||||
if (!write_reg(0x14000000, 0)) {
|
||||
printf("Disable XIP failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < num_sections; ++i)
|
||||
{
|
||||
if (!load(addresses[i], data[i], data_len_in_bytes[i])) {
|
||||
|
@ -303,7 +366,12 @@ bool swd_load_program(const uint* addresses, const uint** data, const uint* data
|
|||
}
|
||||
}
|
||||
|
||||
ok = start();
|
||||
ok = start(pc, sp);
|
||||
|
||||
ok |= connect(false, 1);
|
||||
|
||||
ok |= start(0, 0x20041000);
|
||||
|
||||
unload_pio();
|
||||
return ok;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
bool swd_load_program(const uint* addresses, const uint** data, const uint* data_len_in_bytes, uint num_sections);
|
||||
bool swd_load_program(const uint* addresses, const uint** data, const uint* data_len_in_bytes, uint num_sections, uint pc = 0x20000001, uint sp = 0x20042000, bool use_xip_as_ram = false);
|
|
@ -6,7 +6,7 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib dv_display hardware_i2c pico_graphics)
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib dv_display hardware_i2c hardware_uart pico_graphics)
|
||||
|
||||
pico_enable_stdio_usb(${OUTPUT_NAME} 1)
|
||||
|
||||
|
|
|
@ -3,19 +3,37 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "drivers/dv_display/dv_display.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
#define FRAME_WIDTH 640
|
||||
#define FRAME_WIDTH 720
|
||||
#define FRAME_HEIGHT 480
|
||||
|
||||
void on_uart_rx() {
|
||||
while (uart_is_readable(uart1)) {
|
||||
uint8_t ch = uart_getc(uart1);
|
||||
putc(ch, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
set_sys_clock_khz(200000, true);
|
||||
set_sys_clock_khz(216000, true);
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
// Relay UART RX from the display driver
|
||||
gpio_set_function(5, GPIO_FUNC_UART);
|
||||
uart_init(uart1, 115200);
|
||||
uart_set_hw_flow(uart1, false, false);
|
||||
uart_set_format(uart1, 8, 1, UART_PARITY_NONE);
|
||||
uart_set_fifo_enabled(uart1, false);
|
||||
irq_set_exclusive_handler(UART1_IRQ, on_uart_rx);
|
||||
irq_set_enabled(UART1_IRQ, true);
|
||||
uart_set_irq_enables(uart1, true, false);
|
||||
|
||||
constexpr uint BUTTON_A = 9;
|
||||
gpio_init(BUTTON_A);
|
||||
gpio_set_dir(BUTTON_A, GPIO_IN);
|
||||
|
|
Ładowanie…
Reference in New Issue