rt-thread/bsp/essemi/es32vf2264/libraries/ALD/ES32VF2264/Source/ald_usb.c

1666 lines
36 KiB
C
Raw Normal View History

/**
*********************************************************************************
*
* @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 */
/**
* @}
*/
/**
* @}
*/