diff options
Diffstat (limited to 'src/modchipfw')
-rw-r--r-- | src/modchipfw/CMakeLists.txt | 40 | ||||
-rw-r--r-- | src/modchipfw/pico_sdk_import.cmake | 62 | ||||
-rw-r--r-- | src/modchipfw/pulsegen.pio | 70 | ||||
-rw-r--r-- | src/modchipfw/utglitcher.c | 158 |
4 files changed, 330 insertions, 0 deletions
diff --git a/src/modchipfw/CMakeLists.txt b/src/modchipfw/CMakeLists.txt new file mode 100644 index 0000000..9367d0f --- /dev/null +++ b/src/modchipfw/CMakeLists.txt @@ -0,0 +1,40 @@ +# Generated Cmake Pico project file + +cmake_minimum_required(VERSION 3.13) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +# Initialise pico_sdk from installed location +# (note this can come from environment, CMake cache etc) +# set(PICO_SDK_PATH "~/pico/pico-sdk") + +# Pull in Raspberry Pi Pico SDK (must be before project) +include(pico_sdk_import.cmake) + +project(utglitcher C CXX ASM) + +# Initialise the Raspberry Pi Pico SDK +pico_sdk_init() + +# Add executable. Default name is the project name, version 0.1 + +add_executable(utglitcher utglitcher.c ) + +pico_set_program_name(utglitcher "utglitcher") +pico_set_program_version(utglitcher "0.3") + +pico_enable_stdio_uart(utglitcher 0) +pico_enable_stdio_usb(utglitcher 1) + +# Add the standard library to the build +target_link_libraries(utglitcher pico_stdlib) + +# Add any user requested libraries +target_link_libraries(utglitcher + hardware_pio + pico_multicore + ) + +pico_generate_pio_header(utglitcher ${CMAKE_CURRENT_LIST_DIR}/pulsegen.pio) +pico_add_extra_outputs(utglitcher) diff --git a/src/modchipfw/pico_sdk_import.cmake b/src/modchipfw/pico_sdk_import.cmake new file mode 100644 index 0000000..28efe9e --- /dev/null +++ b/src/modchipfw/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/src/modchipfw/pulsegen.pio b/src/modchipfw/pulsegen.pio new file mode 100644 index 0000000..4068940 --- /dev/null +++ b/src/modchipfw/pulsegen.pio @@ -0,0 +1,70 @@ +.program pulsegen + +; we use 2 bits from the delay bits for side set +.side_set 2 + +entry: + ; Could probably get rid of these blocking PULLs by enabling autopull and writing to the fifo before enabling the SM? + ; Read number of edges + PULL BLOCK side 0 + MOV X, OSR side 0 ; Might want to use OUT here instead of MOV + + ; Read pulse offset + PULL BLOCK side 0 + MOV Y, OSR side 0 + + ; Clear interrupt (might not be needed if we clear it on the M0 side of things?) + IRQ CLEAR 0 side 0 + +nedges: + ; Wait for rising-edges + WAIT 0 PIN 0 side 0 + WAIT 1 PIN 0 side 0 + JMP X-- nedges side 0 + + ; Read pulse width + ; This will cause a fixed delay between the trigger event and the glitch insertion. Fine for our purposes. + PULL BLOCK side 0 + MOV X, OSR side 0 + +; Loop for pulse offset cycles +poffset: + JMP Y-- poffset side 2 + +; Loop for pulse width cycles +pwidth: + JMP X-- pwidth side 3 + + + SET Y, 31 side 2 ; A fixed delay to ensure that the glitch has been inserted before the capacitors are enabled again. +delay: + NOP side 2 [7] + NOP side 2 [7] + NOP side 2 [7] + NOP side 2 [7] + NOP side 2 [7] + JMP Y-- delay side 2 + + ; Signal that the pulse has been inserted, and disable the pulse using sideset + IRQ WAIT 0 side 0 + + +% c-sdk { +void pulsegen_program_init(PIO pio, uint sm, uint offset, uint trigger_pin, uint pulse_pin, uint caps_pin) { + pio_sm_config c = pulsegen_program_get_default_config(offset); + + sm_config_set_sideset_pins(&c, pulse_pin); + sm_config_set_in_pins(&c, trigger_pin); + sm_config_set_in_shift(&c, false, false, 32); + + pio_gpio_init(pio, trigger_pin); + pio_gpio_init(pio, pulse_pin); + pio_gpio_init(pio, caps_pin); + + pio_sm_set_consecutive_pindirs(pio, sm, trigger_pin, 1, false); + pio_sm_set_consecutive_pindirs(pio, sm, pulse_pin, 2, true); + + sm_config_set_clkdiv(&c, 1); + pio_sm_init(pio, sm, offset, &c); +} +%}
\ No newline at end of file diff --git a/src/modchipfw/utglitcher.c b/src/modchipfw/utglitcher.c new file mode 100644 index 0000000..5ba5c94 --- /dev/null +++ b/src/modchipfw/utglitcher.c @@ -0,0 +1,158 @@ +#include <stdio.h> +#include "pico/stdlib.h" +#include "hardware/uart.h" +#include "hardware/gpio.h" +#include "hardware/pio.h" +#include "hardware/clocks.h" +#include "hardware/vreg.h" +#include "pulsegen.pio.h" + +#define PIN_NRST 7 +#define PIN_TRIG 6 +#define PIN_PULSE 0 +#define PIN_CAPS 1 + +#define PIN_LED1 16 +#define PIN_LED2 17 + +int main() +{ + /* + * For some reason the serial communication fails after some time when running at 200MHz + * For me everything worked fine at 250 MHz without changing the core voltage (vreg_set_voltage) + */ + set_sys_clock_khz(250000, true); + + stdio_init_all(); + + // GPIO initialisation. + gpio_init(PIN_NRST); + gpio_init(PIN_TRIG); + gpio_init(PIN_PULSE); + gpio_init(PIN_CAPS); + gpio_init(PIN_LED1); + gpio_init(PIN_LED2); + gpio_set_dir(PIN_NRST, GPIO_OUT); + gpio_set_dir(PIN_TRIG, GPIO_IN); + gpio_set_dir(PIN_PULSE, GPIO_OUT); + gpio_set_dir(PIN_CAPS, GPIO_OUT); + gpio_set_dir(PIN_LED1, GPIO_OUT); + gpio_set_dir(PIN_LED2, GPIO_OUT); + gpio_set_pulls(PIN_CAPS, true, false); + gpio_set_drive_strength(PIN_PULSE, GPIO_DRIVE_STRENGTH_12MA); + gpio_set_drive_strength(PIN_CAPS, GPIO_DRIVE_STRENGTH_12MA); + gpio_set_slew_rate(PIN_PULSE, GPIO_SLEW_RATE_FAST); + + // Setup PIO + PIO pio = pio0; + uint32_t sm = pio_claim_unused_sm(pio, true); + uint32_t pio_offset = pio_add_program(pio, &pulsegen_program); + pulsegen_program_init(pio, sm, pio_offset, PIN_TRIG, PIN_PULSE, PIN_CAPS); + + // Wait for serial connection + while (!stdio_usb_connected()) { + sleep_ms(500); + } + + gpio_put(PIN_LED1, true); + gpio_put(PIN_NRST, false); + + char cmd; + uint32_t pulse_offset = 0; + uint32_t pulse_width = 0; + uint32_t trig_edges = 1; + uint32_t gpio_states = 0; + + uint8_t gpio_pin = 0; + uint8_t gpio_state = 0; + + while (true) { + cmd = getchar(); + + switch (cmd) + { + // Enable glitch SM + case 'A': + gpio_put(PIN_LED2, true); + pio_sm_put_blocking(pio, sm, trig_edges); + pio_sm_put_blocking(pio, sm, pulse_offset); + pio_sm_put_blocking(pio, sm, pulse_width); + + gpio_put(PIN_NRST, true); + sleep_ms(46); // Delay to make sure all UT signals are stable + + pio_sm_set_enabled(pio, sm, true); + printf("A\n"); + break; + + // Wait for trigger + case 'B': + while(!pio_interrupt_get(pio0, 0)) { + cmd = getchar_timeout_us(1); + if (cmd == 'D') break; // Disarm + }; + + pio_sm_set_enabled(pio, sm, false); + pio_interrupt_clear(pio, 0); + pio_sm_clear_fifos(pio, sm); + pio_sm_drain_tx_fifo(pio, sm); + pio_sm_restart(pio, sm); + pio_sm_set_enabled(pio, sm, false); + + pio_sm_exec_wait_blocking(pio, sm, pio_encode_set(pio_x, pio_offset)); + pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_pc, pio_x)); + printf("T\n"); + gpio_put(PIN_LED2, false); + break; + + // Set the number of edges before inserting a pulse + case 'E': + fread(&trig_edges, 1, 4, stdin); + printf("%d\n", trig_edges); + break; + + // Set the pulse offset + case 'O': + fread(&pulse_offset, 1, 4, stdin); + printf("%d\n", pulse_offset); + break; + + // Set the pulse width + case 'W': + fread(&pulse_width, 1, 4, stdin); + printf("%d\n", pulse_width); + break; + + // print the current pulse offset and width + case 'S': + printf("PulseGenerator offset: %d, width: %d, edges: %d\n", pulse_offset, pulse_width, trig_edges); + break; + + // control a gpio pin, can be expanded to handle multiple pins + case 'G': + fread(&gpio_pin, 1, 1, stdin); + fread(&gpio_state, 1, 1, stdin); + + if (gpio_pin == PIN_NRST) { + if (gpio_state == 0) { + gpio_put(PIN_NRST, false); + } else { + gpio_put(PIN_NRST, true); + } + } + printf("G\n"); + break; + + // Read state of GPIOs + case 'R': + gpio_states = gpio_get_all(); + printf("%d\n", gpio_states); + break; + + default: + break; + } + } + + return 0; +}
\ No newline at end of file |