📄 usb_driver.c
字号:
/******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2005 Freescale Semiconductor, Inc.
* (c) Copyright 2001-2004 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
***************************************************************************//*!
*
* @file usb_driver.c
*
* @author B01119
*
* @version 1.0.3.0
*
* @date Sep-8-2008
*
* @brief USB Module Driver for HC08 MCUs
*
*******************************************************************************
*
*
*
******************************************************************************/
#include <hidef.h> /* for EnableInterrupts macro */
#include <MC68HC908JW32.h> /* include peripheral declarations */
#include "usb.h" /* USB Header file */
#include "usb_periph_cfg.h"
#include "usb_driver.h"
//-------------------------------------------------------------------
// Local Variables
//-------------------------------------------------------------------
#pragma DATA_SEG SHORT _DATA_ZEROPAGE
static volatile uchar* pSrc0;
static volatile uchar* pDst0;
static volatile uchar cntSrc0;
static volatile uchar cntDst0;
static volatile uchar* pSrc1;
static volatile uchar* pDst1;
static volatile uchar cntSrc1;
static volatile uchar cntDst1;
static volatile uchar* pSrc2;
static volatile uchar* pDst2;
static volatile uchar cntSrc2;
static volatile uchar cntDst2;
static volatile uchar* pSrc3;
static volatile uchar* pDst3;
static volatile uchar cntSrc3;
static volatile uchar cntDst3;
static volatile uchar* pSrc4;
static volatile uchar* pDst4;
static volatile uchar cntSrc4;
static volatile uchar cntDst4;
volatile uchar usbStatus;
#pragma DATA_SEG DEFAULT
uchar ep0BufSh[8];
//-------------------------------------------------------------------
// USB line initialization (needs to be done asap after chip reset)
//
// Description:
// - Enable D+ pullup resistor and 3.3V regulator & USB RESET
//-------------------------------------------------------------------
void USB_Init(void)
{
// Set/reset the 3V3 voltage regulator and USB reset
#ifndef USB_3V3REGULATOR_DIS
#define USB_3V3REGULATOR_DIS 0
#endif
#ifndef USB_CHIP_RESET_DIS
#define USB_CHIP_RESET_DIS 0
#endif
#ifndef USB_PULLUP_ENA
#define USB_PULLUP_ENA 0x00
#endif
CONFIG2 |= (USB_3V3REGULATOR_DIS | USB_CHIP_RESET_DIS);
// Enable D+ pullup
#if USB_PULLUP_ENA==0x01
POCR2 |= POCR2_DPPULLEN_MASK;
#endif
}
//-------------------------------------------------------------------
// USB module Enable (shall be done right before interrupt enable)
//
// Description:
// - wait for D+ line to go high (out of USB reset state), if USB chip reset enabled
// - Enable 4 Data Endpoint
// - 16 byte endpoint data buffer
//-------------------------------------------------------------------
void USB_Enable(void)
{
// If the USB reset is set as MCU reset we should avoid the
// multiple chip resetting while long RESET signalling
#if USB_CHIP_RESET_DIS == 0
// Wait for RESET signal on USB D+ line (logic 0)
while (!PTE_PTE2)
{
USB_DO_NOTHING();
__RESET_WATCHDOG();
}
#endif
// Assign the End Points to the interfaces
UINTFCR = UINTFCR_INI;
// Endpoints settings
// Clear EP0 Status Register
UEP0CSR = 0;
// Set EP1 - EP4 base addresses
UEP12BPR = UEP12BPR_INI;
UEP34BPR = UEP34BPR_INI;
// initialise all used EP
#if EP1_MODE
UEP1CSR = UEP1CSR_INI;
#if EP1_DIR & EP_DIR_IN
cntDst1 = EP1_BUFFER_SIZE;
cntSrc1 = 0;
pDst1 = EP1_BASE_ADR;
#else
cntDst1 = 0;
cntSrc1 = 0;
#endif
#endif
#if EP2_MODE
UEP2CSR = UEP2CSR_INI;
#if EP2_DIR & EP_DIR_IN
cntDst2 = EP2_BUFFER_SIZE;
cntSrc2 = 0;
pDst2 = EP2_BASE_ADR;
#else
cntDst2 = 0;
cntSrc2 = 0;
#endif
#endif
#if EP3_MODE
UEP3CSR = UEP3CSR_INI;
#if EP3_DIR & EP_DIR_IN
cntDst3 = EP3_BUFFER_SIZE;
cntSrc3 = 0;
pDst3 = EP3_BASE_ADR;
#else
cntDst3 = 0;
cntSrc3 = 0;
#endif
#endif
#if EP4_MODE
UEP4CSR = UEP4CSR_INI;
#if EP4_DIR & EP_DIR_IN
cntDst4 = EP4_BUFFER_SIZE;
cntSrc4 = 0;
pDst4 = EP4_BASE_ADR;
#else
cntDst4 = 0;
cntSrc4 = 0;
#endif
#endif
USBSR = 0; // Clear Status Register
#ifndef USB_SETUPIE_ENA
#define USB_SETUPIE_ENA 0
#endif
#ifndef USB_SOFIE_ENA
#define USB_SOFIE_ENA 0
#endif
#ifndef USB_CONFIGCHGIE_ENA
#define USB_CONFIGCHGIE_ENA 0
#endif
#ifndef USB_USBRSTIE_ENA
#define USB_USBRSTIE_ENA 0
#endif
#ifndef USB_RESUMEFIE_ENA
#define USB_RESUMEFIE_ENA 0
#endif
#ifndef USB_SUSPNDIE_ENA
#define USB_SUSPNDIE_ENA 0
#endif
USIMR = (USB_SUSPNDIE_ENA?USIMR_SUSPNDIE_MASK:0)|\
(USB_RESUMEFIE_ENA?USIMR_RESUMEFIE_MASK:0)|\
(USB_USBRSTIE_ENA?USIMR_USBRSTIE_MASK:0)|\
(USB_CONFIGCHGIE_ENA?USIMR_CONFIG_CHGIE_MASK:0)|\
(USB_SOFIE_ENA?USIMR_SOFIE_MASK:0)|\
(USB_SETUPIE_ENA?USIMR_SETUPIE_MASK:0);
USBCR = USBCR_USBCLKEN_MASK|USBCR_USBEN_MASK|USBCR_TFC0IE_MASK|\
(EP1_MODE?USBCR_TFC1IE_MASK:0)|\
(EP2_MODE?USBCR_TFC2IE_MASK:0)|\
(EP3_MODE?USBCR_TFC3IE_MASK:0)|\
(EP4_MODE?USBCR_TFC4IE_MASK:0);
}
//---------------------------------------------------------------------------------------
// USB line deinitialization
//---------------------------------------------------------------------------------------
void USB_Deinit(void)
{
// Disable D+ pullup
POCR2 &= ~POCR2_DPPULLEN_MASK;
}
//---------------------------------------------------------------------------------------
// USB module Disable
//---------------------------------------------------------------------------------------
void USB_Disable(void)
{
// Disable USB Module
USBCR = 0;
}
//---------------------------------------------------------------------------------------
// uchar USB_TxBuff0(uchar* adr, uchar cnt)
//---------------------------------------------------------------------------------------
uchar USB_TxBuff0(uchar* adr, uchar cnt)
{
pDst0 = EP0_BASE_ADR;
cntDst0 = EP0_BUFFER_SIZE;
pSrc0 = adr;
cntSrc0 = cnt;
while(cntDst0 && cntSrc0)
{
cntDst0--;
cntSrc0--;
*pDst0++ = *pSrc0++;
}
if(cntDst0 == 0)
usbStatus |= CTRL_READ_STATE;
// Set DVALID_IN flag and data length, others bits leave unchanged
UEP0CSR = (EP0_BUFFER_SIZE - cntDst0)<<4 | (UEP0CSR_DVALID_IN_MASK | UEP0CSR_TFRC_IN_MASK | UEP0CSR_TFRC_OUT_MASK | UEP0CSR_DVALID_OUT_MASK);
return(cntSrc0);
}
//---------------------------------------------------------------------------------------
// void USB_RxBuff0(uchar* adr, uchar cnt)
//---------------------------------------------------------------------------------------
void USB_RxBuff0(uchar* adr, uchar cnt)
{
pDst0 = adr;
cntDst0 = cnt;
usbStatus |= CTRL_WRITE_STATE;
}
//---------------------------------------------------------------------------------------
// uchar USB_RxBuff1(uchar* adr, uchar cnt) - used for OUT bulk/interrupt packet
// NON BLOCKING function. Set user buffer address and number of bytes to be
// received. If there are any available data these will be copied intermidiately.
// The rest of the user buffer is filled during interrupt service routine.
// Function returns number of pending bytes in user buffer.
//---------------------------------------------------------------------------------------
uchar USB_RxBuff1(uchar* adr, uchar cnt)
{
// Set address where to copy received data
pDst1 = adr;
// How many bytes to be copied
cntDst1 = cnt;
// If there are any data available, copy them intermidiately
while(cntSrc1 && cntDst1)
{
cntSrc1--;
cntDst1--;
*pDst1++ = *pSrc1++;
}
// If all the received bytes are copied to the user buffer, enable to receive next OUT packet
if(cntSrc1 == 0)
UEP1CSR &= ~UEP1CSR_DVALID_MASK;
// Return number of pending data in user buffer
return(cntDst1);
}
//---------------------------------------------------------------------------------------
// uchar USB_RxChar1(void)
// BLOCKING function - wait till RxBuffPending and there are any received data in EP buffer
// then read one byte from EP buffer and return it.
//---------------------------------------------------------------------------------------
uchar USB_RxChar1(void)
{
uchar retVal;
// Wait until user buffer pending
while(cntDst1)
USB_DO_NOTHING();
// Wait while data in EP buffer available
while(!(cntSrc1))
USB_DO_NOTHING();
retVal = *pSrc1++;
// If no more data in EP buffer, enable another packet receive
if(!(--cntSrc1))
UEP1CSR &= ~UEP1CSR_DVALID_MASK;
// Return received data
return(retVal);
}
//---------------------------------------------------------------------------------------
// uchar USB_RxBuffPending1(void)
// returns number of bytes pending to be received to user buffer
//---------------------------------------------------------------------------------------
uchar USB_RxBuffPending1(void)
{
return(cntDst1);
}
//---------------------------------------------------------------------------------------
// uchar USB_GetRxReady1(void)
// return number of available data bytes in EP buffer
//---------------------------------------------------------------------------------------
uchar USB_GetRxReady1(void)
{
return(cntSrc1);
}
//---------------------------------------------------------------------------------------
// uchar USB_GetTxEmpty1(void)
// returns number of available bytes in EP buffer (to be write)
//---------------------------------------------------------------------------------------
uchar USB_GetTxEmpty1(void)
{
if(UEP1CSR_DVALID) // if transmit is pending
return(0); // return zero
else
return(cntDst1); // else return free space in transmit buffer
}
//---------------------------------------------------------------------------------------
// uchar USB_TxChar1(uchar ch) - used for IN bulk/interrupt packet
// BLOCKING function - waits till user Tx buffer is pending and
// EP buffer has free place. Then write character to EP buffer. When EP buffer
// is full, flushes this packet.
// Function returns number of available bytes in EP buffer
//---------------------------------------------------------------------------------------
#pragma MESSAGE DISABLE C1853
uchar USB_TxChar1(uchar ch)
{
uchar retVal;
// wait pending buffer
while(cntSrc1)
USB_DO_NOTHING();
// wait while EP buffer not sent
while(UEP1CSR_DVALID)
USB_DO_NOTHING();
// write character to buffer
*pDst1++ = ch;
cntDst1--;
retVal = cntDst1;
// if EP buffer is full, flush it
if(retVal == 0)
{
UEP1DSR = EP1_BUFFER_SIZE;
UEP1CSR |= UEP1CSR_DVALID_MASK;
}
return(retVal);
}
#pragma MESSAGE DEFAULT C1853
//---------------------------------------------------------------------------------------
// uchar USB_TxBuff1(uchar* adr, uchar cnt) user for IN interrupt/bulk packet
// NON BLOCKING function - function copy data from user buffer to EP
// buffer. If user buffer is larger then EP buffer the rest of data is send in interrupt
// service routine. Function returns number of bytes pending in user buffer
//---------------------------------------------------------------------------------------
#pragma MESSAGE DISABLE C1853
uchar USB_TxBuff1(uchar* adr, uchar cnt)
{
uchar retVal;
// set address of buffer where the data to be send are placed
pSrc1 = adr;
// set number of bytes to send
cntSrc1 = cnt;
// copy data from user buffer to EP buffer
while(cntSrc1 && cntDst1)
{
cntSrc1--;
cntDst1--;
*pDst1++ = *pSrc1++;
}
retVal = cntSrc1;
// flush it
UEP1DSR = EP1_BUFFER_SIZE - cntDst1;
UEP1CSR |= UEP1CSR_DVALID_MASK;
// return number of bytes pending in user buffer
return(retVal);
}
#pragma MESSAGE DEFAULT C1853
//---------------------------------------------------------------------------------------
// uchar USB_TxBuffPending1(void)
// function returns number of bytes pending in user buffer
//---------------------------------------------------------------------------------------
uchar USB_TxBuffPending1(void)
{
return(cntSrc1);
}
//---------------------------------------------------------------------------------------
// uchar USB_TxFlush1(void)
// if there is at least one byte to be send in EP buffer, flush buffer
// Function returns number of send bytes
//---------------------------------------------------------------------------------------
#pragma MESSAGE DISABLE C1853
uchar USB_TxFlush1(void)
{
UEP1DSR = EP1_BUFFER_SIZE - cntDst1;
UEP1CSR |= UEP1CSR_DVALID_MASK;
return(UEP1DSR);
}
#pragma MESSAGE DEFAULT C1853
//---------------------------------------------------------------------------------------
// uchar USB_RxBuff2(uchar* adr, uchar cnt) - used for OUT bulk/interrupt packet
// NON BLOCKING function. Set user buffer address and number of bytes to be
// received. If there are any available data these will be copied intermidiately.
// The rest of the user buffer is filled during interrupt service routine.
// Function returns number of pending bytes in user buffer.
//---------------------------------------------------------------------------------------
uchar USB_RxBuff2(uchar* adr, uchar cnt)
{
// set address where to copy received data
pDst2 = adr;
// how many bytes to be copied
cntDst2 = cnt;
// if there are any data available, copy them intermidiately
while(cntSrc2 && cntDst2)
{
cntSrc2--;
cntDst2--;
*pDst2++ = *pSrc2++;
}
// if all received bytes are copied to user buffe, enable to receive next OUT packet
if(cntSrc2 == 0)
UEP2CSR &= ~UEP2CSR_DVALID_MASK;
// return number of pending data in user buffer
return(cntDst2);
}
//---------------------------------------------------------------------------------------
// uchar USB_RxChar2(void)
// BLOCKING function - wait till RxBuffPending and there are any received data in EP buffer
// then read one byte from EP buffer and return it.
//---------------------------------------------------------------------------------------
uchar USB_RxChar2(void)
{
uchar retVal;
// wait until buffer pending
while(cntDst2)
USB_DO_NOTHING();
// wait while data in EP buffer aviable
while(!(cntSrc2))
USB_DO_NOTHING();
retVal = *pSrc2++;
// if no more data in EP buffer, enalble another packet receive
if(!(--cntSrc2))
UEP2CSR &= ~UEP2CSR_DVALID_MASK;
// return data
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -