mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
314 lines
7.7 KiB
C
314 lines
7.7 KiB
C
/*
|
|
* Copyright 2021 MindMotion Microelectronics Co., Ltd.
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "hal_usb.h"
|
|
|
|
|
|
void USB_SetBufDespTableAddr(USB_Type * USBx, uint32_t addr)
|
|
{
|
|
USBx->FSBDTPAGE1 = USB_FSBDTPAGE1_BDTBA(addr >> 9u);
|
|
USBx->FSBDTPAGE2 = USB_FSBDTPAGE2_BDTBA(addr >> 16u);
|
|
USBx->FSBDTPAGE3 = USB_FSBDTPAGE3_BDTBA(addr >> 24u);
|
|
}
|
|
|
|
void USB_InitDevice(USB_Type * USBx, USB_Device_Init_Type *init)
|
|
{
|
|
if ( (uintptr_t)(init->BufDespTable_Addr) % 512u != 0u)
|
|
{
|
|
return;
|
|
}
|
|
USB_SetDeviceAddr(USBx, 0x00u);
|
|
USB_SetBufDespTableAddr(USBx, init->BufDespTable_Addr);
|
|
USB_Enable(USBx, true);
|
|
}
|
|
|
|
void USB_EnableInterrupts(USB_Type * USBx, uint32_t interrupts, bool enable)
|
|
{
|
|
if(enable)
|
|
{
|
|
USBx->FSINTENB |= interrupts;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSINTENB &= ~interrupts;
|
|
}
|
|
}
|
|
|
|
uint32_t USB_GetEnabledInterrupts(USB_Type * USBx)
|
|
{
|
|
return USBx->FSINTENB;
|
|
}
|
|
|
|
uint32_t USB_GetInterruptStatus(USB_Type * USBx)
|
|
{
|
|
uint32_t stat = USBx->FSINTSTAT;
|
|
uint32_t enb = USBx->FSINTENB;
|
|
return stat & enb;
|
|
}
|
|
|
|
void USB_ClearInterruptStatus(USB_Type * USBx, uint32_t interrupts)
|
|
{
|
|
uint32_t enb = USBx->FSINTENB;
|
|
USBx->FSINTSTAT = interrupts & enb;
|
|
}
|
|
|
|
void USB_EnableErrInterrupts(USB_Type * USBx, uint32_t interrupts, bool enable)
|
|
{
|
|
if(enable)
|
|
{
|
|
USBx->FSERRENB |= interrupts;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSERRENB &= ~interrupts;
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t USB_GetEnabledErrInterrupts(USB_Type * USBx)
|
|
{
|
|
return USBx->FSERRENB;
|
|
}
|
|
|
|
uint32_t USB_GetErrInterruptStatus(USB_Type * USBx)
|
|
{
|
|
uint32_t stat = USBx->FSERRSTAT;
|
|
uint32_t enb = USBx->FSERRENB;
|
|
USBx->FSERRSTAT = stat & ~enb;
|
|
return stat & enb;
|
|
}
|
|
|
|
void USB_ClearErrInterruptStatus(USB_Type * USBx, uint32_t interrupts)
|
|
{
|
|
uint32_t enb = USBx->FSERRENB;
|
|
USBx->FSERRSTAT = interrupts & enb;
|
|
}
|
|
|
|
uint32_t USB_GetBufDespIndex(USB_Type * USBx)
|
|
{
|
|
return (USBx->FSSTAT)>>2;
|
|
}
|
|
|
|
void USB_Enable(USB_Type * USBx, bool enable)
|
|
{
|
|
if(enable)
|
|
{
|
|
USBx->FSCTL |= USB_FSCTL_USBEN_MASK;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSCTL &= ~USB_FSCTL_USBEN_MASK;
|
|
}
|
|
}
|
|
|
|
void USB_EnableOddEvenReset(USB_Type * USBx, bool enable)
|
|
{
|
|
if(enable)
|
|
{
|
|
USBx->FSCTL |= USB_FSCTL_ODDRST_MASK;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSCTL &= ~USB_FSCTL_ODDRST_MASK;
|
|
}
|
|
}
|
|
|
|
void USB_EnableResumeSignal(USB_Type * USBx, bool enable)
|
|
{
|
|
if(enable)
|
|
{
|
|
USBx->FSCTL |= USB_FSCTL_RESUME_MASK;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSCTL &= ~USB_FSCTL_RESUME_MASK;
|
|
}
|
|
}
|
|
|
|
void USB_EnableSuspend(USB_Type * USBx, bool enable)
|
|
{
|
|
if(true == enable)
|
|
{
|
|
USBx->FSCTL |= USB_FSCTL_TXDSUSPENDTOKENBUSY_MASK;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSCTL &= ~USB_FSCTL_TXDSUSPENDTOKENBUSY_MASK;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void USB_SetDeviceAddr(USB_Type * USBx, uint8_t addr)
|
|
{
|
|
USBx->FSADDR = ( (USBx->FSADDR & ~USB_FSADDR_ADDR_MASK)
|
|
| (addr & USB_FSADDR_ADDR_MASK) )
|
|
;
|
|
}
|
|
|
|
uint8_t USB_GetDeviceAddr(USB_Type * USBx)
|
|
{
|
|
return USBx->FSADDR & USB_FSADDR_ADDR_MASK;
|
|
}
|
|
|
|
uint32_t USB_GetBufDespTableAddr(USB_Type * USBx)
|
|
{
|
|
return (uint32_t)
|
|
( ( (USBx->FSBDTPAGE1 >> USB_FSBDTPAGE1_BDTBA_SHIFT) << 9u )
|
|
| ( (USBx->FSBDTPAGE2 >> USB_FSBDTPAGE2_BDTBA_SHIFT) << 16u)
|
|
| ( (USBx->FSBDTPAGE3 >> USB_FSBDTPAGE3_BDTBA_SHIFT) << 24u)
|
|
);
|
|
}
|
|
|
|
uint32_t USB_GetFrameNumber(USB_Type * USBx)
|
|
{
|
|
return (USBx->FSFRMNUML) | (USBx->FSFRMNUML << 7u);
|
|
}
|
|
|
|
USB_BufDesp_Type * USB_GetBufDesp(USB_Type * USBx)
|
|
{
|
|
USB_BufDespTable_Type *bdt = (USB_BufDespTable_Type *)USB_GetBufDespTableAddr(USBx);
|
|
return &bdt->Index[USBx->FSSTAT >> 2];
|
|
}
|
|
|
|
USB_TokenPid_Type USB_BufDesp_GetTokenPid(USB_BufDesp_Type * bd)
|
|
{
|
|
return (USB_TokenPid_Type)bd->TOK_PID;
|
|
}
|
|
|
|
uint32_t USB_BufDesp_GetPacketAddr(USB_BufDesp_Type * bd)
|
|
{
|
|
return bd->ADDR;
|
|
}
|
|
|
|
uint32_t USB_BufDesp_GetPacketSize(USB_BufDesp_Type * bd)
|
|
{
|
|
return bd->BC;
|
|
}
|
|
|
|
void USB_BufDesp_Reset(USB_BufDesp_Type * bd)
|
|
{
|
|
bd->BDT_STALL = 0u;
|
|
bd->NINC = 0u;
|
|
bd->KEEP = 0u;
|
|
bd->DTS = 1u;
|
|
}
|
|
|
|
uint32_t USB_GetEndPointIndex(USB_Type * USBx)
|
|
{
|
|
return (USBx->FSSTAT & USB_FSSTAT_ENDP_MASK) >> USB_FSSTAT_ENDP_SHIFT;
|
|
}
|
|
|
|
USB_Direction_Type USB_GetXferDirection(USB_Type * USBx)
|
|
{
|
|
return (USB_Direction_Type)( (USBx->FSSTAT & USB_FSSTAT_TX_MASK) >> USB_FSSTAT_TX_SHIFT);
|
|
}
|
|
|
|
USB_BufDesp_OddEven_Type USB_GetBufDespOddEven(USB_Type * USBx)
|
|
{
|
|
return (USB_BufDesp_OddEven_Type)( (USBx->FSSTAT & USB_FSSTAT_ODD_MASK) >> USB_FSSTAT_ODD_SHIFT );
|
|
}
|
|
|
|
bool USB_BufDesp_Xfer(USB_BufDesp_Type * bd, uint32_t data_n, uint8_t * buffer, uint32_t len)
|
|
{
|
|
if (1u == bd->OWN)
|
|
{
|
|
return false;
|
|
}
|
|
bd->ADDR = (uint32_t)buffer;
|
|
bd->DATA = data_n;
|
|
bd->BC = len;
|
|
bd->OWN = 1u;
|
|
return true;
|
|
}
|
|
|
|
bool USB_BufDesp_IsBusy(USB_BufDesp_Type * bd)
|
|
{
|
|
if (1u == bd->OWN)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void USB_EnableEndPoint(USB_Type * USBx, uint32_t index, USB_EndPointMode_Type mode, bool enable)
|
|
{
|
|
if (false == enable)
|
|
{
|
|
USBx->FSEPCTL[index] = 0u;
|
|
USB_BufDespTable_Type * bdt = (USB_BufDespTable_Type * )USB_GetBufDespTableAddr(USBx);
|
|
bdt->Table[index][0u][0u].HEAD = 0u;
|
|
bdt->Table[index][0u][1u].HEAD = 0u;
|
|
bdt->Table[index][1u][0u].HEAD = 0u;
|
|
bdt->Table[index][1u][1u].HEAD = 0u;
|
|
return;
|
|
}
|
|
if (USB_EndPointMode_Control == mode)
|
|
{
|
|
USBx->FSEPCTL[index] |= USB_FSEPCTL_EPCTLDISEPRXENEPTXEN(3) | USB_FSEPCTL_EPHSHK_MASK;
|
|
}
|
|
else if (USB_EndPointMode_Bulk == mode)
|
|
{
|
|
USBx->FSEPCTL[index] |= USB_FSEPCTL_EPCTLDISEPRXENEPTXEN(7u) | USB_FSEPCTL_EPHSHK_MASK;
|
|
}
|
|
else if (USB_EndPointMode_Interrupt == mode)
|
|
{
|
|
USBx->FSEPCTL[index] |= USB_FSEPCTL_EPCTLDISEPRXENEPTXEN(7u) | USB_FSEPCTL_EPHSHK_MASK;
|
|
}
|
|
else if (USB_EndPointMode_Isochronous == mode)
|
|
{
|
|
USBx->FSEPCTL[index] |= USB_FSEPCTL_EPCTLDISEPRXENEPTXEN(7u);
|
|
}
|
|
}
|
|
|
|
void USB_EnableEndPointStall(USB_Type * USBx, uint32_t index, bool enable)
|
|
{
|
|
USB_BufDespTable_Type * bdt = (USB_BufDespTable_Type * )USB_GetBufDespTableAddr(USBx);
|
|
for (uint32_t i = 0; i < USB_BDT_EP_NUM; i++)
|
|
{
|
|
if (true == enable)
|
|
{
|
|
USBx->FSEPCTL[i] |= USB_FSEPCTL_EPSTALL_MASK;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_IN ].BDT_STALL = 1u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_OUT].BDT_STALL = 1u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_IN ].BDT_STALL = 1u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_OUT].BDT_STALL = 1u;
|
|
}
|
|
else
|
|
{
|
|
USBx->FSEPCTL[i] &= ~USB_FSEPCTL_EPSTALL_MASK;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_IN ].BDT_STALL = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_IN ].OWN = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_OUT].BDT_STALL = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Odd ][USB_Direction_OUT].OWN = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_IN ].BDT_STALL = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_IN ].OWN = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_OUT].BDT_STALL = 0u;
|
|
bdt->Table[i][USB_BufDesp_OddEven_Even][USB_Direction_OUT].OWN = 0u;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t USB_GetEnabledEndPointStall(USB_Type * USBx)
|
|
{
|
|
uint32_t status = 0u;
|
|
for(uint32_t i = 0u; i < USB_BDT_EP_NUM; i++)
|
|
{
|
|
if (0 != (USBx->FSEPCTL[i] & USB_FSEPCTL_EPSTALL_MASK) )
|
|
{
|
|
status |= 1u << i;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/* EOF. */
|
|
|