add stuff
This commit is contained in:
commit
5dfd44123f
|
@ -0,0 +1 @@
|
||||||
|
build/
|
|
@ -0,0 +1,59 @@
|
||||||
|
# use directory name for project id
|
||||||
|
set(FAMILY "rp2040" CACHE STRING "Board/MCU family, decides which drivers to use. Set to RP2040 by default.")
|
||||||
|
set(BOARD "raspberry_pi_pico" CACHE STRING "Board used, determines the pinout. Defaults to the Raspberry Pi Pico.")
|
||||||
|
|
||||||
|
set(PROJECT "430prog")
|
||||||
|
#set(PROJECT ${BOARD}-${PROJECT})
|
||||||
|
|
||||||
|
# TOP is absolute path to root directory of TinyUSB git repo
|
||||||
|
|
||||||
|
# Check for -DFAMILY=
|
||||||
|
if(FAMILY STREQUAL "rp2040")
|
||||||
|
option(PICO_NO_FLASH "Disable writing the compiled program to flash, and only load it to RAM. Useful for testing, but not much else (OFF by default)." ON)
|
||||||
|
option(PICO_COPY_TO_RAM "Run all code in RAM, while the program is also stored on flash. On bootup, everything will be copied to RAM (OFF by default)." OFF)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
#set(TOP "$ENV{PICO_SDK_PATH}/lib/tinyusb")
|
||||||
|
#get_filename_component(TOP "${TOP}" REALPATH)
|
||||||
|
include(cmake/pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
#include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
|
||||||
|
|
||||||
|
#family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
project(${PROJECT})
|
||||||
|
#family_initialize_project(PROJECT ${CMAKE_CURRENT_LIST_DIR}) # calls pico_sdk_init()
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
add_executable(${PROJECT})
|
||||||
|
|
||||||
|
pico_enable_stdio_uart(${PROJECT} 1)
|
||||||
|
pico_enable_stdio_usb(${PROJECT} 0)
|
||||||
|
# Example source
|
||||||
|
target_sources(${PROJECT} PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/pio_sbw.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Example include
|
||||||
|
target_include_directories(${PROJECT} PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/
|
||||||
|
)
|
||||||
|
|
||||||
|
# Example defines
|
||||||
|
target_compile_definitions(${PROJECT} PUBLIC
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT} pico_stdlib pico_unique_id
|
||||||
|
hardware_pio hardware_dma hardware_pwm)
|
||||||
|
|
||||||
|
pico_generate_pio_header(${PROJECT} ${CMAKE_CURRENT_SOURCE_DIR}/src/sbw.pio)
|
||||||
|
|
||||||
|
pico_add_extra_outputs(${PROJECT})
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Invalid FAMILY specified")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Werror=maybe-uninitialized")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--cref")
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# 430prog
|
||||||
|
|
||||||
|
Researching MSP430 programming/Spy-Bi-Wire debugging impl on the RP2040. It's
|
||||||
|
all very WIP. Will probably be integrated into DragonProbe when ready.
|
||||||
|
|
|
@ -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})
|
|
@ -0,0 +1 @@
|
||||||
|
*.bak*
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
#include <pico/binary_info.h>
|
||||||
|
#include "pio_sbw.h"
|
||||||
|
|
||||||
|
void printbuf(const uint8_t* buf, size_t size) {
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
printf("%02x%c", buf[i], i % 16 == 15 ? '\n' : ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
bool s = sbw_init();
|
||||||
|
printf("%s", s ? "inited" : "failure");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <hardware/clocks.h>
|
||||||
|
#include <hardware/dma.h>
|
||||||
|
#include <hardware/gpio.h>
|
||||||
|
#include <hardware/pio.h>
|
||||||
|
#include <hardware/pio_instructions.h>
|
||||||
|
|
||||||
|
#include "pio_sbw.h"
|
||||||
|
|
||||||
|
#include "sbw.pio.h"
|
||||||
|
|
||||||
|
int sbw_piosm = -1, sbw_offset = -1;
|
||||||
|
|
||||||
|
bool sbw_init(void) {
|
||||||
|
if (sbw_piosm >= 0 || sbw_offset >= 0) return false;
|
||||||
|
|
||||||
|
if (!pio_can_add_program(PINOUT_SBW_PIO, &sbw_program)) return false;
|
||||||
|
sbw_offset = pio_add_program(PINOUT_SBW_PIO, &sbw_program);
|
||||||
|
|
||||||
|
sbw_piosm = pio_claim_unused_sm(PINOUT_SBW_PIO, false);
|
||||||
|
if (sbw_piosm < 0) {
|
||||||
|
pio_remove_program(PINOUT_SBW_PIO, &sbw_program, sbw_offset);
|
||||||
|
sbw_offset = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sbw_pio_init(PINOUT_SBW_PIO, sbw_piosm, sbw_offset, 200e3,
|
||||||
|
PINOUT_SBW_TCK, PINOUT_SBW_TDIO);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbw_deinit(void) {
|
||||||
|
if (sbw_piosm >= 0) {
|
||||||
|
pio_sm_set_enabled(PINOUT_SBW_PIO, sbw_piosm, false);
|
||||||
|
pio_sm_unclaim(PINOUT_SBW_PIO, sbw_piosm);
|
||||||
|
sbw_piosm = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sbw_offset >= 0) {
|
||||||
|
pio_remove_program(PINOUT_SBW_PIO, &sbw_program, sbw_offset);
|
||||||
|
sbw_offset = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbw_set_freq(bool tclk, float freq) {
|
||||||
|
if (tclk) {
|
||||||
|
sbw_pio_set_tclkfreq(PINOUT_SBW_PIO, sbw_piosm, freq);
|
||||||
|
} else {
|
||||||
|
sbw_pio_set_baudrate(PINOUT_SBW_PIO, sbw_piosm, freq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbw_sequence(uint32_t ncyc, uint32_t tms, const uint8_t* tdi, uint8_t* tdo) {
|
||||||
|
static uint64_t last_tdi = ~(uint64_t)0;
|
||||||
|
static uint64_t devnull = 0;
|
||||||
|
|
||||||
|
uint32_t nbytes = (ncyc + 7) >> 3;
|
||||||
|
|
||||||
|
// fuck this im not doing this rn sorry
|
||||||
|
// TODO: finish this tomorrow
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbw_tms_sequence(uint32_t ncyc, uint32_t tdi, const uint8_t* tms) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int last_tclk = 1;
|
||||||
|
|
||||||
|
void sbw_clr_tclk(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
void sbw_set_tclk(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbw_tclk_burst(uint32_t ncyc) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just 8 bit functions provided here. The PIO program supports any frame size
|
||||||
|
// 1...32, but the software to do the necessary FIFO shuffling is left as an
|
||||||
|
// exercise for the reader :)
|
||||||
|
//
|
||||||
|
// Likewise we only provide MSB-first here. To do LSB-first, you need to
|
||||||
|
// - Do shifts when reading from the FIFO, for general case n != 8, 16, 32
|
||||||
|
// - Do a narrow read at a one halfword or 3 byte offset for n == 16, 8
|
||||||
|
// in order to get the read data correctly justified.
|
||||||
|
|
||||||
|
/*void __time_critical_func(pio_spi_write8_blocking)(const pio_spi_inst_t *spi, const uint8_t *src, size_t len) {
|
||||||
|
size_t tx_remain = len, rx_remain = len;
|
||||||
|
// Do 8 bit accesses on FIFO, so that write data is byte-replicated. This
|
||||||
|
// gets us the left-justification for free (for MSB-first shift-out)
|
||||||
|
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||||
|
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||||
|
while (tx_remain || rx_remain) {
|
||||||
|
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||||
|
*txfifo = *src++;
|
||||||
|
--tx_remain;
|
||||||
|
}
|
||||||
|
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||||
|
(void) *rxfifo;
|
||||||
|
--rx_remain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __time_critical_func(pio_spi_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *dst, size_t len) {
|
||||||
|
size_t tx_remain = len, rx_remain = len;
|
||||||
|
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||||
|
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||||
|
while (tx_remain || rx_remain) {
|
||||||
|
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||||
|
*txfifo = 0;
|
||||||
|
--tx_remain;
|
||||||
|
}
|
||||||
|
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||||
|
*dst++ = *rxfifo;
|
||||||
|
--rx_remain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __time_critical_func(pio_spi_write8_read8_blocking)(const pio_spi_inst_t *spi, uint8_t *src, uint8_t *dst,
|
||||||
|
size_t len) {
|
||||||
|
size_t tx_remain = len, rx_remain = len;
|
||||||
|
io_rw_8 *txfifo = (io_rw_8 *) &spi->pio->txf[spi->sm];
|
||||||
|
io_rw_8 *rxfifo = (io_rw_8 *) &spi->pio->rxf[spi->sm];
|
||||||
|
while (tx_remain || rx_remain) {
|
||||||
|
if (tx_remain && !pio_sm_is_tx_fifo_full(spi->pio, spi->sm)) {
|
||||||
|
*txfifo = *src++;
|
||||||
|
--tx_remain;
|
||||||
|
}
|
||||||
|
if (rx_remain && !pio_sm_is_rx_fifo_empty(spi->pio, spi->sm)) {
|
||||||
|
*dst++ = *rxfifo;
|
||||||
|
--rx_remain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef _PIO_SPI_H
|
||||||
|
#define _PIO_SPI_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
/*#include <hardware/pio.h>*/
|
||||||
|
|
||||||
|
#define PINOUT_SBW_PIO pio0
|
||||||
|
#define PINOUT_SBW_TCK 8
|
||||||
|
#define PINOUT_SBW_TDIO 9
|
||||||
|
|
||||||
|
extern int sbw_piosm, sbw_offset;
|
||||||
|
|
||||||
|
bool sbw_init(void);
|
||||||
|
void sbw_deinit(void);
|
||||||
|
|
||||||
|
void sbw_set_freq(bool tclk, float freq);
|
||||||
|
|
||||||
|
void sbw_sequence(uint32_t ncyc, uint32_t tms, const uint8_t* tdi, uint8_t* tdo);
|
||||||
|
void sbw_tms_sequence(uint32_t ncyc, uint32_t tdi, const uint8_t* tms);
|
||||||
|
|
||||||
|
void sbw_clr_tclk(void);
|
||||||
|
void sbw_set_tclk(void);
|
||||||
|
|
||||||
|
void sbw_tclk_burst(uint32_t ncyc);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,192 @@
|
||||||
|
;
|
||||||
|
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
;
|
||||||
|
; SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
;
|
||||||
|
|
||||||
|
.program sbw
|
||||||
|
.side_set 1
|
||||||
|
|
||||||
|
; Pin assignments:
|
||||||
|
; - SBWTCK is side-set pin 0
|
||||||
|
; - SBWTDIO is OUT/IN pin 0
|
||||||
|
;
|
||||||
|
; Autopush and autopull must be enabled, set to 8
|
||||||
|
; SBWTDIO input should not be guarded with sync flipflops, as TDO xfers are synchronous
|
||||||
|
|
||||||
|
PUBLIC start:
|
||||||
|
; SBWTCK hi to not lose/reset debug mode
|
||||||
|
pull side 1 ; clear leftover OSR bits, pull in new data
|
||||||
|
startloop:
|
||||||
|
out exec, 16 side 1 ; use for set y, 0/1 ; in x, num ; jmp addr
|
||||||
|
jmp startloop side 1
|
||||||
|
|
||||||
|
; "subroutine" "calling convention"
|
||||||
|
; * set y, 0/1 : initial TMS (sbw_seq) / TDI (sbw_tms_seq) / TCLK (sbw_tclk_burst) value
|
||||||
|
; * in x, num : number of JTAG cycles (sbw_seq/sbw_tms_seq) / TCLK half-cycles (sbw_tclk_burst)
|
||||||
|
; * jmp subroutine
|
||||||
|
; * ^ all 'side 1'
|
||||||
|
|
||||||
|
; y: static TMS value to use
|
||||||
|
; x: number of JTAG clock cycles minus one
|
||||||
|
; TDI output gets sourced bit by bit from the TX FIFO
|
||||||
|
; TDO input gets sent bit by bit to the RX FIFO
|
||||||
|
PUBLIC sbw_seq:
|
||||||
|
sbw_seq_iter:
|
||||||
|
; tms slot:
|
||||||
|
set pindirs, 1 side 1 ; SBWTDIO is now output
|
||||||
|
mov pins, y side 1 ; output static TMS value
|
||||||
|
nop side 0 [1] ; target reads TMS at falling edge
|
||||||
|
; tdi slot:
|
||||||
|
out pins, 1 side 1 [1] ; output TDI from FIFO
|
||||||
|
nop side 0 [1] ; target reads TDI at falling edge
|
||||||
|
; tdo slot:
|
||||||
|
set pindirs, 0 side 1 [1] ; we need some clock pulse
|
||||||
|
nop side 0 ; give target some time to drive IO
|
||||||
|
in pins, 1 side 0 ; input TDO
|
||||||
|
|
||||||
|
jmp x--, sbw_seq_iter side 1 ; also gives target some time to stop driving IO
|
||||||
|
|
||||||
|
push side 1 ; flush ISR
|
||||||
|
jmp start side 1
|
||||||
|
|
||||||
|
|
||||||
|
; y: static TDI value to use
|
||||||
|
; x: number of JTAG clock cycles minus one
|
||||||
|
; TMS output gets sourced bit by bit from the TX FIFO
|
||||||
|
PUBLIC sbw_tms_seq:
|
||||||
|
; tms slot
|
||||||
|
set pindirs, 1 side 1 ; SBWTDIO is now output
|
||||||
|
out pins, 1 side 1 ; output TMS from FIFO
|
||||||
|
nop side 0 [1] ; target reads TMS at falling edge
|
||||||
|
; tdi slot
|
||||||
|
mov pins, y side 1 [1] ; output static TDI value
|
||||||
|
nop side 0 [1] ; target reads TDI at falling edge
|
||||||
|
; tdo slot
|
||||||
|
set pindirs, 0 side 1 [1]
|
||||||
|
jmp x--, sbw_tms_seq side 0 [1] ; ignore returned TDO, go back
|
||||||
|
|
||||||
|
jmp start side 1
|
||||||
|
|
||||||
|
|
||||||
|
; stationary SBWTCK values are:
|
||||||
|
; jmp
|
||||||
|
; TMS TDI TDO |TMS TDI TDO
|
||||||
|
; | | | || | |
|
||||||
|
; 1100110011001110011001100 ...
|
||||||
|
;
|
||||||
|
; a full cycle takes 13 cycles, a single slot 4
|
||||||
|
; the SM divider should be sysclk/(4*baudrate)
|
||||||
|
; baudrate shouldn't exceed 20 MHz (typical value is 1.8 MHz?)
|
||||||
|
; SBWTCK LOW phases shouldn't exceed 7us, so the baudrate should be at least 72 kHz
|
||||||
|
|
||||||
|
; y: initial/previous TCLK value
|
||||||
|
; x: number of TCLK *half*-cycles minus one!
|
||||||
|
; TCLK values get sourced from the TX FIFO. best is to use a DMA with fixed
|
||||||
|
; source address, with value 0x55/0xaa (depending on y) for strobes, or
|
||||||
|
; 0x00/0xff (and x=0) for a single set/clear.
|
||||||
|
; alternatively, one could set the "load-bearing instruction" to a
|
||||||
|
; "set pins, 0/1 side 1 [12]" for a fixed value useful for single sets/clears
|
||||||
|
PUBLIC sbw_tclk_burst:
|
||||||
|
set pindirs, 1 side 1 ; SBWTDIO is now output
|
||||||
|
; tms slot:
|
||||||
|
set pins, 0 side 1 ; stay in run-test/idle TAP state
|
||||||
|
nop side 0 ; target reads TMS at falling edge
|
||||||
|
mov pins, y side 0 ; during low phase, prepare TCLK
|
||||||
|
; tdi slot:
|
||||||
|
nop side 1 ; wait a bit
|
||||||
|
burst_loop:
|
||||||
|
PUBLIC sbw_tclk_burst_loadbearing_insn:
|
||||||
|
out pins, 1 side 1 [12] ; in the middle of TDI hiphase: do TCLK
|
||||||
|
jmp x--, burst_loop side 1 [12]
|
||||||
|
nop side 0 [1] ; need a low clock edge for TDO
|
||||||
|
; tdo slot:
|
||||||
|
set pindirs, 0 side 1 [1]
|
||||||
|
nop side 0 [1]
|
||||||
|
|
||||||
|
;jmp start side 1 ; not needed because of wrapping
|
||||||
|
; 32 insns -- filling one entire PIO instruction memory
|
||||||
|
|
||||||
|
; TODO: update this paragraph
|
||||||
|
; a full TCLK cycle in this burst mode takes 24 PIOSM cycles. at a "standard"
|
||||||
|
; baudrate of 18 MHz, this ends up being 375 kHz, which is in the required
|
||||||
|
; range when doing eg. flash programming. at the max baudrate (20 MHz), the
|
||||||
|
; TCLK speed is 417 kHz, which is still ok. max TCLK would be, if PIOSM freq is
|
||||||
|
; 125 MHz, 2.6 MHz, which is good enough imo
|
||||||
|
; TODO: determine minimum baudrate for stable TCLK (12 MHz?)
|
||||||
|
|
||||||
|
|
||||||
|
% c-sdk {
|
||||||
|
static inline void sbw_pio_init(PIO pio, uint sm, uint prog_offs,
|
||||||
|
float freq, uint pin_sbwclk, uint pin_sbwio) {
|
||||||
|
if (freq < 72e3) freq = 72e3;
|
||||||
|
if (freq > 20e6) freq = 20e6;
|
||||||
|
|
||||||
|
pio_sm_config c = sbw_program_get_default_config(prog_offs);
|
||||||
|
sm_config_set_out_pins(&c, pin_sbwio, 1);
|
||||||
|
sm_config_set_in_pins(&c, pin_sbwio);
|
||||||
|
sm_config_set_sideset_pins(&c, pin_sbwclk);
|
||||||
|
sm_config_set_out_shift(&c, false, true, 8);
|
||||||
|
sm_config_set_in_shift(&c, false, true, 8);
|
||||||
|
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (4 * freq));
|
||||||
|
|
||||||
|
// SBWTDIO is low, SBWTCK is high, SBWTDIO is input by default
|
||||||
|
// MOSI, SCK output are low, MISO is input
|
||||||
|
pio_sm_set_pins_with_mask(pio, sm,
|
||||||
|
(1u << pin_sbwclk), (1u << pin_sbwclk) | (1u << pin_sbwio));
|
||||||
|
pio_sm_set_pindirs_with_mask(pio, sm,
|
||||||
|
(1u << pin_sbwclk), (1u << pin_sbwclk) | (1u << pin_sbwio));
|
||||||
|
pio_gpio_init(pio, pin_sbwclk);
|
||||||
|
pio_gpio_init(pio, pin_sbwio );
|
||||||
|
|
||||||
|
// SBW is mostly synchronous, bypass input synchroniser to reduce delay
|
||||||
|
hw_set_bits(&pio->input_sync_bypass, 1u << pin_sbwio);
|
||||||
|
|
||||||
|
pio_sm_init(pio, sm, prog_offs, &c);
|
||||||
|
pio_sm_set_enabled(pio, sm, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// meant for sbw_seq/sbw_tms_seq
|
||||||
|
static inline void sbw_pio_set_baudrate(PIO pio, uint sm, float freq) {
|
||||||
|
if (freq < 72e3) freq = 72e3;
|
||||||
|
if (freq > 20e6) freq = 20e6;
|
||||||
|
|
||||||
|
pio_sm_set_clkdiv(pio, sm, (float)clock_get_hz(clk_sys) / (4 * freq));
|
||||||
|
}
|
||||||
|
|
||||||
|
// meant for sbw_tclk_burst
|
||||||
|
static inline void sbw_pio_set_tclkfreq(PIO pio, uint sm, float freq) {
|
||||||
|
if (freq < 250e3) freq = 250e3;
|
||||||
|
if (freq > 450e3) freq = 450e3;
|
||||||
|
|
||||||
|
pio_sm_set_clkdiv(pio, sm, (float)clock_get_hz(clk_sys) / (24 * freq));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t sbw_pio_gen_sety(uint y) {
|
||||||
|
return pio_encode_set(pio_y, y) | pio_encode_sideset(1, 1);
|
||||||
|
}
|
||||||
|
static inline uint16_t sbw_pio_gen_inx(uint bits) {
|
||||||
|
return pio_encode_in(pio_x, bits) | pio_encode_sideset(1, 1);
|
||||||
|
}
|
||||||
|
// subroutine is one of "sbw_offset_sbw_seq", "sbw_offset_sbw_tms_seq", "sbw_offset_sbw_tclk_burst"
|
||||||
|
static inline uint16_t sbw_pio_gen_jmp(uint subroutine) {
|
||||||
|
return pio_encode_jmp(subroutine) | pio_encode_sideset(1, 1);
|
||||||
|
}
|
||||||
|
static inline uint16_t sbw_pio_loadbearing_gen_outpins(void) {
|
||||||
|
return pio_encode_out(pio_pins, 1) | pio_encode_sideset(1, 1) | pio_encode_delay(12);
|
||||||
|
}
|
||||||
|
static inline uint16_t sbw_pio_loadbearing_gen_setpins(uint value) {
|
||||||
|
return pio_encode_set(pio_pins, value) | pio_encode_sideset(1, 1) | pio_encode_delay(12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sbw_pio_loadbearing_set_outpins(PIO pio) {
|
||||||
|
pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] =
|
||||||
|
sbw_pio_loadbearing_gen_outpins();
|
||||||
|
}
|
||||||
|
static inline void sbw_pio_loadbearing_set_setpins(PIO pio, uint value) {
|
||||||
|
pio->instr_mem[sbw_offset_sbw_tclk_burst_loadbearing_insn] =
|
||||||
|
sbw_pio_loadbearing_gen_setpins(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
Loading…
Reference in New Issue