/** ********************************************************************************* * * @file ald_usb.c * @brief USB module driver. * * @version V1.0 * @date 25 Feb 2022 * @author AE Team * @note * Change Logs: * Date Author Notes * 25 Feb 2022 AE Team The first version * * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************** */ #include "ald_conf.h" #include "usb_lowlayer_api.h" /** @addtogroup ES32VF2264_ALD * @{ */ /** @defgroup USB USB * @brief USB module driver * @{ */ #ifdef ALD_USB /** * @defgroup USB_Public_Functions USB Public Function * @{ */ /** @defgroup USB_Public_Functions_Group1 Base functions * @brief Base functions * @{ */ /** * @brief Gets the number of current frame. * @retval Number of the frame. */ uint32_t ald_usb_frame_number_get(void) { uint8_t framel = (uint8_t)USB->FRAME1; uint8_t frameh = (uint8_t)USB->FRAME2; return ((uint32_t)(framel & 0xFF) + ((uint32_t)(frameh & 0xFF) << 8)); } /** * @brief Request the session. * @param start: true/false. * @retval None */ void ald_usb_otg_session_request(bool start) { if (start) USB->DEVCON |= (uint8_t)ALD_USB_DEVCON_SESSION; else USB->DEVCON &= (uint8_t)(~(ALD_USB_DEVCON_SESSION)); return; } /** * @brief Gets the mode. * @retval Mode */ uint32_t ald_usb_mode_get(void) { return (USB->DEVCON & ((uint8_t)(ALD_USB_DEVCON_HOST | ALD_USB_DEVCON_SESSION))); } /** * @brief Start host require. * @retval Mode */ uint32_t ald_usb_mode_host_req(void) { USB->DEVCON |= (uint8_t)ALD_USB_DEVCON_HOSTREQ; return 0; } /** * @brief Clear host require. * @retval Mode */ uint32_t ald_usb_mode_host_req_clear(void) { USB->DEVCON &= (uint8_t)(~ALD_USB_DEVCON_HOSTREQ); return 0; } /** * @brief Enable/Disable the high mode. * @param enable: ENABLE/DISABLE. * @retval None */ void ald_usb_high_speed_enable(bool enable) { assert_param(enable == DISABLE); return; } /** * @brief Gets the speed of the device. * @retval Type of the speed. */ uint32_t ald_usb_device_speed_get(void) { return ALD_USB_FULL_SPEED; } /** * @brief Gets the number of the endpoint. * @retval Number of the endpoint. */ uint32_t ald_usb_num_ep_get( void) { return ALD_NUM_USB_EP; } /** * @brief Reset USB Control. * @retval None */ void ald_usb_control_reset(void) { //ALD_RCU_USB_RESET_ENABLE(); return; } /** * @brief Output USB clock, not support. * @retval None */ void ald_usb_clock_output(void) { return; } /** * @brief Starts eye diagram for high-speed host, not support. * @param buf: Buffer for eye diagram. * @param len: Length of the buffer. * @retval Status, 0 means success, other values means failure. */ int ald_usb_eye_diagram_start(uint8_t *buf, uint16_t len) { return 0; } /** * @brief Pull up or pull down USB dp line. * @param pupd: USB_DPDM_FLOATING/USB_DPDM_PUSH_UP/USB_DPDM_PUSH_DOWN. * @retval None */ void ald_usb_dppud_set(ald_dpdm_push_t pupd) { USB->DPDMCON &= (uint8_t)(~USB_DPDMCON_DPPUD_MSK); USB->DPDMCON |= (uint8_t)(pupd << USB_DPDMCON_DPPUD_POSS); return; } /** * @brief Pull up or pull down USB dm line. * @param pupd: USB_DPDM_FLOATING/USB_DPDM_PUSH_UP/USB_DPDM_PUSH_DOWN. * @retval None */ void ald_usb_dmpud_set(ald_dpdm_push_t pupd) { USB->DPDMCON &= (uint8_t)(~USB_DPDMCON_DMPUD_MSK); USB->DPDMCON |= (uint8_t)(pupd << USB_DPDMCON_DMPUD_POSS); return; } /** * @brief Switch usb mode by software. * @param host: 0, indicates that software force to host host: 1, indicates that software force to device. * @retval None */ void ald_usb_swcid_host(uint8_t host) { if (host) USB->SWCID |= (uint8_t)(USB_SWCID_HOST_MSK); else USB->SWCID &= (uint8_t)(~USB_SWCID_HOST_MSK); return; } /** * @brief Switch the control method of CID. * @param cid: 0, indicates that use the hardware control cid: 1, indicates that use the software control. * @retval None */ void ald_usb_swcid_cidctrl(uint8_t cid) { if (cid) USB->SWCID |= (uint8_t)(ALD_USB_SWCID_CIDCTRL); else USB->SWCID &= (uint8_t)(~ALD_USB_SWCID_CIDCTRL); return; } /** * @} */ /** @defgroup USB_Public_Functions_Group2 Device functions * @brief Device functions * @{ */ /** * @brief Gets the address. * @retval Address. */ uint8_t ald_usb_dev_get_addr(void) { return (USB->FADDR); } /** * @brief Sets the address. * @param addr: The address which will be set. * @retval None */ void ald_usb_dev_set_addr(uint8_t addr) { USB->FADDR = addr; return; } /** * @brief Enable connection. * @retval None */ void ald_usb_dev_connect(void) { USB->DPDMCON |= (uint8_t)(ALD_USB_DPDMCON_PHYPWREN); return; } /** * @brief Disable connection. * @retval None */ void ald_usb_dev_disconnect(void) { USB->DPDMCON &= (uint8_t)(~(ALD_USB_DPDMCON_PHYPWREN)); return; } /** * @brief Enable the devices suspend. * @retval None */ void ald_usb_dev_suspend_enable(void) { USB->POWER |= (uint8_t)USB_POWER_SUSPENDEN_MSK; return; } /** * @brief Configure the endpoint in device mode. * @param ep_idx: Index of the endpoint * @param p_max: Size of the maximum package. * @param flags: Flags of the endpoint. * @retval None */ void ald_usb_dev_ep_config(uint32_t ep_idx, uint32_t p_max, uint32_t flags) { uint32_t tmp = 0U; USB->INDEX = (uint8_t)ep_idx; if (flags & ALD_USB_EP_DEV_IN) { USB->TXMAXP = (uint8_t)(p_max); if (flags & ALD_USB_EP_AUTO_SET) tmp |= USB_TXCSRH_AUTOSET_MSK; if ((flags & ALD_USB_EP_MODE_MASK) == ALD_USB_EP_MODE_ISOC) tmp |= USB_TXCSRH_ISO_MSK; USB->CSR0H_TXCSRH |= (uint8_t)tmp; USB->CSR0L_TXCSRL |= (uint8_t)USB_TXCSRL_CLRDT_MSK; } else { USB->RXMAXP = (uint8_t)(p_max); if (flags & ALD_USB_EP_AUTO_CLEAR) tmp |= USB_RXCSRH_AUTOCLR_MSK; if ((flags & ALD_USB_EP_MODE_MASK) == ALD_USB_EP_MODE_ISOC) tmp |= USB_TXCSRH_ISO_MSK; USB->RXCSRH |= (uint8_t)tmp; USB->RXCSRL |= (uint8_t)USB_RXCSRL_CLRDT_MSK; } return; } /** * @brief Gets the parameters of the endpoint. * @param ep_idx: Index of the endpoint * @param p_max: Size of the maximum package. * @param flags: Flags of the endpoint. * @retval None */ void ald_usb_dev_ep_get_config(uint32_t ep_idx, uint32_t *p_max, uint32_t *flags) { uint32_t tmp; USB->INDEX = (uint8_t)ep_idx; if (*flags & ALD_USB_EP_DEV_IN) { *flags = ALD_USB_EP_DEV_IN; *p_max = (uint32_t)USB->TXMAXP; tmp = (uint32_t)USB->CSR0H_TXCSRH; if (tmp & USB_TXCSRH_AUTOSET_MSK) *flags |= ALD_USB_EP_AUTO_SET; if (tmp & USB_TXCSRH_ISO_MSK) *flags |= ALD_USB_EP_MODE_ISOC; else *flags |= ALD_USB_EP_MODE_BULK; } else { *flags = ALD_USB_EP_DEV_OUT; *p_max = (uint32_t)USB->RXMAXP; tmp = (uint32_t)USB->RXCSRH; if (tmp & USB_RXCSRH_AUTOCLR_MSK) *flags |= ALD_USB_EP_AUTO_CLEAR; if (tmp & USB_RXCSRH_ISO_MSK) *flags |= ALD_USB_EP_MODE_ISOC; else *flags |= ALD_USB_EP_MODE_BULK; } return; } extern void printf_e(const char *fmt, ...); /** * @brief Acknowledge the data from host. * @param ep_idx: Index of the endpoint * @param last: true/false * @retval None */ void ald_usb_dev_ep_data_ack(uint32_t ep_idx, bool last) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL |= (uint8_t)(USB_CSR0L_RXRDYC_MSK | (last ? USB_CSR0L_DATAEND_MSK : 0)); else USB->RXCSRL &= (uint8_t)(~USB_RXCSRL_RXRDY_MSK); return; } /** * @brief Stall the endpoint. * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval None */ void ald_usb_dev_ep_stall(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL |= (uint8_t)(USB_CSR0L_RXRDYC_MSK | USB_CSR0L_STALL_MSK); else if (flags == ALD_USB_EP_DEV_IN) USB->CSR0L_TXCSRL |= (uint8_t)USB_TXCSRL_STALL_MSK; else USB->RXCSRL |= (uint8_t)USB_RXCSRL_STALL_MSK; return; } /** * @brief Cancel the stall status. * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval None */ void ald_usb_dev_ep_stall_clear(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL &= (uint8_t)(~USB_CSR0L_STALLED_MSK); else if (flags == ALD_USB_EP_DEV_IN){ USB->CSR0L_TXCSRL &= (uint8_t)(~(USB_TXCSRL_STALL_MSK | USB_TXCSRL_STALLED_MSK)); USB->CSR0L_TXCSRL |= (uint8_t)USB_TXCSRL_CLRDT_MSK; } else{ USB->RXCSRL &= (uint8_t)(~(USB_RXCSRL_STALL_MSK | USB_RXCSRL_STALLED_MSK)); USB->RXCSRL |= (uint8_t)USB_RXCSRL_CLRDT_MSK; } return; } /** * @brief Clear the status of the endpoint. * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval None */ void ald_usb_dev_ep_status_clear(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { if (flags & ALD_USB_DEV_EP0_OUT_PKTRDY) USB->CSR0L_TXCSRL |= (uint8_t)USB_CSR0L_RXRDYC_MSK; if (flags & ALD_USB_DEV_EP0_SETUP_END) USB->CSR0L_TXCSRL |= (uint8_t)USB_CSR0L_SETENDC_MSK; if (flags & ALD_USB_DEV_EP0_SENT_STALL) USB->CSR0L_TXCSRL &= (uint8_t)(~USB_CSR0L_STALLED_MSK); } else { USB->CSR0L_TXCSRL &= (uint8_t)(~(flags & (ALD_USB_DEV_TX_SENT_STALL | ALD_USB_DEV_TX_UNDERRUN))); USB->RXCSRL &= (uint8_t)(~((flags & (ALD_USB_DEV_RX_SENT_STALL | ALD_USB_DEV_RX_DATA_ERROR | ALD_USB_DEV_RX_OVERRUN)) >> ALD_USB_RX_EPSTATUS_SHIFT)); } return; } /** * @} */ /** @defgroup USB_Public_Functions_Group3 Host functions * @brief Host functions * @{ */ /** * @brief Gets the device's address. * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval Address */ uint32_t ald_usb_host_addr_get(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; return (USB->FADDR); } /** * @brief Sets the device's address. * @param ep_idx: Index of the endpoint. * @param addr: The device's address. * @param flags: Flags. * @retval None */ void ald_usb_host_addr_set(uint32_t ep_idx, uint32_t addr, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; USB->FADDR = (uint8_t)addr; return; } /** * @brief Configure the endpoint in host mode. * @param ep_idx: Index of the endpoint. * @param p_max: Size of the maximum package. * @param nak_val: Value of the nack. * @param t_ep: Target endpoint. * @param flags: Flags. * @retval None */ void ald_usb_host_ep_config(uint32_t ep_idx, uint32_t p_max, uint32_t nak_val, uint32_t t_ep, uint32_t flags) { uint32_t tmp = 0U; USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { USB->NAKLIMIT0_TXINTERVAL = (uint8_t)nak_val; if (flags & ALD_USB_EP_SPEED_HIGH) ; else if (flags & ALD_USB_EP_SPEED_FULL) ; else ; } else { tmp = t_ep; if (flags & ALD_USB_EP_SPEED_HIGH) ; else if (flags & ALD_USB_EP_SPEED_FULL) ; else ; switch (flags & ALD_USB_EP_MODE_MASK) { case ALD_USB_EP_MODE_BULK: tmp |= ALD_USB_TXTYPE1_PROTO_BULK; break; case ALD_USB_EP_MODE_ISOC: tmp |= ALD_USB_TXTYPE1_PROTO_ISOC; break; case ALD_USB_EP_MODE_INT: tmp |= ALD_USB_TXTYPE1_PROTO_INT; break; case ALD_USB_EP_MODE_CTRL: tmp |= ALD_USB_TXTYPE1_PROTO_CTRL; break; } if (flags & ALD_USB_EP_HOST_OUT) { USB->TXTYPE = (uint8_t)tmp; USB->NAKLIMIT0_TXINTERVAL = (uint8_t)nak_val; USB->TXMAXP = (uint8_t)p_max; tmp = 0; if (flags & ALD_USB_EP_AUTO_SET) tmp = (uint8_t)ALD_USB_TXCSRH_AUTOSET; USB->CSR0H_TXCSRH |= (uint8_t)tmp; } else { USB->RXTYPE = (uint8_t)tmp; USB->RXINTERVAL = (uint8_t)nak_val; USB->RXMAXP = (uint8_t)p_max; tmp = 0; if (flags & ALD_USB_EP_AUTO_CLEAR) tmp |= (uint8_t)USB_RXCSRH_AUTOCLR_MSK; if (flags & ALD_USB_EP_AUTO_REQUEST) tmp |= (uint8_t)USB_RXCSRH_AUTOREQ_MSK; USB->RXCSRH |= (uint8_t)tmp; } } return; } /** * @brief Acknowledge the data in host mode. * @param ep_idx: Index of the endpoint. * @retval None */ void ald_usb_host_ep_data_ack(uint32_t ep_idx) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL &= (uint8_t)(~(USB_CSR0L_RXRDY_MSK)); else USB->RXCSRL &= (uint8_t)(~(USB_RXCSRL_RXRDY_MSK)); return; } /** * @brief Toggle the data in host mode. * The function is used to force the state of the data toggle in host mode. * If the value passed in the bDataToggle parameter is false, then the data * toggle is set to the DATA0 state, and if it is true it is set to the DATA1 * state. * @param ep_idx: Index of the endpoint. * @param toggle: true/false. * @param flags: can be USB_EP_HOST_IN or USB_EP_HOST_OUT. * @retval None */ void ald_usb_host_ep_data_toggle(uint32_t ep_idx, bool toggle, uint32_t flags) { /* not supported by es32f0271. */ return; } /** * @brief Clear the status of endpoint in host mode. * @param ep_idx: Index of the endpoint. * @param flags: Flags. * @retval None */ void ald_usb_host_ep_status_clear(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { USB->CSR0L_TXCSRL &= (uint8_t)(~flags & 0xFF); } else { USB->CSR0L_TXCSRL &= (uint8_t)(~flags & 0xFF); USB->RXCSRL &= (uint8_t)(~(flags >> 16) & 0xFF); } return; } /** * @brief Gets the HUB's address. * @param ep_idx: Index of the endpoint. * @param flags: Flags. * @retval Address */ uint32_t ald_usb_host_hub_addr_get(uint32_t ep_idx, uint32_t flags) { /* not supported by es32f0271. */ return 0; } /** * @brief Sets the HUB's address. * @param ep_idx: Index of the endpoint. * @param addr: HUB's address which will be set. * @param flags: Flags. * @retval Address */ void ald_usb_host_hub_addr_set(uint32_t ep_idx, uint32_t addr, uint32_t flags) { /* not supported by es32f0271. */ return; } /** * @brief Disable power. * @retval None */ void ald_usb_host_pwr_disable(void) { USB->DPDMCON &= (uint8_t)(~(ALD_USB_DPDMCON_PHYPWREN)); return; } /** * @brief Enable power. * @retval None */ void ald_usb_host_pwr_enable(void) { USB->DPDMCON |= (uint8_t)(ALD_USB_DPDMCON_PHYPWREN); return; } /** * @brief Configure power in host mode. * @param flags: Flags * @retval None */ void ald_usb_host_pwr_config(uint32_t flags) { return; } /** * @brief Disable the fault parameters of the power. * @retval None */ void ald_usb_host_pwr_fault_disable(void) { return; } /** * @brief Enable the fault parameters of the power. * @retval None */ void ald_usb_host_pwr_fault_enable(void) { return; } /** * @brief Request data IN(from device to host) * @param ep_idx: Index of the endpoint. * @retval None */ void ald_usb_host_request_in(uint32_t ep_idx) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL |= (uint8_t)USB_CSR0L_REQPKT_MSK; else USB->RXCSRL |= (uint8_t)USB_RXCSRL_REQPKT_MSK; return; } /** * @brief Clear the status of request IN. * @param ep_idx: Index of the endpoint. * @retval None */ void ald_usb_host_request_in_clear(uint32_t ep_idx) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) USB->CSR0L_TXCSRL &= (uint8_t)(~USB_CSR0L_REQPKT_MSK); else USB->RXCSRL &= (uint8_t)(~USB_RXCSRL_REQPKT_MSK); return; } /** * @brief Set the request for a status IN transaction. * @retval None */ void ald_usb_host_request_status(void) { USB->CSR0L_TXCSRL |= (uint8_t)(ALD_USB_CSR0L_REQPKT | ALD_USB_CSR0L_STATUSPKT); return; } /** * @brief Reset the USB's bus. * @param start: true/false. * @retval None */ void ald_usb_host_reset(bool start) { if (start) USB->POWER |= ALD_USB_POWER_RESET; else USB->POWER &= ~(ALD_USB_POWER_RESET); return; } /** * @brief Resume the devices. * @param start: true/false. * @retval None */ void ald_usb_host_resume(bool start) { if (start) USB->POWER |= (uint8_t)USB_POWER_RESUME_MSK; else USB->POWER &= (uint8_t)(~(ALD_USB_POWER_RESUME)); return; } /** * @brief Suspend the devices. * @retval None */ void ald_usb_host_suspend(void) { USB->POWER |= (uint8_t)USB_POWER_SUSPEND_MSK; return; } /** * @brief Gets the device's speed. * @retval Type of the speed. */ uint32_t ald_usb_host_speed_get(void) { if (USB->DEVCON & ALD_USB_DEVCON_FSDEV) return ALD_USB_FULL_SPEED; if (USB->DEVCON & ALD_USB_DEVCON_LSDEV) return ALD_USB_LOW_SPEED; return ALD_USB_UNDEF_SPEED; } /** * @brief Sets the endpoint speed. * @param ep_idx: Index of the endpoint. * @param flags: Type of the speed. * @retval None */ void ald_usb_host_ep_speed_set(uint32_t ep_idx, uint32_t flags) { /* not support in F0271 */ return; } /** * @brief Ping the endpoint. * @param ep_idx: Index of the endpoint. * @param enable: ENABLE/DISABLE. * @retval None */ void ald_usb_host_ep_ping(uint32_t ep_idx, bool enable) { /* not support in F0271 */ return; } /** * @} */ /** @defgroup USB_Public_Functions_Group4 Endpoint functions * @brief Endpoint functions * @{ */ /** * @brief Gets the size of the available data. * @param ep_idx: Index of the endpoint * @retval Size in bytes. */ uint32_t ald_usb_ep_data_avail(uint32_t ep_idx) { USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { if ((USB->CSR0L_TXCSRL & ALD_USB_CSR0L_RXRDY) == 0){ return 0; } return USB->COUNT0_RX1; } else { if ((USB->RXCSRL & ALD_USB_CSR0L_RXRDY) == 0) { return 0; } return (USB->COUNT0_RX1 + (((uint32_t)USB->RXCOUNT2) << 8)); } } /** * @brief Gets the data from FIFO. * @param ep_idx: Index of the endpoint * @param data: Pointer to the buffer. * @param size: Size of the data. * @retval Status. */ int32_t ald_usb_ep_data_get(uint32_t ep_idx, uint8_t *data, uint32_t *size) { uint32_t i, rx_fifo_addr; USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { if ((USB->CSR0L_TXCSRL & ALD_USB_CSR0L_RXRDY) == 0) { *size = 0; return -1; } i = USB->COUNT0_RX1; } else { if ((USB->RXCSRL & ALD_USB_CSR0L_RXRDY) == 0) { *size = 0; return -1; } i = USB->COUNT0_RX1 + (((uint32_t)USB->RXCOUNT2) << 8); } i = (i < *size) ? i : *size; *size = i; rx_fifo_addr = (uint32_t)(&USB->EP0FIFO) + 4 * ep_idx; for (; i > 0; i--) *data++ = *(volatile uint8_t *)(rx_fifo_addr); return 0; } /** * @brief Puts data to the FIFO. * @param ep_idx: Index of the endpoint * @param data: Pointer to the data. * @param size: Size of the data. * @retval Status. */ int32_t ald_usb_ep_data_put(uint32_t ep_idx, uint8_t *data, uint32_t size) { uint32_t tx_fifo_addr; USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { if (USB->CSR0L_TXCSRL & ALD_USB_CSR0L_TXRDY) return -1; } else { if (USB->CSR0L_TXCSRL & ALD_USB_TXCSRL_TXRDY) return -1; } tx_fifo_addr = (uint32_t)(&USB->EP0FIFO) + 4 * ep_idx; for (; size > 0; size--) *(volatile uint8_t *)tx_fifo_addr = *data++; return 0; } /** * @brief Send data. * @param ep_idx: Index of the endpoint * @param tx_type: Type. * @retval Status. */ int32_t ald_usb_ep_data_send(uint32_t ep_idx, uint32_t tx_type) { uint32_t tmp; USB->INDEX = (uint8_t)ep_idx; if (ep_idx == ALD_USB_EP_0) { if (USB->CSR0L_TXCSRL & ALD_USB_CSR0L_TXRDY) return -1; tmp = tx_type & 0xFF; } else { if (USB->CSR0L_TXCSRL & ALD_USB_TXCSRL_TXRDY) return -1; tmp = (tx_type >> 8) & 0xff; } USB->CSR0L_TXCSRL = tmp; return 0; } /** * @brief Clear the status of the toggle. * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval None */ void ald_usb_ep_data_toggle_clear(uint32_t ep_idx, uint32_t flags) { USB->INDEX = (uint8_t)ep_idx; if (flags & (ALD_USB_EP_HOST_OUT | ALD_USB_EP_DEV_IN)) USB->CSR0L_TXCSRL |= (uint8_t)ALD_USB_TXCSRL_CLRDT; else USB->RXCSRL |= (uint8_t)ALD_USB_RXCSRL_CLRDT; return; } /** * @brief Sets the size of request data IN * @param ep_idx: Index of the endpoint * @param count: Size of request data IN. * @retval None */ void ald_usb_ep_req_packet_count(uint32_t ep_idx, uint32_t count) { /* not support in f0271 */ return; } /** * @brief Gets the status of the endpoint. * @param ep_idx: Index of the endpoint * @retval Status. */ uint32_t ald_usb_ep_status(uint32_t ep_idx) { uint32_t status; USB->INDEX = (uint8_t)ep_idx; status = (ep_idx == ALD_USB_EP_0) ? (USB->CSR0L_TXCSRL): (USB->CSR0L_TXCSRL | (USB->RXCSRL << 16)); return status; } /** * @brief Configure the endpoint in DMA mode. * @param ep_idx: Index of the endpoint * @param flag: Flags. * @param en: ENABLE/DISABLE. * @retval None */ void ald_usb_ep_dma_config(uint32_t ep_idx, uint32_t flag, type_func_t en) { /* Not supported in F0271 */ return; } /** * @} */ /** @defgroup USB_Public_Functions_Group5 FIFO functions * @brief FIFO functions * @{ */ /** * @brief Gets the address of the FIFO. * @param ep_idx: Index of the endpoint * @retval Address */ uint32_t ald_usb_fifo_addr_get(uint32_t ep_idx) { /* Not supported in F0271 */ return 0; } /** * @brief Gets the parameters of the FIFO. * @param ep_idx: Index of the endpoint * @param addr: Address. * @param size: Size of FIFO. * @param flags: Flags. * @retval None */ void ald_usb_fifo_config_get(uint32_t ep_idx, uint32_t *addr, uint32_t *size, uint32_t flags) { USB->INDEX = ep_idx; if (flags & (ALD_USB_EP_HOST_OUT | ALD_USB_EP_DEV_IN)) { *addr = ((uint32_t)USB->TXFIFO1 | ((uint32_t)USB->TXFIFO2 & 0x03)) << 3; *size = ((USB->TXFIFO2 & ALD_USB_TXFIFO2_DPB) == 0x00) ? (USB->TXFIFO2 & ALD_USB_TXFIFO2_MAXPKTSIZE_1024) : (2 * (USB->TXFIFO2 & ALD_USB_TXFIFO2_MAXPKTSIZE_1024)); } else { *addr = ((uint32_t)USB->RXFIFO1 | ((uint32_t)USB->RXFIFO2 & 0x03)) << 3; *size = ((USB->RXFIFO2 & ALD_USB_RXFIFO2_DPB) == 0x00) ? (USB->RXFIFO2 & ALD_USB_RXFIFO2_MAXPKTSIZE_1024) : (2 * (USB->RXFIFO2 & ALD_USB_RXFIFO2_MAXPKTSIZE_1024)); } return; } /** * @brief Sets the parameters of the FIFO. * @param ep_idx: Index of the endpoint * @param addr: Address. * @param size: Size of FIFO, valid parameter has defined in usb_lowlayer_api.h. * @param flags: Flags. * @retval None */ void ald_usb_fifo_config_set(uint32_t ep_idx, uint32_t addr, uint32_t size, uint32_t flags) { USB->INDEX = ep_idx; if (flags & (ALD_USB_EP_HOST_OUT | ALD_USB_EP_DEV_IN)) { USB->TXFIFO1 = (uint8_t)((addr >> 3) & 0xFF); USB->TXFIFO2 |= (uint8_t)(((addr >> 3) >> 8) & 0x0F); USB->TXFIFO2 |= (uint8_t)(size << USB_TXFIFO2_MAXPKTSIZE_POSS); USB->CSR0L_TXCSRL |= (uint8_t)ALD_USB_TXCSRL_FLUSH; } else { USB->RXFIFO1 = (uint8_t)((addr >> 3) & 0xFF); USB->RXFIFO2 |= (uint8_t)(((addr >> 3) >> 8) & 0x0F); USB->RXFIFO2 |= (uint8_t)(size << USB_RXFIFO2_MAXPKTSIZE_POSS); USB->RXCSRL |= (uint8_t)ALD_USB_RXCSRL_FLUSH; } return; } /** * @brief Flush the FIFO * @param ep_idx: Index of the endpoint * @param flags: Flags. * @retval None */ void ald_usb_fifo_flush(uint32_t ep_idx, uint32_t flags) { USB->INDEX = ep_idx; if (ep_idx == ALD_USB_EP_0) { if ((USB->CSR0L_TXCSRL & (ALD_USB_CSR0L_RXRDY | ALD_USB_CSR0L_TXRDY)) != 0) USB->CSR0H_TXCSRH |= ALD_USB_CSR0H_FLUSH; } else { if (flags & (ALD_USB_EP_HOST_OUT | ALD_USB_EP_DEV_IN)) { if (USB->CSR0L_TXCSRL & ALD_USB_TXCSRL_TXRDY) USB->CSR0L_TXCSRL |= ALD_USB_TXCSRL_FLUSH; } else { if (USB->RXCSRL & ALD_USB_RXCSRL_RXRDY) USB->RXCSRL |= ALD_USB_RXCSRL_FLUSH; } } return; } /** * @} */ /** @defgroup USB_Public_Functions_Group6 Interrupt functions * @brief Interrupt functions * @{ */ /** * @brief Disable interrupt. * @param flags: Type of the interrupt. * @retval None */ void ald_usb_int_disable(uint32_t flags) { if (flags & ALD_USB_IDR_STATUS) USB->IDR |= (uint8_t)(flags & ALD_USB_IDR_STATUS); return; } /** * @brief Enable interrupt. * @param flags: Type of the interrupt. * @retval None */ void ald_usb_int_enable(uint32_t flags) { if (flags & ALD_USB_IER_STATUS) USB->IER |= (uint8_t)(flags & ALD_USB_IER_STATUS); return; } /** * @brief Gets the status of the interrupt. * @retval Status. */ uint32_t ald_usb_int_status_get(void) { uint32_t Status; Status = USB->IFM & 0x7F; USB->ICR |= Status; return Status; } /** * @brief Disable interrupt of the endpoint. * @param flags: Type of the interrupt. * @retval None */ void ald_usb_int_disable_ep(uint32_t flags) { USB->TXIDR |= (uint8_t)(flags & (ALD_USB_INTEP_HOST_OUT | ALD_USB_INTEP_DEV_IN | ALD_USB_INTEP_0)); USB->RXIDR |= (uint8_t)((flags & (ALD_USB_INTEP_HOST_IN | ALD_USB_INTEP_DEV_OUT)) >> ALD_USB_INTEP_RX_SHIFT); return; } /** * @brief Enable interrupt of the endpoint. * @param flags: Type of the interrupt. * @retval None */ void ald_usb_int_enable_ep(uint32_t flags) { USB->TXIER |= (uint8_t)(flags & (ALD_USB_INTEP_HOST_OUT | ALD_USB_INTEP_DEV_IN | ALD_USB_INTEP_0)); USB->RXIER |= (uint8_t)((flags & (ALD_USB_INTEP_HOST_IN | ALD_USB_INTEP_DEV_OUT)) >> ALD_USB_INTEP_RX_SHIFT); return; } /** * @brief Gets the ststus of the endpoint interrupt. * @retval Status. */ uint32_t ald_usb_int_status_ep_get(void) { uint32_t status; status = USB->TXIFM; status |= (USB->RXIFM << ALD_USB_INTEP_RX_SHIFT); USB->TXICR |= (uint8_t)(status & 0xFF); USB->RXICR |= (uint8_t)((status >> ALD_USB_INTEP_RX_SHIFT) & 0xFF); return status; } /** * @brief Register USB's interrupt. * @retval None */ void ald_usb_int_register(void) { //ald_mcu_irq_config(USB_IRQn, 2, ENABLE); csi_vic_set_prio(USB_IRQn, 3); csi_vic_enable_sirq(USB_IRQn); return; } /** * @brief Unregister USB's interrupt. * @retval None */ void ald_usb_int_unregister(void) { //ald_mcu_irq_config(USB_IRQn, 2, DISABLE); csi_vic_disable_sirq(USB_IRQn); return; } /** * @brief Get USB's interrupt number. * @retval None */ uint32_t ald_usb_int_num_get(void) { return USB_IRQn; } /** * @} */ /** @defgroup USB_Public_Functions_Group7 DMA functions * @brief DMA functions * @{ */ #if defined(__ALD_MDA_H__) /** * @brief Configure DMA's channel. * @param ch: Channel. * @param addr: Address. * @param count: Size of the data to be moved. * @param ctrl: Parameters of the DMA's controler * @retval None */ void ald_usb_dma_channel_config(uint8_t ch, uint32_t addr, uint32_t count, uint32_t ctrl) { return; } /** * @brief Start multiple receive. * @param ep_idx: Index of the endpoint * @retval None */ void ald_usb_dma_mult_recv_start(uint32_t ep_idx) { return; } /** * @brief Start DMA's machine. * @param ch: Channel. * @retval None */ void ald_usb_dma_channel_start(uint8_t ch) { return; } /** * @brief Stop DMA's machine. * @param ch: Channel. * @retval None */ void ald_usb_dma_channel_stop(uint8_t ch) { return; } /** * @brief Gets flags of the interrupt. * @retval Flags of the interrupt. */ uint32_t ald_usb_dma_get_interrupt_flag(void) { return; } /** * @brief Gets the status of the error. * @param ch: Channel. * @retval Status. */ uint32_t ald_usb_dma_get_channel_error(uint8_t ch) { return 0; } /** * @brief Clear the status of the error. * @param ch: Channel. * @retval None */ void ald_usb_dma_clear_channel_error(uint8_t ch) { return; } #endif /** * @} */ /** @defgroup USB_Public_Functions_Group8 LPM functions * @brief LPM functions * @{ */ /** * @brief Gets status of remote wakeup. * @retval Status. */ uint32_t ald_usb_lpm_remote_wake_is_enable(void) { return 1; } /** * @brief Gets the link status * @retval Status */ uint32_t ald_usb_lpm_link_status_get(void) { return 0; } /** * @brief Gets the index of the endpoint. * @retval Index of the endpoint. */ uint32_t ald_usb_lpm_ep_get(void) { return 0; } /** * @brief Gets the status of the interrupt. * @retval Status. */ uint32_t ald_usb_lpm_int_status_get(void) { return 0; } /** * @brief Disable the LPM interrupt. * @retval None */ void ald_usb_lpm_int_disable(uint32_t ints) { return; } /** * @brief Enable the LPM interrupt. * @retval None */ void ald_usb_lpm_int_enable(uint32_t ints) { return; } /** * @brief Transmit a LPM transaction in host mode. * @param addr: Address. * @param ep_idx: Index of the endpoint. * @retval None */ void ald_usb_host_lpm_send(uint32_t addr, uint32_t ep_idx) { return; } /** * @brief Configure the LPM parameters in host mode. * @param resume_time: Resume time. * @param config: Parameters * @retval None */ void ald_usb_host_lpm_config(uint32_t resume_time, uint32_t config) { return; } /** * @brief Initiate a RESUME from the L1 state in host mode. * @retval None */ void ald_usb_host_lpm_resume(void) { return; } /** * @brief Enable remote wakeup in device mode. * @retval None */ void ald_usb_dev_lpm_remote_wake(void) { return; } /** * @brief Enable remote wakeup in device mode. * @retval None */ void ald_usb_dev_lpm_config(uint32_t config) { return; } /** * @brief Enable LPM in device mode. * @retval None */ void ald_usb_dev_lpm_enable(void) { return; } /** * @brief Disable LPM in device mode. * @retval None */ void ald_usb_dev_lpm_disable(void) { return; } /** * @} */ /** @defgroup USB_Public_Functions_Group10 LPM functions * @brief USB SWVBUS control * @{ */ /** * @brief Selet the control mode of VBUS. * @param sigctl: 0, indicates that use the hardware control * sigctl: 1, indicates that use the software control. * @retval Status. */ void ald_usb_swvbus_sigctl_set(uint8_t sigctl) { if (sigctl == 1) { USB->SWVBUS |= 0x01 << 0; } else { USB->SWVBUS &= ~(0x01 << 0); } return; } /** * @brief Selet the control mode of VBUS. * @param None. * @retval Status: 0, indicates that use the hardware control * Status: 1, indicates that use the software control. */ uint8_t ald_usb_swvbus_sigctl_get(void) { return (USB->SWVBUS & (0x01 << 0)); } /** * @brief Set session end threshold. * @param thd: 0, indicates that lower than the session end threshold * thd: 1, indicates that higher than the session end threshold. * @retval Status. */ void ald_usb_swvbus_sesendth_set(uint8_t thd) { if (thd == 1) { USB->SWVBUS |= 0x01 << 1; } else { USB->SWVBUS &= ~(0x01 << 1); } return; } /** * @brief Set session end threshold. * @param None. * @retval Status: 0, indicates that lower than the session end threshold * Status: 1, indicates that higher than the session end threshold. */ uint8_t ald_usb_swvbus_sesendth_get(void) { return (USB->SWVBUS & (0x01 << 1)); } /** * @brief Set session valid threshold. * @param thd: 0, indicates that lower than the session valid threshold thd: 1, indicates that higher than the session valid threshold. * @retval Status. */ void ald_usb_swvbus_sesvalth_set(uint8_t thd) { if (thd == 1) { USB->SWVBUS |= 0x01 << 2; } else { USB->SWVBUS &= ~(0x01 << 2); } return; } /** * @brief Set session valid threshold. * @param None. * @retval Status: 0, indicates that lower than the session valid threshold Status: 1, indicates that higher than the session valid threshold. */ uint8_t ald_usb_swvbus_sesvalth_get(void) { return (USB->SWVBUS & (0x01 << 2)); } /** * @brief Set VBUS valid threshold. * @param thd: 0, indicates that lower than the vbus valid threshold thd: 1, indicates that higher than the vbus valid threshold. * @retval Status. */ void ald_usb_swvbus_valth_set(uint8_t thd) { if (thd == 1) { USB->SWVBUS |= 0x01 << 3; } else { USB->SWVBUS &= ~(0x01 << 3); } return; } /** * @brief Set VBUS valid threshold. * @param None. * @retval Status: 0, indicates that lower than the vbus valid threshold Status:thd: 1, indicates that higher than the vbus valid threshold. */ uint8_t ald_usb_swvbus_valth_get(void) { return (USB->SWVBUS & (0x01 << 3)); } /** * @} */ /** @defgroup USB_Public_Functions_Group11 components initialization functions * @brief USB components initialization * @{ */ /** * @brief Initialize usb host components. * @retval None */ void ald_usb_host_components_init(void) { WRITE_REG(SYSCFG->PROT, 0x55AA6996U); RMU->AHB1RSTR |= 0x40; RMU->AHB1RSTR &= 0xFFFFFFBF; WRITE_REG(SYSCFG->PROT, 0x0); /* Config EP0 */ ald_usb_host_ep_config(ALD_USB_EP_0, 64, 0, 0, (ALD_USB_EP_MODE_CTRL | ALD_USB_EP_SPEED_FULL | ALD_USB_EP_HOST_OUT)); /* Clear interrupts */ /* Enable PHY power */ ald_usb_host_pwr_enable(); /* clear hnp session */ ald_usb_otg_session_request(false); /* set vbus control mode and threshold value */ ald_usb_swvbus_sigctl_set(1); ald_usb_swvbus_sesendth_set(1); ald_usb_swvbus_sesvalth_set(1); ald_usb_swvbus_valth_set(1); /* Pull down DP and DM */ ald_usb_dppud_set(ALD_USB_DPDM_PUSH_DOWN); ald_usb_dmpud_set(ALD_USB_DPDM_PUSH_DOWN); /* software control CID */ ald_usb_swcid_cidctrl(1); /* force to host mode */ ald_usb_swcid_host(0); /* start host request */ ald_usb_mode_host_req(); /* Start hnp */ ald_usb_otg_session_request(true); /* Clear interrupts */ ald_usb_int_status_get(); /* Init interrupts */ ald_usb_int_enable(ALD_USB_INTCTRL_SESSION | ALD_USB_INTCTRL_DISCONNECT | ALD_USB_INTCTRL_CONNECT | ALD_USB_INTCTRL_SOF | ALD_USB_INTCTRL_BABBLE | ALD_USB_INTCTRL_RESUME); ald_usb_int_enable_ep(ALD_USB_INTEP_ALL); ald_usb_int_register(); return; } /** * @brief Initialize usb device components. * @retval None */ void ald_usb_device_components_init(void) { ald_usb_otg_session_request(true); #if (defined(ES32VF2264)) ald_usb_dppud_set(ALD_USB_DPDM_FLOATING);/*测试板的USBDP(PA12),上拉到3.3V。具体情况请参考ReadMe.txt*/ #else ald_usb_dppud_set(USB_DPDM_PUSH_UP); #endif /* ES32VF2264 */ /* software control CID */ ald_usb_swcid_cidctrl(1); /* force to dev mode */ ald_usb_swcid_host(1); ald_usb_dev_suspend_enable(); return; } /** * @} */ /** * @} */ #endif /* ALD_USB */ /** * @} */ /** * @} */