Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/pbio/drv/usb/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,14 +294,14 @@ static pbio_error_t pbdrv_usb_process_thread(pbio_os_state_t *state, void *conte
pbdrv_usb_respond_soon = false;

// Send the response.
PBIO_OS_AWAIT(state, &sub, err = pbdrv_usb_tx_response(&sub, error_code));
PBIO_OS_AWAIT(state, &sub, err = pbdrv_usb_tx_response(&sub, error_code, pbdrv_usb_process.request == PBIO_OS_PROCESS_REQUEST_TYPE_CANCEL));
if (err != PBIO_SUCCESS) {
pbdrv_usb_reset_state();
PBIO_OS_AWAIT(state, &sub, pbdrv_usb_tx_reset(&sub));
}
} else if (pbdrv_usb_connection_is_active() && update_and_get_event_buffer(&noti_buf, &noti_size)) {
// Send out pending event if any.
PBIO_OS_AWAIT(state, &sub, err = pbdrv_usb_tx_event(&sub, noti_buf, *noti_size));
PBIO_OS_AWAIT(state, &sub, err = pbdrv_usb_tx_event(&sub, noti_buf, *noti_size, pbdrv_usb_process.request == PBIO_OS_PROCESS_REQUEST_TYPE_CANCEL));
*noti_size = 0;
if (err != PBIO_SUCCESS) {
pbdrv_usb_reset_state();
Expand Down
14 changes: 8 additions & 6 deletions lib/pbio/drv/usb/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ uint32_t pbdrv_usb_get_data_and_start_receive(uint8_t *data);
/**
* Sends and awaits event message from hub to host via the Pybricks USB interface OUT endpoint.
*
* Driver-specific implementation. Must return within ::PBDRV_USB_TRANSMIT_TIMEOUT.
* Driver-specific implementation. Must support being canceled via @p cancel.
*
* The USB process ensures that only one call is made at once.
*
Expand All @@ -60,31 +60,33 @@ uint32_t pbdrv_usb_get_data_and_start_receive(uint8_t *data);
* @param [in] state Protothread state.
* @param [in] data Data to send.
* @param [in] size Data size.
* @param [in] cancel If true, stop waiting for completion and return error.
* @return ::PBIO_SUCCESS on completion.
* ::PBIO_ERROR_INVALID_OP if there is no connection.
* ::PBIO_ERROR_AGAIN while awaiting.
* ::PBIO_ERROR_BUSY if this operation is already ongoing.
* ::PBIO_ERROR_INVALID_ARG if @p size is too large.
* ::PBIO_ERROR_TIMEDOUT if the operation was started but could not complete.
* ::PBIO_ERROR_CANCELED if the operation was canceled.
*/
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size);
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel);

/**
* Sends and awaits response to an earlier incoming message.
*
* Driver-specific implementation. Must return within ::PBDRV_USB_TRANSMIT_TIMEOUT.
* Driver-specific implementation. Must support being canceled via @p cancel.
*
* The USB process ensures that only one call is made at once.
*
* @param [in] state Protothread state.
* @param [in] code Error code to send.
* @param [in] cancel If true, stop waiting for completion and return error.
* @return ::PBIO_SUCCESS on completion.
* ::PBIO_ERROR_INVALID_OP if there is no connection.
* ::PBIO_ERROR_AGAIN while awaiting.
* ::PBIO_ERROR_BUSY if this operation is already ongoing.
* ::PBIO_ERROR_TIMEDOUT if the operation was started but could not complete.
* ::PBIO_ERROR_CANCELED if the operation was canceled.
*/
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code);
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel);

/**
* Resets the driver transmission state.
Expand Down
27 changes: 8 additions & 19 deletions lib/pbio/drv/usb/usb_ev3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1023,9 +1023,7 @@ pbio_error_t pbdrv_usb_tx_reset(pbio_os_state_t *state) {
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

Expand All @@ -1034,28 +1032,20 @@ pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uin
}

transmitting = true;
pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);

// Transmit event.
pbdrv_cache_prepare_before_dma(data, size);
usb_setup_tx_dma_desc(CPPI_DESC_TX_PYBRICKS_EVENT, (uint8_t *)data, size);

PBIO_OS_AWAIT_UNTIL(state, !transmitting || pbio_os_timer_is_expired(&timer));

if (pbio_os_timer_is_expired(&timer)) {
// Transmission has taken too long, so reset the state to allow
// new transmissions. This can happen if the host stops reading
// data for some reason. This need some time to complete, so delegate
// the reset back to the process.
return PBIO_ERROR_TIMEDOUT;
PBIO_OS_AWAIT_UNTIL(state, !transmitting || cancel);
if (transmitting && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel) {

static uint8_t ep1_tx_response_buf[1 + sizeof(uint32_t)] __aligned(4) = { PBIO_PYBRICKS_IN_EP_MSG_RESPONSE };

Expand All @@ -1066,7 +1056,6 @@ pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t
}

transmitting = true;
pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);

// Response is just the error code.
pbio_set_uint32_le(&ep1_tx_response_buf[1], code);
Expand All @@ -1076,9 +1065,9 @@ pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t
usb_setup_tx_dma_desc(CPPI_DESC_TX_RESPONSE, ep1_tx_response_buf, sizeof(ep1_tx_response_buf));

// Wait until complete or trigger reset on timeout.
PBIO_OS_AWAIT_UNTIL(state, !transmitting || pbio_os_timer_is_expired(&timer));
if (pbio_os_timer_is_expired(&timer)) {
return PBIO_ERROR_TIMEDOUT;
PBIO_OS_AWAIT_UNTIL(state, !transmitting || cancel);
if (transmitting && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
Expand Down
22 changes: 8 additions & 14 deletions lib/pbio/drv/usb/usb_nxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,9 +853,7 @@ pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void) {
return PBDRV_USB_BCD_NONE;
}

pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

Expand All @@ -864,20 +862,17 @@ pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uin
// return PBIO_ERROR_BUSY;
// }

pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);
pbdrv_usb_nxt_write_data(2, data, size);

PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_nxt_state.status == USB_READY || pbio_os_timer_is_expired(&timer));
if (pbio_os_timer_is_expired(&timer)) {
return PBIO_ERROR_TIMEDOUT;
PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_nxt_state.status == USB_READY || cancel);
if (pbdrv_usb_nxt_state.status != USB_READY && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel) {

static uint8_t usb_response_buf[PBIO_PYBRICKS_USB_MESSAGE_SIZE(sizeof(uint32_t))] __aligned(4) = { PBIO_PYBRICKS_IN_EP_MSG_RESPONSE };

Expand All @@ -888,13 +883,12 @@ pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t
// return PBIO_ERROR_BUSY;
// }

pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);
pbio_set_uint32_le(&usb_response_buf[1], code);
pbdrv_usb_nxt_write_data(2, usb_response_buf, sizeof(usb_response_buf));

PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_nxt_state.status == USB_READY || pbio_os_timer_is_expired(&timer));
if (pbio_os_timer_is_expired(&timer)) {
return PBIO_ERROR_TIMEDOUT;
PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_nxt_state.status == USB_READY || cancel);
if (pbdrv_usb_nxt_state.status != USB_READY && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
Expand Down
4 changes: 2 additions & 2 deletions lib/pbio/drv/usb/usb_simulation.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void) {
return PBDRV_USB_BCD_NONE;
}

pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size) {
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel) {

static pbio_os_timer_t timer;

Expand All @@ -53,7 +53,7 @@ pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uin
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code) {
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel) {

static pbio_os_timer_t timer;

Expand Down
9 changes: 6 additions & 3 deletions lib/pbio/drv/usb/usb_simulation_pico.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pbdrv_usb_bcd_t pbdrv_usb_get_bcd(void) {
return PBDRV_USB_BCD_NONE;
}

pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size) {
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

Expand All @@ -54,7 +54,10 @@ pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uin
pbdrv_usb_simulation_tx_ready = false;
// Enable TX interrupt to be notified when ready.
hw_set_bits(&uart_get_hw(uart_default)->imsc, 1 << UART_UARTIMSC_TXIM_LSB);
PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_simulation_tx_ready);
PBIO_OS_AWAIT_UNTIL(state, pbdrv_usb_simulation_tx_ready || cancel);
if (!pbdrv_usb_simulation_tx_ready && cancel) {
return PBIO_ERROR_CANCELED;
}
}

uart_get_hw(uart_default)->dr = data[i];
Expand All @@ -63,7 +66,7 @@ pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uin
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code) {
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

Expand Down
30 changes: 16 additions & 14 deletions lib/pbio/drv/usb/usb_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,48 +292,50 @@ pbio_error_t pbdrv_usb_tx_reset(pbio_os_state_t *state) {
return PBIO_SUCCESS;
}

pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_event(pbio_os_state_t *state, const uint8_t *data, uint32_t size, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

if (cancel) {
return PBIO_ERROR_CANCELED;
}

if (transmitting) {
return PBIO_ERROR_BUSY;
}

transmitting = true;
pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);
USBD_Pybricks_TransmitPacket(&husbd, (uint8_t *)data, size);
PBIO_OS_AWAIT_UNTIL(state, !transmitting || pbio_os_timer_is_expired(&timer));
PBIO_OS_AWAIT_UNTIL(state, !transmitting || cancel);

if (pbio_os_timer_is_expired(&timer)) {
return PBIO_ERROR_TIMEDOUT;
if (transmitting && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
}

pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code) {

static pbio_os_timer_t timer;
pbio_error_t pbdrv_usb_tx_response(pbio_os_state_t *state, pbio_pybricks_error_t code, bool cancel) {

PBIO_OS_ASYNC_BEGIN(state);

if (cancel) {
return PBIO_ERROR_CANCELED;
}

if (transmitting) {
return PBIO_ERROR_BUSY;
}

transmitting = true;
pbio_os_timer_set(&timer, PBDRV_USB_TRANSMIT_TIMEOUT);

pbio_set_uint32_le(&usb_response_buf[1], code);

USBD_Pybricks_TransmitPacket(&husbd, usb_response_buf, sizeof(usb_response_buf));

PBIO_OS_AWAIT_UNTIL(state, !transmitting || pbio_os_timer_is_expired(&timer));
if (pbio_os_timer_is_expired(&timer)) {
return PBIO_ERROR_TIMEDOUT;
PBIO_OS_AWAIT_UNTIL(state, !transmitting || cancel);
if (transmitting && cancel) {
return PBIO_ERROR_CANCELED;
}

PBIO_OS_ASYNC_END(PBIO_SUCCESS);
Expand Down
2 changes: 1 addition & 1 deletion lib/pbio/platform/prime_hub/pbdrvconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
#define PBDRV_CONFIG_USB_PROD_STR LEGO_USB_PROD_STR_TECHNIC_LARGE_HUB " + Pybricks"
#define PBDRV_CONFIG_USB_STM32F4 (1)
#define PBDRV_CONFIG_USB_STM32F4_HUB_VARIANT_ADDR 0x08007d80
#define PBDRV_CONFIG_USB_CHARGE_ONLY (1)
#define PBDRV_CONFIG_USB_CHARGE_ONLY (0)

#define PBDRV_CONFIG_STACK (1)
#define PBDRV_CONFIG_STACK_EMBEDDED (1)
Expand Down