Strip W6300 drivers to W6300-only, remove doxygen, flatten into w6300/
This commit is contained in:
534
w6300/wizchip_qspi_pio.c
Normal file
534
w6300/wizchip_qspi_pio.c
Normal file
@@ -0,0 +1,534 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/error.h"
|
||||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "wizchip_conf.h"
|
||||
#include "wizchip_qspi_pio.h"
|
||||
|
||||
#include "wizchip_qspi_pio.pio.h"
|
||||
|
||||
#ifndef PIO_SPI_PREFERRED_PIO
|
||||
#define PIO_SPI_PREFERRED_PIO 1
|
||||
#endif
|
||||
|
||||
#define PADS_DRIVE_STRENGTH PADS_BANK0_GPIO0_DRIVE_VALUE_12MA
|
||||
#define IRQ_SAMPLE_DELAY_NS 100
|
||||
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
#define PIO_PROGRAM_NAME wizchip_pio_spi_single_write_read
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
#define PIO_PROGRAM_NAME wizchip_pio_spi_dual_write_read
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
#define PIO_PROGRAM_NAME wizchip_pio_spi_quad_write_read
|
||||
#endif
|
||||
|
||||
#define PIO_PROGRAM_FUNC __CONCAT(PIO_PROGRAM_NAME, _program)
|
||||
#define PIO_PROGRAM_GET_DEFAULT_CONFIG_FUNC __CONCAT(PIO_PROGRAM_NAME, _program_get_default_config)
|
||||
#define PIO_OFFSET_WRITE_BITS __CONCAT(PIO_PROGRAM_NAME, _offset_write_bits)
|
||||
#define PIO_OFFSET_WRITE_BITS_END __CONCAT(PIO_PROGRAM_NAME, _offset_write_bits_end)
|
||||
#define PIO_OFFSET_READ_BITS_END __CONCAT(PIO_PROGRAM_NAME, _offset_read_bits_end)
|
||||
|
||||
#ifndef PICO_WIZNET_SPI_PIO_INSTANCE_COUNT
|
||||
#define PICO_WIZNET_SPI_PIO_INSTANCE_COUNT 1
|
||||
#endif
|
||||
|
||||
#define SPI_HEADER_LEN 3
|
||||
|
||||
typedef struct spi_pio_state {
|
||||
wiznet_spi_funcs_t *funcs;
|
||||
const wiznet_spi_config_t *spi_config;
|
||||
pio_hw_t *pio;
|
||||
uint8_t pio_func_sel;
|
||||
int8_t pio_offset;
|
||||
int8_t pio_sm;
|
||||
int8_t dma_out;
|
||||
int8_t dma_in;
|
||||
uint8_t spi_header[SPI_HEADER_LEN];
|
||||
uint8_t spi_header_count;
|
||||
} spi_pio_state_t;
|
||||
|
||||
|
||||
|
||||
static spi_pio_state_t spi_pio_state[PICO_WIZNET_SPI_PIO_INSTANCE_COUNT];
|
||||
static spi_pio_state_t *active_state;
|
||||
|
||||
static void wiznet_spi_pio_close(wiznet_spi_handle_t funcs);
|
||||
static wiznet_spi_funcs_t *get_wiznet_spi_pio_impl(void);
|
||||
|
||||
|
||||
static uint16_t mk_cmd_buf(uint8_t *pdst, uint8_t opcode, uint16_t addr) {
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
|
||||
pdst[0] = opcode;
|
||||
pdst[1] = (uint8_t)((addr >> 8) & 0xFF);
|
||||
pdst[2] = (uint8_t)((addr >> 0) & 0xFF);
|
||||
pdst[3] = 0;
|
||||
|
||||
return 3 + 1;
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
pdst[0] = ((opcode >> 7 & 0x01) << 6) | ((opcode >> 6 & 0x01) << 4) | ((opcode >> 5 & 0x01) << 2) | ((opcode >> 4 & 0x01) << 0);
|
||||
pdst[1] = ((opcode >> 3 & 0x01) << 6) | ((opcode >> 2 & 0x01) << 4) | ((opcode >> 1 & 0x01) << 2) | ((opcode >> 0 & 0x01) << 0);
|
||||
pdst[2] = (uint8_t)((addr >> 8) & 0xFF);
|
||||
pdst[3] = (uint8_t)((addr >> 0) & 0xFF);
|
||||
|
||||
pdst[4] = 0;
|
||||
|
||||
return 4 + 1;
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
pdst[0] = ((opcode >> 7 & 0x01) << 4) | ((opcode >> 6 & 0x01) << 0);
|
||||
pdst[1] = ((opcode >> 5 & 0x01) << 4) | ((opcode >> 4 & 0x01) << 0);
|
||||
pdst[2] = ((opcode >> 3 & 0x01) << 4) | ((opcode >> 2 & 0x01) << 0);
|
||||
pdst[3] = ((opcode >> 1 & 0x01) << 4) | ((opcode >> 0 & 0x01) << 0);
|
||||
|
||||
pdst[4] = ((uint8_t)(addr >> 8) & 0xFF);
|
||||
pdst[5] = ((uint8_t)(addr >> 0) & 0xFF);
|
||||
|
||||
pdst[6] = 0;
|
||||
|
||||
return 6 + 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialise our gpios
|
||||
static void pio_spi_gpio_setup(spi_pio_state_t *state) {
|
||||
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
gpio_init(state->spi_config->data_io0_pin);
|
||||
gpio_init(state->spi_config->data_io1_pin);
|
||||
gpio_set_dir(state->spi_config->data_io0_pin, GPIO_OUT);
|
||||
gpio_set_dir(state->spi_config->data_io1_pin, GPIO_OUT);
|
||||
gpio_put(state->spi_config->data_io0_pin, false);
|
||||
gpio_put(state->spi_config->data_io1_pin, false);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
gpio_init(state->spi_config->data_io0_pin);
|
||||
gpio_init(state->spi_config->data_io1_pin);
|
||||
gpio_set_dir(state->spi_config->data_io0_pin, GPIO_OUT);
|
||||
gpio_set_dir(state->spi_config->data_io1_pin, GPIO_OUT);
|
||||
gpio_put(state->spi_config->data_io0_pin, false);
|
||||
gpio_put(state->spi_config->data_io1_pin, false);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
gpio_init(state->spi_config->data_io0_pin);
|
||||
gpio_init(state->spi_config->data_io1_pin);
|
||||
gpio_init(state->spi_config->data_io2_pin);
|
||||
gpio_init(state->spi_config->data_io3_pin);
|
||||
gpio_set_dir(state->spi_config->data_io0_pin, GPIO_OUT);
|
||||
gpio_set_dir(state->spi_config->data_io1_pin, GPIO_OUT);
|
||||
gpio_set_dir(state->spi_config->data_io2_pin, GPIO_OUT);
|
||||
gpio_set_dir(state->spi_config->data_io3_pin, GPIO_OUT);
|
||||
gpio_put(state->spi_config->data_io0_pin, false);
|
||||
gpio_put(state->spi_config->data_io1_pin, false);
|
||||
gpio_put(state->spi_config->data_io2_pin, false);
|
||||
gpio_put(state->spi_config->data_io3_pin, false);
|
||||
#endif
|
||||
|
||||
gpio_init(state->spi_config->cs_pin);
|
||||
gpio_set_dir(state->spi_config->cs_pin, GPIO_OUT);
|
||||
gpio_put(state->spi_config->cs_pin, true);
|
||||
|
||||
gpio_init(state->spi_config->irq_pin);
|
||||
gpio_set_dir(state->spi_config->irq_pin, GPIO_IN);
|
||||
gpio_set_pulls(state->spi_config->irq_pin, false, false);
|
||||
|
||||
}
|
||||
|
||||
wiznet_spi_handle_t wiznet_spi_pio_open(const wiznet_spi_config_t *spi_config) {
|
||||
|
||||
spi_pio_state_t *state;
|
||||
for (int i = 0; i < count_of(spi_pio_state); i++) {
|
||||
if (!spi_pio_state[i].funcs) {
|
||||
state = &spi_pio_state[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(state);
|
||||
if (!state) {
|
||||
return NULL;
|
||||
}
|
||||
state->spi_config = spi_config;
|
||||
state->funcs = get_wiznet_spi_pio_impl();
|
||||
|
||||
pio_spi_gpio_setup(state);
|
||||
|
||||
pio_hw_t *pios[2] = {pio0, pio1};
|
||||
uint pio_index = PIO_SPI_PREFERRED_PIO;
|
||||
|
||||
if (!pio_can_add_program(pios[pio_index], &PIO_PROGRAM_FUNC)) {
|
||||
pio_index ^= 1;
|
||||
if (!pio_can_add_program(pios[pio_index], &PIO_PROGRAM_FUNC)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
state->pio = pios[pio_index];
|
||||
state->dma_in = -1;
|
||||
state->dma_out = -1;
|
||||
|
||||
static_assert(GPIO_FUNC_PIO1 == GPIO_FUNC_PIO0 + 1, "");
|
||||
state->pio_func_sel = GPIO_FUNC_PIO0 + pio_index;
|
||||
state->pio_sm = (int8_t)pio_claim_unused_sm(state->pio, false);
|
||||
if (state->pio_sm < 0) {
|
||||
wiznet_spi_pio_close(&state->funcs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->pio_offset = pio_add_program(state->pio, &PIO_PROGRAM_FUNC);
|
||||
|
||||
uint64_t f_sys = clock_get_hz(clk_sys); // Hz
|
||||
printf("[PIO QSPI CLOCK SPEED : %.2f MHz] (sys=%.2f MHz)\r\n\r\n",
|
||||
(double)f_sys / (2.0 * (state->spi_config->clock_div_major +
|
||||
state->spi_config->clock_div_minor / 256.0)) / 1e6,
|
||||
f_sys / 1e6);
|
||||
|
||||
pio_sm_config sm_config = PIO_PROGRAM_GET_DEFAULT_CONFIG_FUNC(state->pio_offset);
|
||||
|
||||
sm_config_set_clkdiv_int_frac(&sm_config, state->spi_config->clock_div_major, state->spi_config->clock_div_minor);
|
||||
hw_write_masked(&pads_bank0_hw->io[state->spi_config->clock_pin],
|
||||
(uint)PADS_DRIVE_STRENGTH << PADS_BANK0_GPIO0_DRIVE_LSB,
|
||||
PADS_BANK0_GPIO0_DRIVE_BITS
|
||||
);
|
||||
hw_write_masked(&pads_bank0_hw->io[state->spi_config->clock_pin],
|
||||
(uint)1 << PADS_BANK0_GPIO0_SLEWFAST_LSB,
|
||||
PADS_BANK0_GPIO0_SLEWFAST_BITS
|
||||
);
|
||||
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
sm_config_set_out_pins(&sm_config, state->spi_config->data_io0_pin, 1);
|
||||
sm_config_set_in_pins(&sm_config, state->spi_config->data_io1_pin);
|
||||
sm_config_set_set_pins(&sm_config, state->spi_config->data_io0_pin, 2);
|
||||
sm_config_set_sideset(&sm_config, 1, false, false);
|
||||
sm_config_set_sideset_pins(&sm_config, state->spi_config->clock_pin);
|
||||
|
||||
sm_config_set_in_shift(&sm_config, false, true, 8);
|
||||
sm_config_set_out_shift(&sm_config, false, true, 8);
|
||||
|
||||
hw_set_bits(&state->pio->input_sync_bypass,
|
||||
(1u << state->spi_config->data_io0_pin) | (1u << state->spi_config->data_io1_pin));
|
||||
pio_sm_set_config(state->pio, state->pio_sm, &sm_config);
|
||||
pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->clock_pin, 1, true);
|
||||
|
||||
gpio_set_function(state->spi_config->data_io0_pin, state->pio_func_sel);
|
||||
|
||||
// Set data pin to pull down and schmitt
|
||||
gpio_set_pulls(state->spi_config->data_io0_pin, false, true);
|
||||
gpio_set_pulls(state->spi_config->data_io1_pin, false, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io0_pin, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io1_pin, true);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
sm_config_set_out_pins(&sm_config, state->spi_config->data_io0_pin, 2);
|
||||
sm_config_set_in_pins(&sm_config, state->spi_config->data_io0_pin);
|
||||
sm_config_set_set_pins(&sm_config, state->spi_config->data_io0_pin, 2);
|
||||
sm_config_set_sideset(&sm_config, 1, false, false);
|
||||
sm_config_set_sideset_pins(&sm_config, state->spi_config->clock_pin);
|
||||
|
||||
sm_config_set_in_shift(&sm_config, false, true, 8);
|
||||
sm_config_set_out_shift(&sm_config, false, true, 8);
|
||||
|
||||
hw_set_bits(&state->pio->input_sync_bypass,
|
||||
(1u << state->spi_config->data_io0_pin) | (1u << state->spi_config->data_io1_pin));
|
||||
pio_sm_set_config(state->pio, state->pio_sm, &sm_config);
|
||||
pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->clock_pin, 1, true);
|
||||
|
||||
gpio_set_function(state->spi_config->data_io0_pin, state->pio_func_sel);
|
||||
gpio_set_function(state->spi_config->data_io1_pin, state->pio_func_sel);
|
||||
|
||||
// Set data pin to pull down and schmitt
|
||||
gpio_set_pulls(state->spi_config->data_io0_pin, false, true);
|
||||
gpio_set_pulls(state->spi_config->data_io1_pin, false, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io0_pin, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io1_pin, true);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
sm_config_set_out_pins(&sm_config, state->spi_config->data_io0_pin, 4);
|
||||
sm_config_set_in_pins(&sm_config, state->spi_config->data_io0_pin);
|
||||
sm_config_set_set_pins(&sm_config, state->spi_config->data_io0_pin, 4);
|
||||
sm_config_set_sideset(&sm_config, 1, false, false);
|
||||
sm_config_set_sideset_pins(&sm_config, state->spi_config->clock_pin);
|
||||
|
||||
sm_config_set_in_shift(&sm_config, false, true, 8);
|
||||
sm_config_set_out_shift(&sm_config, false, true, 8);
|
||||
|
||||
hw_set_bits(&state->pio->input_sync_bypass,
|
||||
(1u << state->spi_config->data_io0_pin) | (1u << state->spi_config->data_io1_pin) | (1u << state->spi_config->data_io2_pin) | (1u << state->spi_config->data_io3_pin));
|
||||
pio_sm_set_config(state->pio, state->pio_sm, &sm_config);
|
||||
pio_sm_set_consecutive_pindirs(state->pio, state->pio_sm, state->spi_config->clock_pin, 1, true);
|
||||
|
||||
gpio_set_function(state->spi_config->data_io0_pin, state->pio_func_sel);
|
||||
gpio_set_function(state->spi_config->data_io1_pin, state->pio_func_sel);
|
||||
gpio_set_function(state->spi_config->data_io2_pin, state->pio_func_sel);
|
||||
gpio_set_function(state->spi_config->data_io3_pin, state->pio_func_sel);
|
||||
|
||||
// Set data pin to pull down and schmitt
|
||||
gpio_set_pulls(state->spi_config->data_io0_pin, false, true);
|
||||
gpio_set_pulls(state->spi_config->data_io1_pin, false, true);
|
||||
gpio_set_pulls(state->spi_config->data_io2_pin, false, true);
|
||||
gpio_set_pulls(state->spi_config->data_io3_pin, false, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io0_pin, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io1_pin, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io2_pin, true);
|
||||
gpio_set_input_hysteresis_enabled(state->spi_config->data_io3_pin, true);
|
||||
#endif
|
||||
|
||||
pio_sm_exec(state->pio, state->pio_sm, pio_encode_set(pio_pins, 1));
|
||||
|
||||
state->dma_out = (int8_t)dma_claim_unused_channel(false); // todo: Should be able to use one dma channel?
|
||||
state->dma_in = (int8_t)dma_claim_unused_channel(false);
|
||||
if (state->dma_out < 0 || state->dma_in < 0) {
|
||||
wiznet_spi_pio_close(&state->funcs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &state->funcs;
|
||||
|
||||
}
|
||||
|
||||
static void wiznet_spi_pio_close(wiznet_spi_handle_t handle) {
|
||||
|
||||
spi_pio_state_t *state = (spi_pio_state_t *)handle;
|
||||
if (state) {
|
||||
if (state->pio_sm >= 0) {
|
||||
if (state->pio_offset != -1) {
|
||||
pio_remove_program(state->pio, &PIO_PROGRAM_FUNC, state->pio_offset);
|
||||
}
|
||||
|
||||
pio_sm_unclaim(state->pio, state->pio_sm);
|
||||
}
|
||||
if (state->dma_out >= 0) {
|
||||
dma_channel_unclaim(state->dma_out);
|
||||
state->dma_out = -1;
|
||||
}
|
||||
if (state->dma_in >= 0) {
|
||||
dma_channel_unclaim(state->dma_in);
|
||||
state->dma_in = -1;
|
||||
}
|
||||
state->funcs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cs_set(spi_pio_state_t *state, bool value) {
|
||||
gpio_put(state->spi_config->cs_pin, value);
|
||||
}
|
||||
|
||||
static __noinline void ns_delay(uint32_t ns) {
|
||||
// cycles = ns * clk_sys_hz / 1,000,000,000
|
||||
uint32_t cycles = ns * (clock_get_hz(clk_sys) >> 16u) / (1000000000u >> 16u);
|
||||
busy_wait_at_least_cycles(cycles);
|
||||
}
|
||||
|
||||
static void wiznet_spi_pio_frame_start(void) {
|
||||
assert(active_state);
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
gpio_set_function(active_state->spi_config->data_io0_pin, active_state->pio_func_sel);
|
||||
gpio_set_function(active_state->spi_config->data_io1_pin, active_state->pio_func_sel);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
gpio_set_function(active_state->spi_config->data_io0_pin, active_state->pio_func_sel);
|
||||
gpio_set_function(active_state->spi_config->data_io1_pin, active_state->pio_func_sel);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
gpio_set_function(active_state->spi_config->data_io0_pin, active_state->pio_func_sel);
|
||||
gpio_set_function(active_state->spi_config->data_io1_pin, active_state->pio_func_sel);
|
||||
gpio_set_function(active_state->spi_config->data_io2_pin, active_state->pio_func_sel);
|
||||
gpio_set_function(active_state->spi_config->data_io3_pin, active_state->pio_func_sel);
|
||||
#endif
|
||||
gpio_set_function(active_state->spi_config->clock_pin, active_state->pio_func_sel);
|
||||
gpio_pull_down(active_state->spi_config->clock_pin);
|
||||
// Pull CS low
|
||||
cs_set(active_state, false);
|
||||
}
|
||||
|
||||
static void wiznet_spi_pio_frame_end(void) {
|
||||
assert(active_state);
|
||||
// from this point a positive edge will cause an IRQ to be pending
|
||||
cs_set(active_state, true);
|
||||
// we need to wait a bit in case the irq line is incorrectly high
|
||||
#ifdef IRQ_SAMPLE_DELAY_NS
|
||||
ns_delay(IRQ_SAMPLE_DELAY_NS);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wiznet_spi_pio_read_byte(uint8_t op_code, uint16_t AddrSel, uint8_t *rx, uint16_t rx_length) {
|
||||
uint8_t command_buf[8] = {0,};
|
||||
uint16_t command_len = mk_cmd_buf(command_buf, op_code, AddrSel);
|
||||
uint32_t loop_cnt = 0;
|
||||
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, false);
|
||||
pio_sm_set_wrap(active_state->pio, active_state->pio_sm, active_state->pio_offset, active_state->pio_offset + PIO_OFFSET_READ_BITS_END - 1);
|
||||
//pio_sm_set_wrap(active_state->pio, active_state->pio_sm, active_state->pio_offset + PIO_SPI_OFFSET_WRITE_BITS, active_state->pio_offset + PIO_SPI_OFFSET_READ_BITS_END - 1);
|
||||
pio_sm_clear_fifos(active_state->pio, active_state->pio_sm);
|
||||
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
loop_cnt = 8;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin), (1u << active_state->spi_config->data_io0_pin));// | (1u << active_state->spi_config->data_io1_pin));
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
loop_cnt = 4;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin),
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin));
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
loop_cnt = 2;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin) | (1u << active_state->spi_config->data_io2_pin) | (1u << active_state->spi_config->data_io3_pin),
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin) | (1u << active_state->spi_config->data_io2_pin) | (1u << active_state->spi_config->data_io3_pin));
|
||||
|
||||
/* @todo: Implement to use. */
|
||||
#endif
|
||||
|
||||
pio_sm_restart(active_state->pio, active_state->pio_sm);
|
||||
pio_sm_clkdiv_restart(active_state->pio, active_state->pio_sm);
|
||||
|
||||
pio_sm_put(active_state->pio, active_state->pio_sm, command_len * loop_cnt - 1);
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_out(pio_x, 32));
|
||||
|
||||
pio_sm_put(active_state->pio, active_state->pio_sm, rx_length - 1);
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_out(pio_y, 32));
|
||||
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_jmp(active_state->pio_offset));
|
||||
|
||||
dma_channel_abort(active_state->dma_out);
|
||||
dma_channel_abort(active_state->dma_in);
|
||||
|
||||
dma_channel_config out_config = dma_channel_get_default_config(active_state->dma_out);
|
||||
channel_config_set_transfer_data_size(&out_config, DMA_SIZE_8);
|
||||
channel_config_set_bswap(&out_config, true);
|
||||
channel_config_set_dreq(&out_config, pio_get_dreq(active_state->pio, active_state->pio_sm, true));
|
||||
dma_channel_configure(active_state->dma_out, &out_config, &active_state->pio->txf[active_state->pio_sm], command_buf, command_len, true);
|
||||
|
||||
dma_channel_config in_config = dma_channel_get_default_config(active_state->dma_in);
|
||||
channel_config_set_transfer_data_size(&in_config, DMA_SIZE_8);
|
||||
channel_config_set_bswap(&in_config, true);
|
||||
channel_config_set_dreq(&in_config, pio_get_dreq(active_state->pio, active_state->pio_sm, false));
|
||||
channel_config_set_write_increment(&in_config, true);
|
||||
channel_config_set_read_increment(&in_config, false);
|
||||
dma_channel_configure(active_state->dma_in, &in_config, rx, &active_state->pio->rxf[active_state->pio_sm], rx_length, true);
|
||||
|
||||
#if 1
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, true);
|
||||
|
||||
__compiler_memory_barrier();
|
||||
|
||||
dma_channel_wait_for_finish_blocking(active_state->dma_out);
|
||||
dma_channel_wait_for_finish_blocking(active_state->dma_in);
|
||||
|
||||
__compiler_memory_barrier();
|
||||
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, false);
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_mov(pio_pins, pio_null));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void wiznet_spi_pio_write_byte(uint8_t op_code, uint16_t AddrSel, uint8_t *tx, uint16_t tx_length) {
|
||||
uint8_t command_buf[8] = {0,};
|
||||
uint16_t command_len = mk_cmd_buf(command_buf, op_code, AddrSel);
|
||||
uint32_t loop_cnt = 0;
|
||||
tx_length = tx_length + command_len;
|
||||
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, false);
|
||||
pio_sm_set_wrap(active_state->pio, active_state->pio_sm, active_state->pio_offset, active_state->pio_offset + PIO_OFFSET_WRITE_BITS_END - 1);
|
||||
pio_sm_clear_fifos(active_state->pio, active_state->pio_sm);
|
||||
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
loop_cnt = 8;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin), (1u << active_state->spi_config->data_io0_pin));
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
loop_cnt = 4;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin),
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin));
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
loop_cnt = 2;
|
||||
pio_sm_set_pindirs_with_mask(active_state->pio,
|
||||
active_state->pio_sm,
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin) | (1u << active_state->spi_config->data_io2_pin) | (1u << active_state->spi_config->data_io3_pin),
|
||||
(1u << active_state->spi_config->data_io0_pin) | (1u << active_state->spi_config->data_io1_pin) | (1u << active_state->spi_config->data_io2_pin) | (1u << active_state->spi_config->data_io3_pin));
|
||||
|
||||
#endif
|
||||
|
||||
pio_sm_restart(active_state->pio, active_state->pio_sm);
|
||||
pio_sm_clkdiv_restart(active_state->pio, active_state->pio_sm);
|
||||
pio_sm_put(active_state->pio, active_state->pio_sm, tx_length * loop_cnt - 1);
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_out(pio_x, 32));
|
||||
pio_sm_put(active_state->pio, active_state->pio_sm, 0);
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_out(pio_y, 32));
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_jmp(active_state->pio_offset));
|
||||
dma_channel_abort(active_state->dma_out);
|
||||
|
||||
|
||||
dma_channel_config out_config = dma_channel_get_default_config(active_state->dma_out);
|
||||
channel_config_set_transfer_data_size(&out_config, DMA_SIZE_8);
|
||||
channel_config_set_bswap(&out_config, true);
|
||||
channel_config_set_dreq(&out_config, pio_get_dreq(active_state->pio, active_state->pio_sm, true));
|
||||
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, true);
|
||||
|
||||
dma_channel_configure(active_state->dma_out, &out_config, &active_state->pio->txf[active_state->pio_sm], command_buf, command_len, true);
|
||||
dma_channel_wait_for_finish_blocking(active_state->dma_out);
|
||||
dma_channel_configure(active_state->dma_out, &out_config, &active_state->pio->txf[active_state->pio_sm], tx, tx_length - command_len, true);
|
||||
dma_channel_wait_for_finish_blocking(active_state->dma_out);
|
||||
|
||||
const uint32_t fdebug_tx_stall = 1u << (PIO_FDEBUG_TXSTALL_LSB + active_state->pio_sm);
|
||||
active_state->pio->fdebug = fdebug_tx_stall;
|
||||
// pio_sm_set_enabled(active_state->pio, active_state->pio_sm, true);
|
||||
while (!(active_state->pio->fdebug & fdebug_tx_stall)) {
|
||||
tight_loop_contents(); // todo timeout
|
||||
}
|
||||
#if 1
|
||||
|
||||
__compiler_memory_barrier();
|
||||
//pio_sm_set_enabled(active_state->pio, active_state->pio_sm, false);
|
||||
#if (_WIZCHIP_QSPI_MODE_ == QSPI_SINGLE_MODE)
|
||||
pio_sm_set_consecutive_pindirs(active_state->pio, active_state->pio_sm, active_state->spi_config->data_io0_pin, 1, false);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_DUAL_MODE)
|
||||
pio_sm_set_consecutive_pindirs(active_state->pio, active_state->pio_sm, active_state->spi_config->data_io0_pin, 2, false);
|
||||
#elif (_WIZCHIP_QSPI_MODE_ == QSPI_QUAD_MODE)
|
||||
pio_sm_set_consecutive_pindirs(active_state->pio, active_state->pio_sm, active_state->spi_config->data_io0_pin, 4, false);
|
||||
#endif
|
||||
|
||||
pio_sm_exec(active_state->pio, active_state->pio_sm, pio_encode_mov(pio_pins, pio_null));
|
||||
pio_sm_set_enabled(active_state->pio, active_state->pio_sm, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void wiznet_spi_pio_set_active(wiznet_spi_handle_t handle) {
|
||||
active_state = (spi_pio_state_t *)handle;
|
||||
}
|
||||
|
||||
static void wiznet_spi_pio_set_inactive(void) {
|
||||
active_state = NULL;
|
||||
}
|
||||
|
||||
static void wizchip_spi_pio_reset(wiznet_spi_handle_t handle) {
|
||||
|
||||
spi_pio_state_t *state = (spi_pio_state_t *)handle;
|
||||
gpio_set_dir(state->spi_config->reset_pin, GPIO_OUT);
|
||||
gpio_put(state->spi_config->reset_pin, 0);
|
||||
sleep_ms(100);
|
||||
gpio_put(state->spi_config->reset_pin, 1);
|
||||
sleep_ms(100);
|
||||
|
||||
}
|
||||
|
||||
static wiznet_spi_funcs_t *get_wiznet_spi_pio_impl(void) {
|
||||
static wiznet_spi_funcs_t funcs = {
|
||||
.close = wiznet_spi_pio_close,
|
||||
.set_active = wiznet_spi_pio_set_active,
|
||||
.set_inactive = wiznet_spi_pio_set_inactive,
|
||||
.frame_start = wiznet_spi_pio_frame_start,
|
||||
.frame_end = wiznet_spi_pio_frame_end,
|
||||
.read_byte = wiznet_spi_pio_read_byte,
|
||||
.write_byte = wiznet_spi_pio_write_byte,
|
||||
.reset = wizchip_spi_pio_reset,
|
||||
};
|
||||
return &funcs;
|
||||
}
|
||||
Reference in New Issue
Block a user