mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-02-16 20:29:12 +01:00
reset improvement
This commit is contained in:
parent
f669f730da
commit
6d460e83bd
@ -394,13 +394,13 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_USB_SCR: begin
|
REG_USB_SCR: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= {
|
||||||
2'd0,
|
1'd0,
|
||||||
|
usb_scb.fifo_flush_busy,
|
||||||
usb_scb.pwrsav,
|
usb_scb.pwrsav,
|
||||||
usb_scb.reset_state,
|
usb_scb.reset_state,
|
||||||
usb_scb.tx_count,
|
usb_scb.tx_count,
|
||||||
usb_scb.rx_count,
|
usb_scb.rx_count,
|
||||||
2'b00,
|
3'b000,
|
||||||
usb_scb.reset_pending,
|
|
||||||
~fifo_bus.tx_full,
|
~fifo_bus.tx_full,
|
||||||
~fifo_bus.rx_empty,
|
~fifo_bus.rx_empty,
|
||||||
1'b0
|
1'b0
|
||||||
@ -681,9 +681,10 @@ module mcu_top (
|
|||||||
mem_start <= 1'b0;
|
mem_start <= 1'b0;
|
||||||
mem_stop <= 1'b0;
|
mem_stop <= 1'b0;
|
||||||
|
|
||||||
usb_scb.write_buffer_flush <= 1'b0;
|
|
||||||
usb_scb.reset_ack <= 1'b0;
|
|
||||||
usb_scb.fifo_flush <= 1'b0;
|
usb_scb.fifo_flush <= 1'b0;
|
||||||
|
usb_scb.write_buffer_flush <= 1'b0;
|
||||||
|
usb_scb.reset_on_ack <= 1'b0;
|
||||||
|
usb_scb.reset_off_ack <= 1'b0;
|
||||||
|
|
||||||
usb_dma_scb.start <= 1'b0;
|
usb_dma_scb.start <= 1'b0;
|
||||||
usb_dma_scb.stop <= 1'b0;
|
usb_dma_scb.stop <= 1'b0;
|
||||||
@ -770,11 +771,10 @@ module mcu_top (
|
|||||||
end
|
end
|
||||||
|
|
||||||
REG_USB_SCR: begin
|
REG_USB_SCR: begin
|
||||||
{
|
usb_scb.write_buffer_flush <= reg_wdata[5];
|
||||||
usb_scb.write_buffer_flush,
|
usb_scb.reset_off_ack <= reg_wdata[4];
|
||||||
usb_scb.reset_ack,
|
usb_scb.reset_on_ack <= reg_wdata[3];
|
||||||
usb_scb.fifo_flush
|
usb_scb.fifo_flush <= reg_wdata[0];
|
||||||
} <= {reg_wdata[5:4], reg_wdata[0]};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_USB_DMA_ADDRESS: begin
|
REG_USB_DMA_ADDRESS: begin
|
||||||
|
@ -1,34 +1,37 @@
|
|||||||
interface usb_scb ();
|
interface usb_scb ();
|
||||||
|
|
||||||
logic fifo_flush;
|
logic fifo_flush;
|
||||||
logic reset_pending;
|
logic fifo_flush_busy;
|
||||||
logic reset_ack;
|
|
||||||
logic write_buffer_flush;
|
logic write_buffer_flush;
|
||||||
logic [10:0] rx_count;
|
logic [10:0] rx_count;
|
||||||
logic [10:0] tx_count;
|
logic [10:0] tx_count;
|
||||||
logic pwrsav;
|
logic pwrsav;
|
||||||
logic reset_state;
|
logic reset_state;
|
||||||
|
logic reset_on_ack;
|
||||||
|
logic reset_off_ack;
|
||||||
|
|
||||||
modport controller (
|
modport controller (
|
||||||
output fifo_flush,
|
output fifo_flush,
|
||||||
input reset_pending,
|
input fifo_flush_busy,
|
||||||
output reset_ack,
|
|
||||||
output write_buffer_flush,
|
output write_buffer_flush,
|
||||||
input rx_count,
|
input rx_count,
|
||||||
input tx_count,
|
input tx_count,
|
||||||
input pwrsav,
|
input pwrsav,
|
||||||
input reset_state
|
input reset_state,
|
||||||
|
output reset_on_ack,
|
||||||
|
output reset_off_ack
|
||||||
);
|
);
|
||||||
|
|
||||||
modport usb (
|
modport usb (
|
||||||
input fifo_flush,
|
input fifo_flush,
|
||||||
output reset_pending,
|
output fifo_flush_busy,
|
||||||
input reset_ack,
|
|
||||||
input write_buffer_flush,
|
input write_buffer_flush,
|
||||||
output rx_count,
|
output rx_count,
|
||||||
output tx_count,
|
output tx_count,
|
||||||
output pwrsav,
|
output pwrsav,
|
||||||
output reset_state
|
output reset_state,
|
||||||
|
input reset_on_ack,
|
||||||
|
input reset_off_ack
|
||||||
);
|
);
|
||||||
|
|
||||||
endinterface
|
endinterface
|
||||||
@ -59,9 +62,11 @@ module usb_ft1248 (
|
|||||||
logic tx_read;
|
logic tx_read;
|
||||||
logic [7:0] tx_rdata;
|
logic [7:0] tx_rdata;
|
||||||
|
|
||||||
|
logic fifo_flush;
|
||||||
|
|
||||||
fifo_8kb fifo_8kb_rx_inst (
|
fifo_8kb fifo_8kb_rx_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset(reset || usb_scb.fifo_flush),
|
.reset(reset || fifo_flush),
|
||||||
|
|
||||||
.empty(fifo_bus.rx_empty),
|
.empty(fifo_bus.rx_empty),
|
||||||
.almost_empty(fifo_bus.rx_almost_empty),
|
.almost_empty(fifo_bus.rx_almost_empty),
|
||||||
@ -78,7 +83,7 @@ module usb_ft1248 (
|
|||||||
|
|
||||||
fifo_8kb fifo_8kb_tx_inst (
|
fifo_8kb fifo_8kb_tx_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset(reset || usb_scb.fifo_flush),
|
.reset(reset || fifo_flush),
|
||||||
|
|
||||||
.empty(tx_empty),
|
.empty(tx_empty),
|
||||||
.almost_empty(tx_almost_empty),
|
.almost_empty(tx_almost_empty),
|
||||||
@ -142,7 +147,6 @@ module usb_ft1248 (
|
|||||||
logic [3:0] phase;
|
logic [3:0] phase;
|
||||||
logic last_tx_failed;
|
logic last_tx_failed;
|
||||||
logic reset_reply;
|
logic reset_reply;
|
||||||
logic last_reset_status;
|
|
||||||
logic [4:0] modem_status_counter;
|
logic [4:0] modem_status_counter;
|
||||||
logic write_modem_status_pending;
|
logic write_modem_status_pending;
|
||||||
logic write_buffer_flush_pending;
|
logic write_buffer_flush_pending;
|
||||||
@ -152,7 +156,7 @@ module usb_ft1248 (
|
|||||||
cmd <= next_cmd;
|
cmd <= next_cmd;
|
||||||
|
|
||||||
usb_scb.pwrsav <= !ft_pwrsav;
|
usb_scb.pwrsav <= !ft_pwrsav;
|
||||||
usb_scb.reset_state <= last_reset_status;
|
fifo_flush <= 1'b0;
|
||||||
|
|
||||||
phase <= {phase[2:0], phase[3]};
|
phase <= {phase[2:0], phase[3]};
|
||||||
if (state == STATE_IDLE) begin
|
if (state == STATE_IDLE) begin
|
||||||
@ -160,25 +164,38 @@ module usb_ft1248 (
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
|
usb_scb.fifo_flush_busy <= 1'b0;
|
||||||
|
usb_scb.reset_state <= 1'b0;
|
||||||
last_tx_failed <= 1'b0;
|
last_tx_failed <= 1'b0;
|
||||||
usb_scb.reset_pending <= 1'b0;
|
reset_reply <= 1'b0;
|
||||||
last_reset_status <= 1'b0;
|
|
||||||
modem_status_counter <= 5'd0;
|
modem_status_counter <= 5'd0;
|
||||||
write_modem_status_pending <= 1'b0;
|
write_modem_status_pending <= 1'b1;
|
||||||
write_buffer_flush_pending <= 1'b0;
|
write_buffer_flush_pending <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (usb_scb.reset_ack) begin
|
if (usb_scb.fifo_flush) begin
|
||||||
usb_scb.reset_pending <= 1'b0;
|
usb_scb.fifo_flush_busy <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (usb_scb.reset_on_ack) begin
|
||||||
reset_reply <= 1'b1;
|
reset_reply <= 1'b1;
|
||||||
write_modem_status_pending <= 1'b1;
|
write_modem_status_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (usb_scb.reset_off_ack) begin
|
||||||
|
reset_reply <= 1'b0;
|
||||||
|
write_modem_status_pending <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
if (usb_scb.write_buffer_flush) begin
|
if (usb_scb.write_buffer_flush) begin
|
||||||
write_buffer_flush_pending <= 1'b1;
|
write_buffer_flush_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (state == STATE_IDLE) begin
|
if (state == STATE_IDLE) begin
|
||||||
modem_status_counter <= modem_status_counter + 1'd1;
|
modem_status_counter <= modem_status_counter + 1'd1;
|
||||||
|
if (usb_scb.fifo_flush_busy) begin
|
||||||
|
usb_scb.fifo_flush_busy <= 1'b0;
|
||||||
|
fifo_flush <= 1'b1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
|
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
|
||||||
@ -187,14 +204,7 @@ module usb_ft1248 (
|
|||||||
|
|
||||||
if (!ft_miso && (state == STATE_DATA) && phase[3]) begin
|
if (!ft_miso && (state == STATE_DATA) && phase[3]) begin
|
||||||
if (cmd == CMD_READ_MODEM_STATUS) begin
|
if (cmd == CMD_READ_MODEM_STATUS) begin
|
||||||
last_reset_status <= ft_miosi_in[0];
|
usb_scb.reset_state <= ft_miosi_in[0];
|
||||||
if (!last_reset_status && ft_miosi_in[0]) begin
|
|
||||||
usb_scb.reset_pending <= 1'b1;
|
|
||||||
end
|
|
||||||
if (last_reset_status && !ft_miosi_in[0]) begin
|
|
||||||
reset_reply <= 1'b0;
|
|
||||||
write_modem_status_pending <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if (cmd == CMD_WRITE_MODEM_STATUS) begin
|
if (cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||||
write_modem_status_pending <= 1'b0;
|
write_modem_status_pending <= 1'b0;
|
||||||
@ -283,7 +293,7 @@ module usb_ft1248 (
|
|||||||
end else begin
|
end else begin
|
||||||
case (state)
|
case (state)
|
||||||
STATE_IDLE: begin
|
STATE_IDLE: begin
|
||||||
if (ft_pwrsav) begin
|
if (ft_pwrsav && !(usb_scb.fifo_flush || usb_scb.fifo_flush_busy || fifo_flush)) begin
|
||||||
if (write_modem_status_pending) begin
|
if (write_modem_status_pending) begin
|
||||||
next_state = STATE_SELECT;
|
next_state = STATE_SELECT;
|
||||||
next_cmd = CMD_WRITE_MODEM_STATUS;
|
next_cmd = CMD_WRITE_MODEM_STATUS;
|
||||||
|
@ -79,8 +79,8 @@ typedef enum {
|
|||||||
#define USB_SCR_FIFO_FLUSH (1 << 0)
|
#define USB_SCR_FIFO_FLUSH (1 << 0)
|
||||||
#define USB_SCR_RXNE (1 << 1)
|
#define USB_SCR_RXNE (1 << 1)
|
||||||
#define USB_SCR_TXE (1 << 2)
|
#define USB_SCR_TXE (1 << 2)
|
||||||
#define USB_SCR_RESET_PENDING (1 << 3)
|
#define USB_SCR_RESET_ON_ACK (1 << 3)
|
||||||
#define USB_SCR_RESET_ACK (1 << 4)
|
#define USB_SCR_RESET_OFF_ACK (1 << 4)
|
||||||
#define USB_SCR_WRITE_FLUSH (1 << 5)
|
#define USB_SCR_WRITE_FLUSH (1 << 5)
|
||||||
#define USB_SCR_RX_COUNT_BIT (6)
|
#define USB_SCR_RX_COUNT_BIT (6)
|
||||||
#define USB_SCR_RX_COUNT_MASK (0x7FF << USB_SCR_RX_COUNT_BIT)
|
#define USB_SCR_RX_COUNT_MASK (0x7FF << USB_SCR_RX_COUNT_BIT)
|
||||||
@ -88,6 +88,7 @@ typedef enum {
|
|||||||
#define USB_SCR_TX_COUNT_MASK (0x7FF << USB_SCR_TX_COUNT_BIT)
|
#define USB_SCR_TX_COUNT_MASK (0x7FF << USB_SCR_TX_COUNT_BIT)
|
||||||
#define USB_SCR_RESET_STATE (1 << 28)
|
#define USB_SCR_RESET_STATE (1 << 28)
|
||||||
#define USB_SCR_PWRSAV (1 << 29)
|
#define USB_SCR_PWRSAV (1 << 29)
|
||||||
|
#define USB_SCR_FIFO_FLUSH_BUSY (1 << 30)
|
||||||
|
|
||||||
#define DMA_SCR_START (1 << 0)
|
#define DMA_SCR_START (1 << 0)
|
||||||
#define DMA_SCR_STOP (1 << 1)
|
#define DMA_SCR_STOP (1 << 1)
|
||||||
|
@ -43,6 +43,8 @@ enum tx_state {
|
|||||||
|
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
|
bool last_reset_state;
|
||||||
|
|
||||||
enum rx_state rx_state;
|
enum rx_state rx_state;
|
||||||
uint8_t rx_counter;
|
uint8_t rx_counter;
|
||||||
uint8_t rx_cmd;
|
uint8_t rx_cmd;
|
||||||
@ -80,10 +82,6 @@ static const uint32_t ERR_TOKEN = (0x45525200UL);
|
|||||||
static const uint32_t PKT_TOKEN = (0x504B5400UL);
|
static const uint32_t PKT_TOKEN = (0x504B5400UL);
|
||||||
|
|
||||||
|
|
||||||
static bool usb_dma_ready (void) {
|
|
||||||
return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool usb_rx_byte (uint8_t *data) {
|
static bool usb_rx_byte (uint8_t *data) {
|
||||||
if (fpga_usb_status_get() & USB_STATUS_RXNE) {
|
if (fpga_usb_status_get() & USB_STATUS_RXNE) {
|
||||||
*data = fpga_usb_pop();
|
*data = fpga_usb_pop();
|
||||||
@ -149,6 +147,59 @@ static bool usb_rx_cmd (uint8_t *cmd) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void usb_reset (void) {
|
||||||
|
fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP);
|
||||||
|
while (fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY);
|
||||||
|
fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH);
|
||||||
|
while (fpga_reg_get(REG_USB_SCR) & USB_SCR_FIFO_FLUSH_BUSY);
|
||||||
|
|
||||||
|
p.rx_state = RX_STATE_IDLE;
|
||||||
|
p.tx_state = TX_STATE_IDLE;
|
||||||
|
|
||||||
|
p.response_pending = false;
|
||||||
|
p.packet_pending = false;
|
||||||
|
|
||||||
|
p.read_ready = true;
|
||||||
|
p.read_length = 0;
|
||||||
|
p.read_address = 0;
|
||||||
|
|
||||||
|
usb_rx_word_counter = 0;
|
||||||
|
usb_rx_word_buffer = 0;
|
||||||
|
usb_tx_word_counter = 0;
|
||||||
|
usb_rx_cmd_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_flush_packet (void) {
|
||||||
|
if (p.packet_pending && p.packet_info.done_callback) {
|
||||||
|
p.packet_pending = false;
|
||||||
|
p.packet_info.done_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) {
|
||||||
|
p.tx_info.done_callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool usb_is_active (void) {
|
||||||
|
uint32_t scr = fpga_reg_get(REG_USB_SCR);
|
||||||
|
bool reset_state = (scr & USB_SCR_RESET_STATE);
|
||||||
|
if (p.last_reset_state != reset_state) {
|
||||||
|
p.last_reset_state = reset_state;
|
||||||
|
if (reset_state) {
|
||||||
|
usb_flush_packet();
|
||||||
|
usb_reset();
|
||||||
|
fpga_reg_set(REG_USB_SCR, USB_SCR_WRITE_FLUSH);
|
||||||
|
}
|
||||||
|
fpga_reg_set(REG_USB_SCR, reset_state ? USB_SCR_RESET_ON_ACK : USB_SCR_RESET_OFF_ACK);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !(reset_state || (scr & USB_SCR_PWRSAV));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool usb_dma_ready (void) {
|
||||||
|
return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY));
|
||||||
|
}
|
||||||
|
|
||||||
static bool usb_validate_address_length (uint32_t address, uint32_t length, bool exclude_bootloader) {
|
static bool usb_validate_address_length (uint32_t address, uint32_t length, bool exclude_bootloader) {
|
||||||
if ((address >= MEMORY_LENGTH) || (length > MEMORY_LENGTH)) {
|
if ((address >= MEMORY_LENGTH) || (length > MEMORY_LENGTH)) {
|
||||||
return true;
|
return true;
|
||||||
@ -556,42 +607,16 @@ void usb_get_read_info (uint32_t *args) {
|
|||||||
|
|
||||||
|
|
||||||
void usb_init (void) {
|
void usb_init (void) {
|
||||||
fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP);
|
p.last_reset_state = false;
|
||||||
fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH);
|
usb_reset();
|
||||||
|
|
||||||
p.rx_state = RX_STATE_IDLE;
|
|
||||||
p.tx_state = TX_STATE_IDLE;
|
|
||||||
|
|
||||||
p.response_pending = false;
|
|
||||||
p.packet_pending = false;
|
|
||||||
|
|
||||||
p.read_ready = true;
|
|
||||||
p.read_length = 0;
|
|
||||||
p.read_address = 0;
|
|
||||||
|
|
||||||
usb_rx_word_counter = 0;
|
|
||||||
usb_rx_word_buffer = 0;
|
|
||||||
usb_tx_word_counter = 0;
|
|
||||||
usb_rx_cmd_counter = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void usb_process (void) {
|
void usb_process (void) {
|
||||||
uint32_t scr = fpga_reg_get(REG_USB_SCR);
|
if (usb_is_active()) {
|
||||||
if (scr & (USB_SCR_PWRSAV | USB_SCR_RESET_STATE | USB_SCR_RESET_PENDING)) {
|
|
||||||
if (p.packet_pending && p.packet_info.done_callback) {
|
|
||||||
p.packet_pending = false;
|
|
||||||
p.packet_info.done_callback();
|
|
||||||
}
|
|
||||||
if (scr & USB_SCR_RESET_PENDING) {
|
|
||||||
if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) {
|
|
||||||
p.tx_info.done_callback();
|
|
||||||
}
|
|
||||||
usb_init();
|
|
||||||
fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
usb_rx_process();
|
usb_rx_process();
|
||||||
usb_tx_process();
|
usb_tx_process();
|
||||||
|
} else {
|
||||||
|
usb_flush_packet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ struct Wrapper {
|
|||||||
context: *mut libftdi1_sys::ftdi_context,
|
context: *mut libftdi1_sys::ftdi_context,
|
||||||
unclog_buffer: std::collections::VecDeque<u8>,
|
unclog_buffer: std::collections::VecDeque<u8>,
|
||||||
write_buffer: Vec<u8>,
|
write_buffer: Vec<u8>,
|
||||||
|
read_timeout: std::time::Duration,
|
||||||
write_timeout: std::time::Duration,
|
write_timeout: std::time::Duration,
|
||||||
read_chunksize: usize,
|
read_chunksize: usize,
|
||||||
write_chunksize: usize,
|
write_chunksize: usize,
|
||||||
@ -49,6 +50,7 @@ impl Wrapper {
|
|||||||
context,
|
context,
|
||||||
unclog_buffer: std::collections::VecDeque::new(),
|
unclog_buffer: std::collections::VecDeque::new(),
|
||||||
write_buffer: vec![],
|
write_buffer: vec![],
|
||||||
|
read_timeout: Wrapper::DEFAULT_RW_TIMEOUT,
|
||||||
write_timeout: Wrapper::DEFAULT_RW_TIMEOUT,
|
write_timeout: Wrapper::DEFAULT_RW_TIMEOUT,
|
||||||
read_chunksize: Wrapper::DEFAULT_CHUNKSIZE,
|
read_chunksize: Wrapper::DEFAULT_CHUNKSIZE,
|
||||||
write_chunksize: Wrapper::DEFAULT_CHUNKSIZE,
|
write_chunksize: Wrapper::DEFAULT_CHUNKSIZE,
|
||||||
@ -158,6 +160,7 @@ impl Wrapper {
|
|||||||
(*self.context).usb_write_timeout = i32::try_from(write_timeout.as_millis())
|
(*self.context).usb_write_timeout = i32::try_from(write_timeout.as_millis())
|
||||||
.map_err(|_| std::io::ErrorKind::InvalidInput)?;
|
.map_err(|_| std::io::ErrorKind::InvalidInput)?;
|
||||||
}
|
}
|
||||||
|
self.read_timeout = read_timeout;
|
||||||
self.write_timeout = write_timeout;
|
self.write_timeout = write_timeout;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -221,6 +224,17 @@ impl Wrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn usb_reset(&mut self) -> std::io::Result<()> {
|
||||||
|
match unsafe { libftdi1_sys::ftdi_usb_reset(self.context) } {
|
||||||
|
0 => Ok(()),
|
||||||
|
-1 => Err(std::io::ErrorKind::BrokenPipe.into()),
|
||||||
|
-2 => Err(std::io::ErrorKind::NotConnected.into()),
|
||||||
|
result => Err(std::io::Error::other(format!(
|
||||||
|
"Unexpected response from ftdi_usb_reset: {result}"
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_latency_timer(&mut self, latency: Option<std::time::Duration>) -> std::io::Result<()> {
|
fn set_latency_timer(&mut self, latency: Option<std::time::Duration>) -> std::io::Result<()> {
|
||||||
let latency = u8::try_from(latency.unwrap_or(Wrapper::DEFAULT_POLL_TIMEOUT).as_millis())
|
let latency = u8::try_from(latency.unwrap_or(Wrapper::DEFAULT_POLL_TIMEOUT).as_millis())
|
||||||
.map_err(|_| std::io::ErrorKind::InvalidInput)?;
|
.map_err(|_| std::io::ErrorKind::InvalidInput)?;
|
||||||
@ -300,14 +314,33 @@ impl Wrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tcioflush(&mut self) -> std::io::Result<()> {
|
fn tciflush(&mut self) -> std::io::Result<()> {
|
||||||
match unsafe { libftdi1_sys::ftdi_tcioflush(self.context) } {
|
let timeout = std::time::Instant::now();
|
||||||
|
loop {
|
||||||
|
match self.read(&mut vec![0u8; self.read_chunksize]) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(error) => match error.kind() {
|
||||||
|
std::io::ErrorKind::Interrupted | std::io::ErrorKind::WouldBlock => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => return Err(error),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if timeout.elapsed() > self.read_timeout {
|
||||||
|
return Err(std::io::ErrorKind::TimedOut.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tcoflush(&mut self) -> std::io::Result<()> {
|
||||||
|
self.write_buffer.clear();
|
||||||
|
match unsafe { libftdi1_sys::ftdi_tcoflush(self.context) } {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
-1 => Err(std::io::ErrorKind::BrokenPipe.into()),
|
-1 => Err(std::io::ErrorKind::BrokenPipe.into()),
|
||||||
-2 => Err(std::io::ErrorKind::BrokenPipe.into()),
|
-2 => Err(std::io::ErrorKind::BrokenPipe.into()),
|
||||||
-3 => Err(std::io::ErrorKind::NotConnected.into()),
|
-3 => Err(std::io::ErrorKind::NotConnected.into()),
|
||||||
result => Err(std::io::Error::other(format!(
|
result => Err(std::io::Error::other(format!(
|
||||||
"Unexpected response from ftdi_tcioflush: {result}"
|
"Unexpected response from ftdi_tcoflush: {result}"
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,6 +476,8 @@ impl FtdiDevice {
|
|||||||
|
|
||||||
wrapper.usb_open_string(description)?;
|
wrapper.usb_open_string(description)?;
|
||||||
|
|
||||||
|
wrapper.usb_reset()?;
|
||||||
|
|
||||||
wrapper.set_latency_timer(poll_timeout)?;
|
wrapper.set_latency_timer(poll_timeout)?;
|
||||||
|
|
||||||
Ok(FtdiDevice { wrapper })
|
Ok(FtdiDevice { wrapper })
|
||||||
@ -456,8 +491,12 @@ impl FtdiDevice {
|
|||||||
Ok(self.wrapper.poll_modem_status()?.dsr)
|
Ok(self.wrapper.poll_modem_status()?.dsr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discard_buffers(&mut self) -> std::io::Result<()> {
|
pub fn discard_input(&mut self) -> std::io::Result<()> {
|
||||||
self.wrapper.tcioflush()
|
self.wrapper.tciflush()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn discard_output(&mut self) -> std::io::Result<()> {
|
||||||
|
self.wrapper.tcoflush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::{error::Error, ftdi::FtdiDevice};
|
use super::{error::Error, ftdi::FtdiDevice};
|
||||||
use serial2::SerialPort;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
@ -197,7 +196,7 @@ pub trait Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SerialBackend {
|
pub struct SerialBackend {
|
||||||
device: SerialPort,
|
device: serial2::SerialPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for SerialBackend {
|
impl Backend for SerialBackend {
|
||||||
@ -250,7 +249,7 @@ impl Backend for SerialBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_serial_backend(port: &str) -> std::io::Result<SerialBackend> {
|
fn new_serial_backend(port: &str) -> std::io::Result<SerialBackend> {
|
||||||
let mut serial = SerialPort::open(port, 115_200)?;
|
let mut serial = serial2::SerialPort::open(port, 115_200)?;
|
||||||
serial.set_read_timeout(POLL_TIMEOUT)?;
|
serial.set_read_timeout(POLL_TIMEOUT)?;
|
||||||
serial.set_write_timeout(WRITE_TIMEOUT)?;
|
serial.set_write_timeout(WRITE_TIMEOUT)?;
|
||||||
Ok(SerialBackend { device: serial })
|
Ok(SerialBackend { device: serial })
|
||||||
@ -274,10 +273,11 @@ impl Backend for FtdiBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self) -> std::io::Result<()> {
|
fn reset(&mut self) -> std::io::Result<()> {
|
||||||
self.device.set_dtr(true)?;
|
self.device.discard_output()?;
|
||||||
|
|
||||||
let timeout = Instant::now();
|
let timeout = Instant::now();
|
||||||
|
self.device.set_dtr(true)?;
|
||||||
loop {
|
loop {
|
||||||
self.device.discard_buffers()?;
|
|
||||||
if self.device.read_dsr()? {
|
if self.device.read_dsr()? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -289,10 +289,10 @@ impl Backend for FtdiBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.purge_incoming_data()?;
|
self.device.discard_input()?;
|
||||||
|
|
||||||
self.device.set_dtr(false)?;
|
|
||||||
let timeout = Instant::now();
|
let timeout = Instant::now();
|
||||||
|
self.device.set_dtr(false)?;
|
||||||
loop {
|
loop {
|
||||||
if !self.device.read_dsr()? {
|
if !self.device.read_dsr()? {
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user