A modified DAPLink firmware (from JiXin) for STM32F103C6T6
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

630 lines
13 KiB

/*----------------------------------------------------------------------------
* RL-ARM - USB
*----------------------------------------------------------------------------
* Name: usbd_STM32F103.c
* Purpose: Hardware Layer module for ST STM32F103
* Rev.: V4.70
*----------------------------------------------------------------------------
* This code is part of the RealView Run-Time Library.
* Copyright (c) 2004-2013 KEIL - An ARM Company. All rights reserved.
*---------------------------------------------------------------------------*/
/* Double Buffering is not yet supported */
#define __STM32
#include <RTL.h>
#include <rl_usb.h>
#include "usbreg.h"
#include <stm32f10x.h>
#include "DAP_config.h"
#define __NO_USB_LIB_C
#include "usb_config.c"
#define USB_DBL_BUF_EP 0x0000
#define EP_BUF_ADDR (sizeof(EP_BUF_DSCR) * (USBD_EP_NUM + 1)) /* Endpoint Buf Adr */
// Ptr to EP Buf Desc
EP_BUF_DSCR *pBUF_DSCR = (EP_BUF_DSCR *)USB_PMA_ADDR;
// Endpoint Free Buffer Address
U16 FreeBufAddr;
/**
* @brief Reset Endpoint
* @params EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* @return None
*/
void EP_Reset (U32 EPNum)
{
U32 num, val;
num = EPNum & 0x0F;
val = EPxREG(num);
if (EPNum & 0x80)
{ // IN Endpoint
EPxREG(num) = val & (EP_MASK | EP_DTOG_TX);
}
else
{ // OUT Endpoint
EPxREG(num) = val & (EP_MASK | EP_DTOG_RX);
}
}
/**
* @brief Set Endpoint Status
* @perems EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* stat: New Status
* @return None
*/
void EP_Status (U32 EPNum, U32 stat)
{
U32 num, val;
num = EPNum & 0x0F;
val = EPxREG(num);
if (EPNum & 0x80)
{ /* IN Endpoint */
EPxREG(num) = (val ^ (stat & EP_STAT_TX)) & (EP_MASK | EP_STAT_TX);
}
else
{ /* OUT Endpoint */
EPxREG(num) = (val ^ (stat & EP_STAT_RX)) & (EP_MASK | EP_STAT_RX);
}
}
/**
* @brief USB Device Interrupt enable
* Called by USBD_Init to enable the USB Interrupt
* @return None
*/
#ifdef __RTX
void __svc(1) USBD_IntrEna (void);
void __SVC_1 (void)
{
#else
void USBD_IntrEna (void)
{
#endif
NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
}
/**
* @brief USB Device Initialize Function
* Called by the User to initialize USB
* @return None
*/
void USBD_Init (void)
{
RCC->APB1ENR |= RCC_APB1ENR_USBEN;
USBD_IntrEna (); /* Enable USB Interrupts */
PORT_USB_CONNECT_SETUP();
}
/*
* USB Device Connect Function
* Called by the User to Connect/Disconnect USB Device
* Parameters: con: Connect/Disconnect
* Return Value: None
*/
void USBD_Connect (BOOL con)
{
if (con)
{
CNTR = CNTR_FRES; /* Force USB Reset */
CNTR = 0;
ISTR = 0; /* Clear Interrupt Status */
CNTR = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; /* USB Interrupt Mask */
PIN_USB_CONNECT_ON();
}
else
{
CNTR = CNTR_FRES | CNTR_PDWN; /* Switch Off USB Device */
PIN_USB_CONNECT_OFF();
}
}
/*
* USB Device Reset Function
* Called automatically on USB Device Reset
* Return Value: None
*/
void USBD_Reset (void)
{
/* Double Buffering is not yet supported */
ISTR = 0; /* Clear Interrupt Status */
CNTR = CNTR_CTRM | CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM
#ifdef __RTX
| ((USBD_RTX_DevTask != 0) ? CNTR_ERRM : 0)
| ((USBD_RTX_DevTask != 0) ? CNTR_PMAOVRM : 0)
| ((USBD_RTX_DevTask != 0) ? CNTR_SOFM : 0)
| ((USBD_RTX_DevTask != 0) ? CNTR_ESOFM : 0);
#else
| ((USBD_P_Error_Event != 0) ? CNTR_ERRM : 0)
| ((USBD_P_Error_Event != 0) ? CNTR_PMAOVRM : 0)
| ((USBD_P_SOF_Event != 0) ? CNTR_SOFM : 0)
| ((USBD_P_SOF_Event != 0) ? CNTR_ESOFM : 0);
#endif
FreeBufAddr = EP_BUF_ADDR;
BTABLE = 0x00; /* set BTABLE Address */
/* Setup Control Endpoint 0 */
pBUF_DSCR->ADDR_TX = FreeBufAddr;
FreeBufAddr += USBD_MAX_PACKET0;
pBUF_DSCR->ADDR_RX = FreeBufAddr;
FreeBufAddr += USBD_MAX_PACKET0;
if (USBD_MAX_PACKET0 > 62)
{
pBUF_DSCR->COUNT_RX = ((USBD_MAX_PACKET0 << 5) - 1) | 0x8000;
}
else
{
pBUF_DSCR->COUNT_RX = USBD_MAX_PACKET0 << 9;
}
EPxREG(0) = EP_CONTROL | EP_RX_VALID;
DADDR = DADDR_EF | 0; /* Enable USB Default Address */
}
/*
* USB Device Suspend Function
* Called automatically on USB Device Suspend
* Return Value: None
*/
void USBD_Suspend (void)
{
CNTR |= CNTR_FSUSP; /* Force Suspend */
CNTR |= CNTR_LPMODE; /* Low Power Mode */
}
/*
* USB Device Resume Function
* Called automatically on USB Device Resume
* Return Value: None
*/
void USBD_Resume (void)
{
/* Performed by Hardware */
}
/*
* USB Device Remote Wakeup Function
* Called automatically on USB Device Remote Wakeup
* Return Value: None
*/
void USBD_WakeUp (void)
{
CNTR &= ~CNTR_FSUSP; /* Clear Suspend */
}
/*
* USB Device Remote Wakeup Configuration Function
* Parameters: cfg: Device Enable/Disable
* Return Value: None
*/
void USBD_WakeUpCfg (BOOL cfg)
{
/* Not needed */
}
/*
* USB Device Set Address Function
* Parameters: adr: USB Device Address
* setup: Called in setup stage (!=0), else after status stage
* Return Value: None
*/
void USBD_SetAddress (U32 adr, U32 setup)
{
if (setup)
return;
DADDR = DADDR_EF | adr;
}
/*
* USB Device Configure Function
* Parameters: cfg: Device Configure/Deconfigure
* Return Value: None
*/
void USBD_Configure (BOOL cfg)
{
if (cfg == __FALSE)
{
FreeBufAddr = EP_BUF_ADDR;
FreeBufAddr += 2 * USBD_MAX_PACKET0; /* reset Buffer address */
}
}
/*
* Configure USB Device Endpoint according to Descriptor
* Parameters: pEPD: Pointer to Device Endpoint Descriptor
* Return Value: None
*/
void USBD_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD)
{
/* Double Buffering is not yet supported */
U32 num, val;
num = pEPD->bEndpointAddress & 0x0F;
val = pEPD->wMaxPacketSize;
if (pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK)
{
(pBUF_DSCR + num)->ADDR_TX = FreeBufAddr;
val = (val + 1) & ~1;
}
else
{
(pBUF_DSCR + num)->ADDR_RX = FreeBufAddr;
if (val > 62)
{
val = (val + 31) & ~31;
(pBUF_DSCR + num)->COUNT_RX = ((val << 5) - 1) | 0x8000;
}
else
{
val = (val + 1) & ~1;
(pBUF_DSCR + num)->COUNT_RX = val << 9;
}
}
FreeBufAddr += val;
switch (pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK)
{
case USB_ENDPOINT_TYPE_CONTROL:
val = EP_CONTROL;
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
val = EP_ISOCHRONOUS;
break;
case USB_ENDPOINT_TYPE_BULK:
val = EP_BULK;
if (USB_DBL_BUF_EP & (1 << num))
{
val |= EP_KIND;
}
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
val = EP_INTERRUPT;
break;
}
val |= num;
EPxREG(num) = val;
}
/*
* Set Direction for USB Device Control Endpoint
* Parameters: dir: Out (dir == 0), In (dir <> 0)
* Return Value: None
*/
void USBD_DirCtrlEP (U32 dir)
{
/* Not needed */
}
/*
* Enable USB Device Endpoint
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_EnableEP (U32 EPNum)
{
EP_Status(EPNum, EP_TX_NAK | EP_RX_VALID); /* EP is able to receive */
}
/*
* Disable USB Endpoint
* Parameters: EPNum: Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_DisableEP (U32 EPNum)
{
EP_Status(EPNum, EP_TX_DIS | EP_RX_DIS);
}
/*
* Reset USB Device Endpoint
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_ResetEP (U32 EPNum)
{
EP_Reset(EPNum);
}
/*
* Set Stall for USB Device Endpoint
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_SetStallEP (U32 EPNum)
{
EP_Status(EPNum, EP_TX_STALL | EP_RX_STALL);
}
/*
* Clear Stall for USB Device Endpoint
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_ClrStallEP (U32 EPNum)
{
EP_Reset(EPNum); /* reset DTog Bits */
EP_Status(EPNum, EP_TX_VALID | EP_RX_VALID);
}
/*
* Clear USB Device Endpoint Buffer
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* Return Value: None
*/
void USBD_ClearEPBuf (U32 EPNum)
{
;
}
/*
* Read USB Device Endpoint Data
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* pData: Pointer to Data Buffer
* Return Value: Number of bytes read
*/
U32 USBD_ReadEP (U32 EPNum, U8 *pData)
{
/* Double Buffering is not yet supported */
U32 num, cnt, *pv, n;
num = EPNum & 0x0F;
pv = (U32 *)(USB_PMA_ADDR + 2 * ((pBUF_DSCR + num)->ADDR_RX));
cnt = (pBUF_DSCR + num)->COUNT_RX & EP_COUNT_MASK;
for (n = 0; n < (cnt + 1) / 2; n++)
{
*((__packed U16 *)pData) = *pv++;
pData += 2;
}
EP_Status(EPNum, EP_RX_VALID);
return (cnt);
}
/*
* Write USB Device Endpoint Data
* Parameters: EPNum: Device Endpoint Number
* EPNum.0..3: Address
* EPNum.7: Dir
* pData: Pointer to Data Buffer
* cnt: Number of bytes to write
* Return Value: Number of bytes written
*/
U32 USBD_WriteEP (U32 EPNum, U8 *pData, U32 cnt)
{
/* Double Buffering is not yet supported */
U32 num, *pv, n;
U16 statusEP;
num = EPNum & 0x0F;
pv = (U32 *)(USB_PMA_ADDR + 2 * ((pBUF_DSCR + num)->ADDR_TX));
for (n = 0; n < (cnt + 1) / 2; n++)
{
*pv++ = *((__packed U16 *)pData);
pData += 2;
}
(pBUF_DSCR + num)->COUNT_TX = cnt;
statusEP = EPxREG(num);
if ((statusEP & EP_STAT_TX) != EP_TX_STALL)
{ /* do not make EP valid if stalled */
EP_Status(EPNum, EP_TX_VALID);
}
return (cnt);
}
/*
* Get USB Device Last Frame Number
* Parameters: None
* Return Value: Frame Number
*/
U32 USBD_GetFrame (void)
{
return (FNR & FNR_FN);
}
#ifdef __RTX
U32 LastError; /* Last Error */
/*
* Get USB Last Error Code
* Parameters: None
* Return Value: Error Code
*/
U32 USBD_GetError (void)
{
return (LastError);
}
#endif
/*
* USB Device Interrupt Service Routine
*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
U32 istr, num, val;
istr = ISTR;
if (istr & ISTR_RESET)
{ /* USB Reset Request */
USBD_Reset();
usbd_reset_core();
#ifdef __RTX
if (USBD_RTX_DevTask)
{
isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
}
#else
if (USBD_P_Reset_Event)
{
USBD_P_Reset_Event();
}
#endif
ISTR = ~ISTR_RESET;
}
if (istr & ISTR_SUSP)
{ /* USB Suspend Request */
USBD_Suspend();
#ifdef __RTX
if (USBD_RTX_DevTask)
{
isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
}
#else
if (USBD_P_Suspend_Event)
{
USBD_P_Suspend_Event();
}
#endif
ISTR = ~ISTR_SUSP;
}
if (istr & ISTR_WKUP)
{ /* USB Wakeup */
USBD_WakeUp();
#ifdef __RTX
if (USBD_RTX_DevTask)
{
isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
}
#else
if (USBD_P_Resume_Event)
{
USBD_P_Resume_Event();
}
#endif
ISTR = ~ISTR_WKUP;
}
if (istr & ISTR_SOF)
{ /* Start of Frame */
#ifdef __RTX
if (USBD_RTX_DevTask)
{
isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
}
#else
if (USBD_P_SOF_Event)
{
USBD_P_SOF_Event();
}
#endif
ISTR = ~ISTR_SOF;
}
if (istr & ISTR_PMAOVR)
{
#ifdef __RTX
LastError = 2;
if (USBD_RTX_DevTask)
{ /* PMA Over/underrun */
isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask);
}
#else
if (USBD_P_Error_Event)
{
USBD_P_Error_Event(2);
}
#endif
ISTR = ~ISTR_PMAOVR;
}
if (istr & ISTR_ERR)
{ /* Error: No Answer, CRC Error, Bit Stuff Error, Frame Format Error */
#ifdef __RTX
LastError = 1;
if (USBD_RTX_DevTask)
{
isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask);
}
#else
if (USBD_P_Error_Event)
{
USBD_P_Error_Event(1);
}
#endif
ISTR = ~ISTR_ERR;
}
while ((istr = ISTR) & ISTR_CTR)
{ /* Endpoint Interrupts */
ISTR = ~ISTR_CTR;
num = istr & ISTR_EP_ID;
val = EPxREG(num);
if (val & EP_CTR_RX)
{
EPxREG(num) = val & ~EP_CTR_RX & EP_MASK;
#ifdef __RTX
if (USBD_RTX_EPTask[num])
{
isr_evt_set((val & EP_SETUP) ? USBD_EVT_SETUP : USBD_EVT_OUT, USBD_RTX_EPTask[num]);
}
#else
if (USBD_P_EP[num])
{
USBD_P_EP[num]((val & EP_SETUP) ? USBD_EVT_SETUP : USBD_EVT_OUT);
}
#endif
}
if (val & EP_CTR_TX)
{
EPxREG(num) = val & ~EP_CTR_TX & EP_MASK;
#ifdef __RTX
if (USBD_RTX_EPTask[num])
{
isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[num]);
}
#else
if (USBD_P_EP[num])
{
USBD_P_EP[num](USBD_EVT_IN);
}
#endif
}
}
}