Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pi Pico port improvements #1050

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ size.report
.obj
*.elf
bin
*.debug
7 changes: 7 additions & 0 deletions Kernel/platform/platform-rpipico/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
utils/progbase.h
utils/ps
utils/ps.c
utils/*.o
filesystem.*
uf2conv

21 changes: 18 additions & 3 deletions Kernel/platform/platform-rpipico/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ set(CMAKE_C_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)
set(PICO_COPY_TO_RAM 1)

add_compile_definitions(
PICO_HEAP_SIZE=0x0
PICO_NO_BINARY_INFO=1
PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
PICO_NO_GC_SECTIONS
)

remove_definitions(
LIB_PICO_STDIO_UART
LIB_PICO_STDIO_USB
LIB_PICO_STDIO_SEMIHOSTING
PICO_NO_GC_SECTIONS
)

pico_sdk_init()

include_directories(
Expand All @@ -20,13 +34,16 @@ include_directories(

add_executable(fuzix
devices.c
devrpi.c
devflash.c
devsdspi.c
#/*devsdspidma.c*/
devtty.c
elf.c
main.c
misc.c
rawflash.c
rawuart.c
swapper.c
tricks.S
core1.c
Expand Down Expand Up @@ -70,9 +87,7 @@ target_link_libraries(fuzix
pico_multicore
hardware_flash
hardware_spi
hardware_uart
tinyusb_device_unmarked
tinyusb_board
tinyusb_device
)

pico_set_float_implementation(fuzix none)
Expand Down
5 changes: 5 additions & 0 deletions Kernel/platform/platform-rpipico/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ image:: world uf2conv
arm-none-eabi-objcopy -I binary -O elf32-littlearm --change-section-vma .data=0x10018000 filesystem.ftl filesystem.elf
./uf2conv filesystem.ftl filesystem.uf2 0x10018000

image-sd:: world uf2conv
./update-flash.sh sd

clean:
rm -rf build
$(MAKE) -C ../../../Library/libs -f Makefile.armm0 clean
Expand All @@ -31,6 +34,7 @@ clean:
$(MAKE) -C ../../../Applications/cave -f Makefile.armm0 clean
$(MAKE) -C ../../../Applications/cursesgames -f Makefile.armm0 clean
$(MAKE) -C ../../../Standalone clean
$(MAKE) -C utils clean

world: build/fuzix.elf
$(MAKE) -C ../../../Library/libs -f Makefile.armm0
Expand All @@ -42,6 +46,7 @@ world: build/fuzix.elf
$(MAKE) -C ../../../Applications/cave -f Makefile.armm0
$(MAKE) -C ../../../Applications/cursesgames -f Makefile.armm0
$(MAKE) -C ../../../Standalone
$(MAKE) -C utils

uf2conv: tools/uf2conv.c
cc -O -g -o $@ $<
Expand Down
15 changes: 15 additions & 0 deletions Kernel/platform/platform-rpipico/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ You can't turn swap off again.

You probably can swap to the NAND flash, but it's a terrible idea.

## Boot device

Edit config.h to select appropriate boot device.

`#define BOOTDEVICE 0x0000` - for NAND flash (hda)

`#define BOOTDEVICE 0x0011` - for the first partioin on the SD card (hdb1)

## Using the NAND flash

The Pico's built-in NAND flash is supported, appearing as `/dev/hda` insize
Expand All @@ -131,6 +139,13 @@ gets notified when sectors become free, but if the filesystem gets very full
and Dhara runs out it can get extremely slow as it constantly does garbage
collection.

## Using SD Card

1. Create dos partition table
* Partition 1: 32MB partition
* Partition 2: 4MB partition (optional)
2. Run `dd if=filesystem.img bs=512 seek=2048 of=/dev/sdX conv=notrunc status=progress` to copy image onto SD card. (**Be careful to not damage your system drive**)

## Issues

There are many, the biggest of which are:
Expand Down
27 changes: 22 additions & 5 deletions Kernel/platform/platform-rpipico/config.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "tusb_config.h"
/*
* Set this according to your SD card pins (default
* is the David Given arrangement).
Expand Down Expand Up @@ -42,13 +45,22 @@
#undef CONFIG_VT
#undef CONFIG_FONT8X8

/* Disable block device in flash. Warning, it's unstable. */
#define PICO_DISABLE_FLASH

/* Program layout */
#ifndef PICO_DISABLE_FLASH
#define FLASHCODESIZE 7
#else
#define FLASHCODESIZE 0
#endif

#define USERMEM ((172-FLASHCODESIZE)*1024)

#define UDATA_BLKS 3
#define UDATA_SIZE (UDATA_BLKS << BLKSHIFT)
#define USERMEM (160*1024)
#define PROGSIZE (65536 - UDATA_SIZE)
extern uint8_t progbase[USERMEM];
extern char progbase[USERMEM];
#define udata (*(struct u_data*)progbase)

#define USERSTACK (4*1024) /* 4kB */
Expand All @@ -69,11 +81,16 @@ extern uint8_t progbase[USERMEM];
/* We need a tidier way to do this from the loader */
#define CMDLINE NULL /* Location of root dev name */

#define BOOTDEVICE 0x0000 /* hda */
#define BOOTDEVICE 0x0011 /* hda 0x0000 hdb1 0x0011 */
#define SWAPDEV (swap_dev) /* dynamic swap */

/* Device parameters */
#define NUM_DEV_TTY 1
#define NUM_DEV_TTY_UART 1
#define NUM_DEV_TTY_USB (CFG_TUD_CDC)
#define NUM_DEV_TTY (NUM_DEV_TTY_UART + NUM_DEV_TTY_USB)

#define USB_TO_TTY(x) (x + 1 + NUM_DEV_TTY_UART)
#define TTY_TO_USB(x) (x - 1 - NUM_DEV_TTY_UART)

#define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */
#define NBUFS 20 /* Number of block buffers */
Expand All @@ -91,5 +108,5 @@ extern uint8_t progbase[USERMEM];
#define MANGLED 1
#include "mangle.h"

#endif
// vim: sw=4 ts=4 et

174 changes: 129 additions & 45 deletions Kernel/platform/platform-rpipico/core1.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,174 @@
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <kernel.h>
#include "picosdk.h"
#include "config.h"
#include "core1.h"

#include <tusb.h>
#include <pico/stdlib.h>
#include <pico/time.h>
#include <pico/binary_info.h>
#include <pico/critical_section.h>
#include <pico/multicore.h>
#include <hardware/uart.h>
#include <hardware/irq.h>
#include "core1.h"

bool usbconsole_is_readable(void)
#define CONFIG_CONSOLE_BUF_LEN 16

#if CONFIG_CONSOLE_BUF_LEN > 255
#error "Invalid console buffer length"
#endif

struct console_buf_t
{
return multicore_fifo_rvalid();
uint8_t buffer[CONFIG_CONSOLE_BUF_LEN];
uint8_t rindex;
uint8_t windex;
uint8_t len;
};

struct console_t
{
struct console_buf_t rbuf;
struct console_buf_t wbuf;
bool sleeping;
};

static struct console_t console_table[NUM_DEV_TTY_USB];
critical_section_t critical_section;

static void console_buf_write(struct console_buf_t *buf, uint8_t b)
{
/*
can deadlock core1 thread
while(buf->len >= CONFIG_CONSOLE_BUF_LEN)
tight_loop_contents();
*/
critical_section_enter_blocking(&critical_section);
if(buf->len < CONFIG_CONSOLE_BUF_LEN)
{
buf->buffer[buf->windex] = b;
buf->windex = (buf->windex + 1) % CONFIG_CONSOLE_BUF_LEN;
buf->len++;
}
critical_section_exit(&critical_section);
}

bool usbconsole_is_writable(void)
static uint8_t console_buf_read(struct console_buf_t *buf)
{
return multicore_fifo_wready();
critical_section_enter_blocking(&critical_section);
if(buf->len == 0)
{
panic("rd undrf");
}
uint8_t b = buf->buffer[buf->rindex];
buf->rindex = (buf->rindex + 1) % CONFIG_CONSOLE_BUF_LEN;
buf->len--;
critical_section_exit(&critical_section);
return b;
}

uint8_t usbconsole_getc_blocking(void)
int usbconsole_read(uint8_t *buffer, int size)
{
return multicore_fifo_pop_blocking();
if(size & 0x01)
{
panic("buf size");
}
int written = 0;
for(int i = 0; i < NUM_DEV_TTY && written < size; i++)
{
struct console_buf_t *buf = &console_table[i].rbuf;
if (buf->len > 0)
{
buffer[0] = USB_TO_TTY(i);
buffer[1] = console_buf_read(buf);
buffer += 2;
written += 2;
}
}
return written;
}

void usbconsole_putc_blocking(uint8_t b)
extern bool usbconsole_is_writable(uint8_t minor)
{
multicore_fifo_push_blocking(b);
minor = TTY_TO_USB(minor);
return console_table[minor].wbuf.len < CONFIG_CONSOLE_BUF_LEN;
}

static void core1_main(void)
extern bool usbconsole_is_available(uint8_t minor)
{
uart_init(uart_default, PICO_DEFAULT_UART_BAUD_RATE);
gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART);
uart_set_translate_crlf(uart_default, false);
uart_set_fifo_enabled(uart_default, true);
minor = TTY_TO_USB(minor);
return minor <= NUM_DEV_TTY_USB;
}

tusb_init();
extern void usbconsole_putc(uint8_t minor, uint8_t b)
{
minor = TTY_TO_USB(minor);
if (minor >= NUM_DEV_TTY_USB)
{
panic("ttydev");
}
struct console_buf_t *buf = &console_table[minor].wbuf;
if (buf->len >= CONFIG_CONSOLE_BUF_LEN)
{
panic("ovf");
}

console_buf_write(buf, b);
}

extern void usbconsole_setsleep(uint8_t minor, bool sleeping)
{
console_table[TTY_TO_USB(minor)].sleeping = sleeping;
}

extern bool usbconsole_is_sleeping(uint8_t minor)
{
return console_table[TTY_TO_USB(minor)].sleeping;
}

static void core1_main(void)
{
tusb_init();

for (;;)
{
tud_task();

if (multicore_fifo_rvalid()
&& (!tud_cdc_connected() || tud_cdc_write_available())
&& uart_is_writable(uart_default))
{
int b = multicore_fifo_pop_blocking();
/*
We ignore tud_cdc_n_connected because if DTR is not set by the host
all tty's will appear disconnected, which seems to be the case for pi pico
*/

if (tud_cdc_connected())
for(int i = 0; i < CFG_TUD_CDC; i++)
{
if (tud_cdc_n_write_available(i)
&& console_table[i].wbuf.len)
{
tud_cdc_write(&b, 1);
tud_cdc_write_flush();
uint8_t b = console_buf_read(&console_table[i].wbuf);
tud_cdc_n_write_char(i, b);
tud_cdc_n_write_flush(i);
}

uart_putc(uart_default, b);
}

if (multicore_fifo_wready()
&& ((tud_cdc_connected() && tud_cdc_available())
|| uart_is_readable(uart_default)))
for (int i = 0; i < CFG_TUD_CDC; i++)
{
/* Only service a byte from CDC *or* the UART, in case two show
* up at the same time and we end up blocking. No big loss, the
* next one will be read the next time around the loop. */

if (tud_cdc_available())
if (!tud_cdc_n_available(i))
{
uint8_t b;
int count = tud_cdc_read(&b, 1);
if (count)
multicore_fifo_push_blocking(b);
continue;
}
else if (uart_is_readable(uart_default))
struct console_buf_t *buf = &console_table[i].rbuf;
if (buf->len < CONFIG_CONSOLE_BUF_LEN)
{
uint8_t b = uart_get_hw(uart_default)->dr;
multicore_fifo_push_blocking(b);
uint8_t b = tud_cdc_n_read_char(i);
console_buf_write(buf, b);
}
}
}
}

void core1_init(void)
{
multicore_reset_core1();
critical_section_init(&critical_section);
multicore_launch_core1(core1_main);
}

Loading
Loading