From 87960830f4eb656f410ff3b220151e0b5ad9a556 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 4 Nov 2010 16:49:03 +1300 Subject: Fixed HALT condition handling and data toggle. --- include/libopenstm32/tools.h | 4 ++-- include/libopenstm32/usb.h | 12 ++++++++++++ include/usbd.h | 3 ++- lib/usb/usb_control.c | 16 ++++++++-------- lib/usb/usb_f103.c | 41 ++++++++++++++++++++++++++++------------- lib/usb/usb_standard.c | 10 +++++----- 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/include/libopenstm32/tools.h b/include/libopenstm32/tools.h index 2a7a0f1..8b32413 100644 --- a/include/libopenstm32/tools.h +++ b/include/libopenstm32/tools.h @@ -52,10 +52,10 @@ */ #define TOG_SET_REG_BIT_MSK(REG, MSK, BIT) \ do { \ - register u16 toggle_mask = GET_REG(REG) & MSK; \ + register u16 toggle_mask = GET_REG(REG) & (MSK); \ register u16 bit_selector; \ for (bit_selector = 1; bit_selector; bit_selector <<= 1) { \ - if ((bit_selector & BIT) != 0) \ + if ((bit_selector & (BIT)) != 0) \ toggle_mask ^= bit_selector; \ } \ SET_REG(REG, toggle_mask); \ diff --git a/include/libopenstm32/usb.h b/include/libopenstm32/usb.h index 3e0efe9..6edfee3 100644 --- a/include/libopenstm32/usb.h +++ b/include/libopenstm32/usb.h @@ -244,6 +244,18 @@ (USB_EP_NTOGGLE_MSK & \ (~USB_EP_ADDR))) | ADDR)) +/* Macros for clearing DTOG bits */ +#define USB_CLR_EP_TX_DTOG(EP) \ + SET_REG(USB_EP_REG(EP), \ + (GET_REG(USB_EP_REG(EP)) & \ + USB_EP_NTOGGLE_MSK) | USB_EP_TX_DTOG) + +#define USB_CLR_EP_RX_DTOG(EP) \ + SET_REG(USB_EP_REG(EP), \ + (GET_REG(USB_EP_REG(EP)) & \ + USB_EP_NTOGGLE_MSK) | USB_EP_RX_DTOG) + + /****************************************************************************** * USB BTABLE registers ******************************************************************************/ diff --git a/include/usbd.h b/include/usbd.h index 9f1c57d..d825d9e 100644 --- a/include/usbd.h +++ b/include/usbd.h @@ -64,7 +64,8 @@ usbd_ep_write_packet(uint8_t addr, const void *buf, uint16_t len); extern uint16_t usbd_ep_read_packet(uint8_t addr, void *buf, uint16_t len); -extern void usbd_ep_stall(uint8_t addr); +extern void usbd_ep_stall_set(uint8_t addr, uint8_t stall); +extern uint8_t usbd_ep_stall_get(uint8_t addr); /* Optional */ extern void usbd_cable_connect(uint8_t on); diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c index 950e491..f5e4d27 100644 --- a/lib/usb/usb_control.c +++ b/lib/usb/usb_control.c @@ -93,7 +93,7 @@ static int usb_control_recv_chunk(void) packetsize); if (size != packetsize) { - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); return -1; } @@ -127,7 +127,7 @@ static void usb_control_setup_nodata(struct usb_setup_data *req) control_state.state = STATUS_IN; } else { /* Stall endpoint on failure */ - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); } } @@ -156,14 +156,14 @@ static void usb_control_setup_read(struct usb_setup_data *req) usb_control_send_chunk(); } else { /* Stall endpoint on failure */ - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); } } static void usb_control_setup_write(struct usb_setup_data *req) { if(req->wLength > _usbd_device.ctrl_buf_len) { - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); return; } @@ -184,7 +184,7 @@ void _usbd_control_setup(uint8_t ea) control_state.complete = NULL; if(usbd_ep_read_packet(0, req, 8) != 8) { - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); return; } @@ -233,7 +233,7 @@ void _usbd_control_out(uint8_t ea) usbd_ep_write_packet(0, NULL, 0); control_state.state = STATUS_IN; } else { - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); } break; @@ -249,7 +249,7 @@ void _usbd_control_out(uint8_t ea) } default: - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); } } @@ -280,7 +280,7 @@ void _usbd_control_in(uint8_t ea) } default: - usbd_ep_stall(0); + usbd_ep_stall_set(0, 1); } } diff --git a/lib/usb/usb_f103.c b/lib/usb/usb_f103.c index 1af4493..5a79a82 100644 --- a/lib/usb/usb_f103.c +++ b/lib/usb/usb_f103.c @@ -83,6 +83,7 @@ void usbd_ep_setup(u8 addr, u8 type, u16 max_size, void (*callback)(u8 ep)) USB_SET_EP_TX_ADDR(addr, _usbd_device.pm_top); if(callback) _usbd_device.user_callback_ctr[addr][USB_TRANSACTION_IN] = (void*)callback; + USB_CLR_EP_TX_DTOG(addr); USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_NAK); _usbd_device.pm_top += max_size; } @@ -91,6 +92,7 @@ void usbd_ep_setup(u8 addr, u8 type, u16 max_size, void (*callback)(u8 ep)) usb_set_ep_rx_bufsize(addr, max_size); if(callback) _usbd_device.user_callback_ctr[addr][USB_TRANSACTION_OUT] = (void*)callback; + USB_CLR_EP_RX_DTOG(addr); USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID); _usbd_device.pm_top += max_size; } @@ -108,27 +110,40 @@ void _usbd_hw_endpoints_reset(void) _usbd_device.pm_top = 0x40 + (2*_usbd_device.desc->bMaxPacketSize0); } -void usbd_ep_stall(u8 addr) +void usbd_ep_stall_set(u8 addr, u8 stall) { if(addr == 0) - USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_STALL); + USB_SET_EP_TX_STAT(addr, + stall ? USB_EP_TX_STAT_STALL : USB_EP_TX_STAT_NAK); - if(addr & 0x80) - USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_STALL); - else - USB_SET_EP_RX_STAT(addr&0x7F, USB_EP_RX_STAT_STALL); + if(addr & 0x80) { + addr &= 0x7F; + + USB_SET_EP_TX_STAT(addr, + stall ? USB_EP_TX_STAT_STALL : USB_EP_TX_STAT_NAK); + + /* Reset to DATA0 if clearing stall condition */ + if(!stall) + USB_CLR_EP_TX_DTOG(addr); + } else { + /* Reset to DATA0 if clearing stall condition */ + if(!stall) + USB_CLR_EP_RX_DTOG(addr); + + USB_SET_EP_RX_STAT(addr, + stall ? USB_EP_RX_STAT_STALL : USB_EP_RX_STAT_VALID); + } } -u8 usbd_get_ep_stall(u8 addr) +u8 usbd_ep_stall_get(u8 addr) { - if(addr == 0) - if ((*USB_EP_REG(addr) & USB_EP_TX_STAT) == USB_EP_TX_STAT_STALL) - return 1; if(addr & 0x80) { - if ((*USB_EP_REG(addr) & USB_EP_TX_STAT) == USB_EP_TX_STAT_STALL) - return 1; + if ((*USB_EP_REG(addr & 0x7F) & USB_EP_TX_STAT) == + USB_EP_TX_STAT_STALL) + return 1; } else { - if ((*USB_EP_REG(addr&0x7F) & USB_EP_RX_STAT) == USB_EP_RX_STAT_STALL) + if ((*USB_EP_REG(addr) & USB_EP_RX_STAT) == + USB_EP_RX_STAT_STALL) return 1; } return 0; diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c index ae6c2ee..770d3cc 100644 --- a/lib/usb/usb_standard.c +++ b/lib/usb/usb_standard.c @@ -220,7 +220,7 @@ static int usb_standard_endpoint_get_status(struct usb_setup_data *req, (void)req; if(*len > 2) *len = 2; - (*buf)[0] = usbd_get_ep_stall(req->wIndex); + (*buf)[0] = usbd_ep_stall_get(req->wIndex) ? 1 : 0; (*buf)[1] = 0; return 1; @@ -232,7 +232,7 @@ static int usb_standard_endpoint_stall(struct usb_setup_data *req, (void)buf; (void)len; - usbd_ep_stall(req->wIndex); + usbd_ep_stall_set(req->wIndex, 1); return 1; } @@ -243,7 +243,7 @@ static int usb_standard_endpoint_unstall(struct usb_setup_data *req, (void)buf; (void)len; - usbd_ep_stall(req->wIndex); + usbd_ep_stall_set(req->wIndex, 0); return 1; } @@ -329,12 +329,12 @@ int _usbd_standard_request_endpoint(struct usb_setup_data *req, uint8_t **buf, switch(req->bRequest) { case USB_REQ_CLEAR_FEATURE: if (req->wValue == USB_FEAT_ENDPOINT_HALT) { - command = usb_standard_endpoint_stall; + command = usb_standard_endpoint_unstall; } break; case USB_REQ_SET_FEATURE: if (req->wValue == USB_FEAT_ENDPOINT_HALT) { - command = usb_standard_endpoint_unstall; + command = usb_standard_endpoint_stall; } break; case USB_REQ_GET_STATUS: -- cgit v1.2.3