stm 32 의 USB 학습 노트 에 대한 USBHW.c
#include
#include
#include "usbreg.h"
#include "usbuser.h"
#include "usbcore.h"
#include "usb_hw.h"
#define _DEBUG_
#include "debug.h"
#define USB_EP_NUM 4
/*
*
* ,USB
* USB , Offset
* 2
* 0 1
* EP_BUF_ADDR
*/
#define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*USB_EP_NUM)
/*USB , */
EP_BUF_DSCR * pBUF_DSCR = (EP_BUF_DSCR *) USB_PMA_ADDR;
/*
* USB */
WORD FreeBufAddr;
/* : USB
* :
* :
*/
void USB_Init(void)
{
printf(" USB_Init, \r
");
// USB
RCC->APB1ENR |= (1<<23);
// USB
/* USB 20, NVIC——IPRX
* , 20/4=5 ,
* 20 */
NVIC->IPR[5] |=0x10;
NVIC->ISER[0]|=(1<<20);
}
/* : USB
* :
* :
*/
/* , ^-^*/
/* :
*USB ( 20): USB ( ,USB ).
*USB ( 19): , .
*USB ( 42): USB . OTG_FS_WKUP
*
* rm0008 21.4.2
*/
void USB_Reset(void)
{
PrintS("USB_Reset\r
");
/* , , !*/
ISTR=0;
/* CNTR stm32 USB
* USB ( 20)
* , !
*/
CNTR= CNTR_CTRM | //
CNTR_RESETM | //
CNTR_SUSPM | //
CNTR_WKUPM ; //
FreeBufAddr = EP_BUF_ADDR; // FreeBuff ( ),
BTABLE = 0x00; //
/* 0 */
pBUF_DSCR->ADDR_TX = FreeBufAddr;
FreeBufAddr+=8; // 0 8 , 8
pBUF_DSCR->ADDR_RX = FreeBufAddr;
FreeBufAddr+=8;
/* count_Rx 10~14bit
* 15bit
*0---2byte
*1---1byte
* 8 ,bit15 0, ((8<<10)>>1) 8<<9;
* count_Rx
*/
pBUF_DSCR->COUNT_RX= 8 << 9;
/* 0 ,
*
*/
EPxREG(0) = EP_CONTROL | EP_RX_VALID;
/* USB , USB 0, */
DADDR = DADDR_EF | 0;
}
/* :
* :
* EPNum:bit3~bit0 ---->
* EPNum:bit7 ---->
*
* :
*/
/* DATA0*/
void EP_Reset(DWORD EPNum)
{
DWORD num,var;
PrintS("EP_Reset\r
");
/* , */
num = EPNum & 0x0F;
var = EPxREG(num);
/* bit7 1 toggle 0,
* toggle 0
* data0
*/
if(EPNum & 0x80)
EPxREG(num) = var & (EP_MASK | EP_DTOG_TX);/* */
else
EPxREG(num) = var & (EP_MASK | EP_DTOG_RX);/* */
}
/* : USB
* :true --> USB
* false--> USB
* :
*/
void USB_Connect(BOOL turnon)
{
/* , USB =
* , */
printf(" USB \r
");
/* USB */
CNTR = CNTR_FRES;
// printf("test1\r
");
/* , */
ISTR=0;
// printf("test2\r
");
if(turnon)
{
// printf("test3\r
");
/* GPIOA, PA.8 , USB
* D+ 1.5K , USB
* USB
*/
RCC->APB2ENR |= (1 << 2); /* enable clock for GPIOA */
GPIOA->CRH &= ~(0x0f << 0 * 4); /* clear port PA8 */
GPIOA->CRH |= (0x03 << 0 * 4); /* PA6 General purpose output open-drain, max speed 50 MHz */
GPIOA->BRR = ( 1 << 8 ); /* reset PA8 (set to low) */
/* , : USB
* CNTR_RESETM
* 0 USB
* , ^_^!*/
CNTR = CNTR_RESETM; /* ,*/
}
else
CNTR = CNTR_FRES | CNTR_PDWN ;/* */
}
/* :
* :EPnum --->
* stat --->
* :
*/
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR * pEPD)
{
DWORD num,val;
//
num = pEPD->bEndpointAddress & 0xf;
val = pEPD->wMaxPacketSize;
// IN
if(pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK)
{
// pBUF_DSCR ,
(pBUF_DSCR + num)->ADDR_TX = FreeBufAddr;
/* 2 , , 1023
* USB_COUNTn_TX bit0~bit9
*/
val = (val + 1)& ~1;
}
//
else
{
(pBUF_DSCR + num)->ADDR_RX = FreeBufAddr;
/* USB_COUNTn_RX bit10~bit14, BLSIZE=0( 2 ), 0~62
* 62, BLSIZE=1( 32 )
*/
if(val > 62 )
{
// 32, 32
val = (val +31)&~31;
/* , rm0008,21,5.3
*(val >> 5)<<10 == val <<5
*/
(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_INTERRUPT:
val = EP_INTERRUPT;
break;
default:
printf(" , \r
");
break;
}
val |= num;
//
EPxREG(num) = val;
}
/* :
* :EPnum --->
* stat --->
* :
*/
void EP_Status(DWORD EPNum,DWORD stat)
{
DWORD num,var;
/* */
num = EPNum & 0x0f;
var = EPxREG(num);
/* , 1 , */
if(EPNum & 0x80) //
EPxREG(num)=(var ^ (stat & EP_STAT_TX)) & (EP_MASK | EP_STAT_TX);
else //
EPxREG(num)=(var ^ (stat & EP_STAT_RX)) & (EP_MASK | EP_STAT_RX);
}
/* :
* :EPNum bit0~bit3
bit7
* :
*/
void USB_ResetEP(DWORD EPNum)
{
EP_Reset(EPNum);
}
/* : stall
* :EPNum bit0~bit3
bit7
* :
*/
void USB_SetStallEP(DWORD EPNum)
{
EP_Status(EPNum,EP_TX_STALL | EP_RX_STALL);
}
/* : enable
* :EPNum bit0~bit3
bit7
* :
*/
void USB_EnableEP(DWORD EPNum)
{
EP_Status(EPNum,EP_TX_VALID | EP_RX_VALID);
}
/* : disable
* :EPNum bit0~bit3
bit7
* :
*/
void USB_DisableEP(DWORD EPNum)
{
EP_Status(EPNum,EP_TX_DIS | EP_RX_DIS);
}
/* : stall
* :EPNum bit0~bit3
bit7
* :
*/
void USB_ClrStallEP(DWORD EPNum)
{
EP_Status(EPNum,EP_TX_VALID | EP_RX_VALID);
}
/* : USB
* :addr
* :
*/
void USB_SetAddress(DWORD addr)
{
//DADDR 1 USB
DADDR = DADDR_EF | addr;
}
/* :
* :EPnum --->
* pData --->
* ,
* :
*/
DWORD USB_ReadEP(DWORD EPnum,BYTE * pData)
{
DWORD num,cnt,*pv,n;
//
num = EPnum & 0xf;
//
pv=(DWORD *)(USB_PMA_ADDR + 2* ((pBUF_DSCR + num)->ADDR_RX));
//COUNT_RX 10
cnt=(pBUF_DSCR + num)->COUNT_RX & EP_COUNT_MASK;
for(n=0;n
* pData --->
* cnt --->
* :
*/
DWORD USB_WriteEP(DWORD EPNum , BYTE * pData,DWORD cnt)
{
DWORD num,*pv,n;
num = EPNum & 0x0f;
pv=(DWORD *)(USB_PMA_ADDR + 2*((pBUF_DSCR+num)->ADDR_TX));
/* , bug*/
for(n=0;nCOUNT_TX=cnt;
EP_Status(EPNum,EP_TX_VALID);
return cnt;
}
/* :USB
* :
* :
*/
void USB_Suspend(void)
{
GPIOE->BSRR |=1 ; /* Turn Off Suspend LED */
printf(" \r
");
//
CNTR |= CNTR_FSUSP;
//
CNTR |= CNTR_LPMODE;
}
/* :USB
* :
* :
*/
void USB_WakeUp(void)
{
GPIOE->BRR |=1 ; /* Turn On Suspend LED */
printf(" \r
");
// ,
CNTR &= ~CNTR_FSUSP;
//USB ,
//CNTR &= ~CNTR_LPMODE;
}
/* :USB
* :
* :
*/
void USB_LP_CAN_RX0_IRQHandler(void)
{
DWORD istr;
DWORD num,var;
istr=ISTR; //
/*USB */
if(istr & ISTR_RESET)
{
//
USB_Reset();
// USB
USB_ResetCore();
ISTR = ~ISTR_RESET; /* , */
}
/*USB */
/* if(istr &
********************************************************************
*/
if (istr & ISTR_SUSP) {
USB_Suspend();
ISTR = ~ISTR_SUSP;
}
/* USB Wakeup */
if (istr & ISTR_WKUP) {
USB_WakeUp();
ISTR = ~ISTR_WKUP;
}
//******************************************************************
/* */
while((istr = ISTR) & ISTR_CTR)
{
//
ISTR = ~ISTR_CTR;
//
num=istr & ISTR_EP_ID;
//
var = EPxREG(num);
//
if(var & EP_CTR_RX )
{
// 0
// printf(" :");
// printhex((u8)num);
EPxREG(num) = var & ~EP_CTR_RX & EP_MASK;
//
if(USB_P_EP[num])
{
// , USG_EVT_SETUP
if(var & EP_SETUP)
USB_P_EP[num](USB_EVT_SETUP);
else
//
USB_P_EP[num](USB_EVT_OUT);
}
}
//
if(var & EP_CTR_TX)
{
//
EPxREG(num) = var & ~EP_CTR_TX & EP_MASK;
//
if(USB_P_EP[num])
{
//USB
USB_P_EP[num](USB_EVT_IN);
}
}
}
}
잘못 이 있 으 면 지적 해 주세요!!