stmhal: Reduce coupling between USB driver and readline.
This makes it easier to re-use readline.c and pyexec.c from stmhal in other ports.
This commit is contained in:
parent
6f5eb84c19
commit
5cbc9e0db0
@ -41,7 +41,7 @@ STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) {
|
||||
vstr_t line;
|
||||
vstr_init(&line, 16);
|
||||
int ret = readline(&line, "");
|
||||
if (line.len == 0 && ret == VCP_CHAR_CTRL_D) {
|
||||
if (line.len == 0 && ret == CHAR_CTRL_D) {
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
|
||||
}
|
||||
mp_obj_t o = mp_obj_new_str(line.buf, line.len, false);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "usb.h"
|
||||
#include "mphal.h"
|
||||
|
||||
// this table converts from HAL_StatusTypeDef to POSIX errno
|
||||
@ -18,3 +19,7 @@ const byte mp_hal_status_to_errno_table[4] = {
|
||||
NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(mp_hal_status_to_errno_table[status])));
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char(int c) {
|
||||
usb_vcp_set_interrupt_char(c);
|
||||
}
|
||||
|
@ -10,3 +10,4 @@
|
||||
extern const byte mp_hal_status_to_errno_table[4];
|
||||
|
||||
NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
|
||||
void mp_hal_set_interrupt_char(int c); // -1 to disable
|
||||
|
@ -46,8 +46,6 @@
|
||||
#include "systick.h"
|
||||
#include "readline.h"
|
||||
#include "pyexec.h"
|
||||
#include "usb.h"
|
||||
#include "uart.h"
|
||||
#include "pybstdio.h"
|
||||
#include "genhdr/py-version.h"
|
||||
|
||||
@ -97,9 +95,9 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
|
||||
nlr_buf_t nlr;
|
||||
uint32_t start = HAL_GetTick();
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
|
||||
mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us
|
||||
mp_call_function_0(module_fun);
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
|
||||
mp_hal_set_interrupt_char(-1); // disable interrupt
|
||||
nlr_pop();
|
||||
ret = 1;
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
@ -108,7 +106,7 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
|
||||
} else {
|
||||
// uncaught exception
|
||||
// FIXME it could be that an interrupt happens just before we disable it here
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
|
||||
mp_hal_set_interrupt_char(-1); // disable interrupt
|
||||
// print EOF after normal output
|
||||
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
|
||||
stdout_tx_strn("\x04", 1);
|
||||
@ -125,8 +123,8 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
|
||||
|
||||
// display debugging info if wanted
|
||||
if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) {
|
||||
uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
|
||||
printf("took %lu ms\n", ticks);
|
||||
mp_uint_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
|
||||
printf("took " UINT_FMT " ms\n", ticks);
|
||||
gc_collect();
|
||||
// qstr info
|
||||
{
|
||||
@ -166,19 +164,19 @@ raw_repl_reset:
|
||||
stdout_tx_str(">");
|
||||
for (;;) {
|
||||
char c = stdin_rx_chr();
|
||||
if (c == VCP_CHAR_CTRL_A) {
|
||||
if (c == CHAR_CTRL_A) {
|
||||
// reset raw REPL
|
||||
goto raw_repl_reset;
|
||||
} else if (c == VCP_CHAR_CTRL_B) {
|
||||
} else if (c == CHAR_CTRL_B) {
|
||||
// change to friendly REPL
|
||||
stdout_tx_str("\r\n");
|
||||
vstr_clear(&line);
|
||||
pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
|
||||
return 0;
|
||||
} else if (c == VCP_CHAR_CTRL_C) {
|
||||
} else if (c == CHAR_CTRL_C) {
|
||||
// clear line
|
||||
vstr_reset(&line);
|
||||
} else if (c == VCP_CHAR_CTRL_D) {
|
||||
} else if (c == CHAR_CTRL_D) {
|
||||
// input finished
|
||||
break;
|
||||
} else if (c <= 127) {
|
||||
@ -230,7 +228,7 @@ friendly_repl_reset:
|
||||
for (;;) {
|
||||
nlr_buf_t nlr;
|
||||
printf("pyexec_repl: %p\n", x);
|
||||
usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C);
|
||||
mp_hal_set_interrupt_char(CHAR_CTRL_C);
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
for (;;) {
|
||||
}
|
||||
@ -246,21 +244,21 @@ friendly_repl_reset:
|
||||
vstr_reset(&line);
|
||||
int ret = readline(&line, ">>> ");
|
||||
|
||||
if (ret == VCP_CHAR_CTRL_A) {
|
||||
if (ret == CHAR_CTRL_A) {
|
||||
// change to raw REPL
|
||||
stdout_tx_str("\r\n");
|
||||
vstr_clear(&line);
|
||||
pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
|
||||
return 0;
|
||||
} else if (ret == VCP_CHAR_CTRL_B) {
|
||||
} else if (ret == CHAR_CTRL_B) {
|
||||
// reset friendly REPL
|
||||
stdout_tx_str("\r\n");
|
||||
goto friendly_repl_reset;
|
||||
} else if (ret == VCP_CHAR_CTRL_C) {
|
||||
} else if (ret == CHAR_CTRL_C) {
|
||||
// break
|
||||
stdout_tx_str("\r\n");
|
||||
continue;
|
||||
} else if (ret == VCP_CHAR_CTRL_D) {
|
||||
} else if (ret == CHAR_CTRL_D) {
|
||||
// exit for a soft reset
|
||||
stdout_tx_str("\r\n");
|
||||
vstr_clear(&line);
|
||||
@ -272,11 +270,11 @@ friendly_repl_reset:
|
||||
while (mp_repl_continue_with_input(vstr_str(&line))) {
|
||||
vstr_add_char(&line, '\n');
|
||||
int ret = readline(&line, "... ");
|
||||
if (ret == VCP_CHAR_CTRL_C) {
|
||||
if (ret == CHAR_CTRL_C) {
|
||||
// cancel everything
|
||||
stdout_tx_str("\r\n");
|
||||
goto input_restart;
|
||||
} else if (ret == VCP_CHAR_CTRL_D) {
|
||||
} else if (ret == CHAR_CTRL_D) {
|
||||
// stop entering compound statement
|
||||
break;
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include MICROPY_HAL_H
|
||||
#include "readline.h"
|
||||
#include "usb.h"
|
||||
#include "uart.h"
|
||||
#include "pybstdio.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
@ -80,16 +79,16 @@ int readline(vstr_t *line, const char *prompt) {
|
||||
bool redraw_from_cursor = false;
|
||||
int redraw_step_forward = 0;
|
||||
if (escape_seq == ESEQ_NONE) {
|
||||
if (VCP_CHAR_CTRL_A <= c && c <= VCP_CHAR_CTRL_D && vstr_len(line) == orig_line_len) {
|
||||
if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_D && vstr_len(line) == orig_line_len) {
|
||||
// control character with empty line
|
||||
return c;
|
||||
} else if (c == VCP_CHAR_CTRL_A) {
|
||||
} else if (c == CHAR_CTRL_A) {
|
||||
// CTRL-A with non-empty line is go-to-start-of-line
|
||||
goto home_key;
|
||||
} else if (c == VCP_CHAR_CTRL_C) {
|
||||
} else if (c == CHAR_CTRL_C) {
|
||||
// CTRL-C with non-empty line is cancel
|
||||
return c;
|
||||
} else if (c == VCP_CHAR_CTRL_E) {
|
||||
} else if (c == CHAR_CTRL_E) {
|
||||
// CTRL-E is go-to-end-of-line
|
||||
goto end_key;
|
||||
} else if (c == '\r') {
|
||||
|
@ -24,5 +24,11 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define CHAR_CTRL_A (1)
|
||||
#define CHAR_CTRL_B (2)
|
||||
#define CHAR_CTRL_C (3)
|
||||
#define CHAR_CTRL_D (4)
|
||||
#define CHAR_CTRL_E (5)
|
||||
|
||||
void readline_init0(void);
|
||||
int readline(vstr_t *line, const char *prompt);
|
||||
|
@ -54,7 +54,7 @@ STATIC mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
|
||||
void pyb_usb_init0(void) {
|
||||
// create an exception object for interrupting by VCP
|
||||
mp_const_vcp_interrupt = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
USBD_CDC_SetInterrupt(VCP_CHAR_NONE, mp_const_vcp_interrupt);
|
||||
USBD_CDC_SetInterrupt(-1, mp_const_vcp_interrupt);
|
||||
}
|
||||
|
||||
void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) {
|
||||
@ -105,7 +105,7 @@ bool usb_vcp_is_connected(void) {
|
||||
|
||||
void usb_vcp_set_interrupt_char(int c) {
|
||||
if (dev_is_enabled) {
|
||||
if (c != VCP_CHAR_NONE) {
|
||||
if (c != -1) {
|
||||
mp_obj_exception_clear_traceback(mp_const_vcp_interrupt);
|
||||
}
|
||||
USBD_CDC_SetInterrupt(c, mp_const_vcp_interrupt);
|
||||
|
@ -24,13 +24,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define VCP_CHAR_NONE (0)
|
||||
#define VCP_CHAR_CTRL_A (1)
|
||||
#define VCP_CHAR_CTRL_B (2)
|
||||
#define VCP_CHAR_CTRL_C (3)
|
||||
#define VCP_CHAR_CTRL_D (4)
|
||||
#define VCP_CHAR_CTRL_E (5)
|
||||
|
||||
typedef enum {
|
||||
USB_DEVICE_MODE_CDC_MSC,
|
||||
USB_DEVICE_MODE_CDC_HID,
|
||||
|
@ -41,12 +41,6 @@
|
||||
#include "usbd_cdc_interface.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "usb.h"
|
||||
|
||||
// CDC control commands
|
||||
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
|
||||
@ -79,7 +73,7 @@ static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
|
||||
static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
|
||||
static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
|
||||
|
||||
static int user_interrupt_char = VCP_CHAR_NONE;
|
||||
static int user_interrupt_char = -1;
|
||||
static void *user_interrupt_data = NULL;
|
||||
|
||||
/* USB handler declaration */
|
||||
@ -159,7 +153,7 @@ static int8_t CDC_Itf_Init(void)
|
||||
* may be called before this init function to set these values.
|
||||
* This can happen if the USB enumeration occurs after the call to
|
||||
* USBD_CDC_SetInterrupt.
|
||||
user_interrupt_char = VCP_CHAR_NONE;
|
||||
user_interrupt_char = -1;
|
||||
user_interrupt_data = NULL;
|
||||
*/
|
||||
|
||||
@ -351,7 +345,7 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
|
||||
|
||||
uint32_t delta_len;
|
||||
|
||||
if (user_interrupt_char == VCP_CHAR_NONE) {
|
||||
if (user_interrupt_char == -1) {
|
||||
// no special interrupt character
|
||||
delta_len = *Len;
|
||||
|
||||
|
@ -14,3 +14,9 @@ uint32_t HAL_GetTick(void) {
|
||||
void HAL_Delay(uint32_t Delay) {
|
||||
delay(Delay);
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char(int c) {
|
||||
// The teensy 3.1 usb stack doesn't currently have the notion of generating
|
||||
// an exception when a certain character is received. That just means that
|
||||
// you can't press Control-C and get your python script to stop.
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ __attribute__(( always_inline )) static inline void __WFI(void) {
|
||||
|
||||
uint32_t HAL_GetTick(void);
|
||||
void HAL_Delay(uint32_t Delay);
|
||||
void mp_hal_set_interrupt_char(int c);
|
||||
|
||||
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init);
|
||||
|
||||
|
@ -22,12 +22,6 @@ bool usb_vcp_is_enabled(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
void usb_vcp_set_interrupt_char(int c) {
|
||||
// The teensy 3.1 usb stack doesn't currently have the notion of generating
|
||||
// an exception when a certain character is received. That just means that
|
||||
// you can't press Control-C and get your python script to stop.
|
||||
}
|
||||
|
||||
int usb_vcp_rx_num(void) {
|
||||
return usb_serial_available();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user