stmhal: Add ioctl to USB_VCP object, so it works with select.

This patch also enables non-blocking streams on stmhal port.

One can now make a USB-UART pass-through function:

def pass_through(usb, uart):
    while True:
        select.select([usb, uart], [], [])
        if usb.any():
            uart.write(usb.read(256))
        if uart.any():
            usb.write(uart.read(256))

pass_through(pyb.USB_VCP(), pyb.UART(1, 9600))
This commit is contained in:
Damien George 2014-10-31 00:12:02 +00:00
parent efc49c5591
commit 9a41b32b3f
4 changed files with 55 additions and 10 deletions

View File

@ -48,6 +48,7 @@
*/ */
#define MICROPY_ENABLE_LFN (1) #define MICROPY_ENABLE_LFN (1)
#define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1) #define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1)

View File

@ -24,7 +24,9 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include "usbd_core.h" #include "usbd_core.h"
#include "usbd_desc.h" #include "usbd_desc.h"
@ -40,6 +42,7 @@
#include "stream.h" #include "stream.h"
#include "bufhelper.h" #include "bufhelper.h"
#include "usb.h" #include "usb.h"
#include "pybioctl.h"
#ifdef USE_DEVICE_MODE #ifdef USE_DEVICE_MODE
USBD_HandleTypeDef hUSBDDevice; USBD_HandleTypeDef hUSBDDevice;
@ -243,16 +246,6 @@ STATIC mp_obj_t pyb_usb_vcp_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv);
STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Rx((byte*)buf, size, -1);
return ret;
}
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Tx((const byte*)buf, size, -1);
return ret;
}
mp_obj_t pyb_usb_vcp___exit__(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_t pyb_usb_vcp___exit__(mp_uint_t n_args, const mp_obj_t *args) {
return mp_const_none; return mp_const_none;
} }
@ -279,9 +272,51 @@ STATIC const mp_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table);
STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Rx((byte*)buf, size, 0);
if (ret == 0) {
// return EAGAIN error to indicate non-blocking
*errcode = EAGAIN;
return MP_STREAM_ERROR;
}
return ret;
}
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Tx((const byte*)buf, size, 0);
if (ret == 0) {
// return EAGAIN error to indicate non-blocking
*errcode = EAGAIN;
return MP_STREAM_ERROR;
}
return ret;
}
STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, int *errcode, ...) {
va_list vargs;
va_start(vargs, errcode);
mp_uint_t ret;
if (request == MP_IOCTL_POLL) {
mp_uint_t flags = va_arg(vargs, mp_uint_t);
ret = 0;
if ((flags & MP_IOCTL_POLL_RD) && USBD_CDC_RxNum() > 0) {
ret |= MP_IOCTL_POLL_RD;
}
if ((flags & MP_IOCTL_POLL_WR) && USBD_CDC_TxHalfEmpty()) {
ret |= MP_IOCTL_POLL_WR;
}
} else {
*errcode = EINVAL;
ret = MP_STREAM_ERROR;
}
va_end(vargs);
return ret;
}
STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = { STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = {
.read = pyb_usb_vcp_read, .read = pyb_usb_vcp_read,
.write = pyb_usb_vcp_write, .write = pyb_usb_vcp_write,
.ioctl = pyb_usb_vcp_ioctl,
}; };
const mp_obj_type_t pyb_usb_vcp_type = { const mp_obj_type_t pyb_usb_vcp_type = {

View File

@ -402,6 +402,14 @@ void USBD_CDC_SetInterrupt(int chr, void *data) {
user_interrupt_data = data; user_interrupt_data = data;
} }
int USBD_CDC_TxHalfEmpty(void) {
int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut;
if (tx_waiting < 0) {
tx_waiting += APP_TX_DATA_SIZE;
}
return tx_waiting <= APP_TX_DATA_SIZE / 2;
}
// timout in milliseconds. // timout in milliseconds.
// Returns number of bytes written to the device. // Returns number of bytes written to the device.
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) { int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) {

View File

@ -37,6 +37,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void);
int USBD_CDC_IsConnected(void); int USBD_CDC_IsConnected(void);
void USBD_CDC_SetInterrupt(int chr, void *data); void USBD_CDC_SetInterrupt(int chr, void *data);
int USBD_CDC_TxHalfEmpty(void);
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout); int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout);
void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len); void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len);