⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbn960x.c

📁 TI公司的CCS一些常用的函数库
💻 C
📖 第 1 页 / 共 4 页
字号:
/////////////////////////////////////////////////////////////////////////
////                      usbn960x.c                                 ////
////                                                                 ////
////    National USBN960x Hardware layer for CCS's PIC USB driver.   ////
////                                                                 ////
//// This file is part of CCS's PIC USB driver code, which includes: ////
////   usb_desc.h - an example set of config and device descriptors  ////
////   usb.c - USB token and request handler code                    ////
////   usb.h - definitions, prototypes and global variables          ////
////                                                                 ////
//// ex_usb_scope.c, an example written specifically for the         ////
//// USBN960x, shows how to use the CCS PIC USB driver with the      ////
//// USBN960x.                                                       ////
////                                                                 ////
//// usbn960x.c is the hardware layer level driver for the CCS PIC   ////
//// USB driver.  You can replace usbn960x.c with another hardware   ////
//// layer level and still use the other parts of the PIC USB        ////
//// driver.  ex_usb_hid.c shows an example of using the Microchip   ////
//// PIC16C765 (a PIC with a Slow speed USB Peripheral).             ////
////                                                                 ////
//// This example USB peripheral layer was written and tested with   ////
//// CCS's USB Full Speed demo board.  When using your own design,   ////
//// either wire your USB960x the same as our demo board or change   ////
//// the port and pin definitions below.                             ////
////                                                                 ////
////   *************************  NOTE  **************************   ////
//// This driver uses INT_EXT.  It requires INT_EXT to interrupt the ////
//// PIC when an event has happened on the USBN960x.  Because of     ////
//// this code enables interrupts.  A user modification can be made  ////
//// to poll the USBN960x device instead of relying on an interrupt. ////
////                                                                 ////
////    **********************  FUNCTIONS  ***********************   ////
////                                                                 ////
//// usb_init() - Initializes the USB code and USBN960x device.      ////
////              NOTE - this enables interrupts.                    ////
////                                                                 ////
//// usb_isr() - Call this if you choose to poll instead of          ////
////             interrupt.  READ THE COMMENTS AT USB_ISR() FIRST.   ////
////                                                                 ////
//// usb_put_packet() - Sends one packet to the host.                ////
////                    If you need to send a message that spans     ////
////                    more than one packet then see usb_puts() in  ////
////                    usb.c                                        ////
////                                                                 ////
//// usbn_get_version() - Returns the revision number of the 960x    ////
////                                                                 ////
//// For more documentation on these functions read the comments at  ////
//// each function.                                                  ////
////                                                                 ////
//// The other functions defined in this file are for use by the     ////
//// USB code, and is not meant to be used by the user.              ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////                                                                 ////
//// Version History:                                                ////
////                                                                 ////
//// October 27th, 2003: RX/TX - IN/OUT Backwards                    ////
////                             in usb_set_configured()             ////
////                                                                 ////
//// June 18th, 2003: Fixed a problem where PIC would miss interrupt ////
////                                                                 ////
//// May 6th, 2003: Fixed a potential read/write to registers        ////
////                                                                 ////
//// August 2nd, 2002: Initial Public Release                        ////
////                                                                 ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2002 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////


#IFNDEF __USB_HARDWARE__
#DEFINE __USB_HARDWARE__

#include <usb.h>

#define __USBN__ 1   //let other parts of the code know that we are running a National USB Part

#define USB_MAX_ENDPOINTS 4 //number of bidrectional endpoints.  960x has 1 control port and 6 individual endpoints = 4 bidrectional endpoints

//CCS USB demo board is connected to the USBN960x in this manner:
#ifndef usbn_out
   #define  usbn_bus_out(x)      output_d(x)
   #define  usbn_bus_in          input_d
   #define  usbn_bus_float()     set_tris_d(0xFF)
   #define  usbn_bus_control()   set_tris_d(0)
#endif

//CCS USB demo board is connected to the USBN960x in this manner:
#ifndef  USBN_CS
   #define  USBN_INT       PIN_B0   //leave at B0 if you want to use external interrupt
   #define  USBN_RS        PIN_C1   //reset
   #define  USBN_CS        PIN_C2
   #define  USBN_RD        PIN_C3
   #define  USBN_WR        PIN_C4
   #define  USBN_A0        PIN_C5
#endif

#if defined(__PCM__)
 #bit int_ext_flag=0x0B.1
#elif defined(__PCH__)
 #bit int_ext_flag=0xFF2.1
#endif

//usbn9603/9604 register set
#define     USBN_MCNTRL    0x00
#define     USBN_CCONF     0x01
//          reserved       0x02
#define     USBN_RID       0x03
#define     USBN_FAR       0x04
#define     USBN_NFSR      0x05
#define     USBN_MAEV      0x06
#define     USBN_MAMSK     0x07
#define     USBN_ALTEV     0x08
#define     USBN_ALTMSK    0x09
#define     USBN_TXEV      0x0A
#define     USBN_TXMSK     0x0B
#define     USBN_RXEV      0x0C
#define     USBN_RXMSK     0x0D
#define     USBN_NAKEV     0x0E
#define     USBN_NAKMSK    0x0F
#define     USBN_FWEV      0x10
#define     USBN_FWMSK     0x11
#define     USBN_FNH       0x12
#define     USBN_FNL       0x13
#define     USBN_DMACNTRL  0x14
#define     USBN_DMAEV     0x15
#define     USBN_DMAMSK    0x16
#define     USBN_MIR       0x17
#define     USBN_DMACNT    0x18
#define     USBN_DMAERR    0x19
//          reserved       0x1A
#define     USBN_WKUP      0x1B
//          reserved       0x1C
//          reserved       0x1D
//          reserved       0x1E
//          reserved       0x1F
#define     USBN_EPC0      0x20
#define     USBN_TXD0      0x21
#define     USBN_TXS0      0x22
#define     USBN_TXC0      0x23
//          reserved       0x24
#define     USBN_RXD0      0x25
#define     USBN_RXS0      0x26
#define     USBN_RXC0      0x27
#define     USBN_EPC1      0x28
#define     USBN_TXD1      0x29
#define     USBN_TXS1      0x2A
#define     USBN_TXC1      0x2B
#define     USBN_EPC2      0x2C
#define     USBN_RXD1      0x2D
#define     USBN_RXS1      0x2E
#define     USBN_RXC1      0x2F
#define     USBN_EPC3      0x30
#define     USBN_TXD2      0x31
#define     USBN_TXS2      0x32
#define     USBN_TXC2      0x33
#define     USBN_EPC4      0x34
#define     USBN_RXD2      0x35
#define     USBN_RXS2      0x36
#define     USBN_RXC2      0x37
#define     USBN_EPC5      0x38
#define     USBN_TXD3      0x39
#define     USBN_TXS3      0x3A
#define     USBN_TXC3      0x3B
#define     USBN_EPC6      0x3C
#define     USBN_RXD3      0x3D
#define     USBN_RXS3      0x3E
#define     USBN_RXC3      0x3F

//max packet size of all endpoints, but not EP0
#define  USB_MAX_PACKET_LENGTH   64

//CCS turns on the following interrupts:
#ifndef USBN_ALTMSK_ENABLES
   #define USBN_ALTMSK_ENABLES   0xC0
#endif
#ifndef USBN_TXMSK_ENABLES
   #define USBN_TXMSK_ENABLES    0xFF  //interrupt on any change on TX interrupt (IN packet or OVR)
#endif
#ifndef USBN_RXMSK_ENABLES
   #define USBN_RXMSK_ENABLES    0xFF  //interrupt on any change on RX interrupt (OUT/SETUP packet or OVR)
#endif
#ifndef USBN_NAKMSK_ENABLES
   #define USBN_NAKMSK_ENABLES   0x10  //interrupt only on NAK on EP0 OUT/SETUP packets.
#endif
#ifndef USBN_FWMSK_ENABLES
   #define USBN_FWMSK_ENABLES    0x00  //dont interrupt at all for frame events
#endif
#ifndef USBN_MAMSK_ENABLES
   #define USBN_MAMSK_ENABLES    0xD6  //interrupt on ALT, NAK, TX and RX events
#endif

int8  usbn_current_alt_mask;  //we will modify what ALT masks depending if we are idle or not

//NFSR STATES
#define     USBN_NFSR_RESET        0
#define     USBN_NFSR_RESUME       1
#define     USBN_NFSR_OPERATIONAL  2
#define     USBN_NFSR_SUSPEND      3

//***************************************************************************************
//* YOU CAN USE THE FOLLOWING 2 CONSTANT ARRAYS TO DEFINE DIFFERENT ENPDOINT MAPPINGS
//*
//* But the way it is setup now is that EPC1 and EPC2 make up USB Endpoint 1,
//* EPC3 and EPC4 make up USB Endpoint 2, and EPC5 and EPC6 make up USB Endpoint 3.
//* EPC0 is always Endpoint 0 (control) and can't be modified.
//* Probably best to leave this way, unless for some reason you need a different
//* endpoint, say you're developing an application that needs to communicate to Endpoint 15.
//****************************************************************************************
//960x has 6 unidrectional endpoint.  this maps bidirectional endpoint[1] to 960x EPC1 and EPC2
//when we see IN for EP1 then we know to look at EPC2 and it's respective FIFO buffer
//directions are respective of HOST
const int8 usb_epc_out_address[USB_MAX_ENDPOINTS]={0,1,2,3};  //epc0=0,epc2=1,epc4=2,epc6=3
const int8 usb_epc_in_address[USB_MAX_ENDPOINTS]={0,1,2,3}; //epc0=0,epc1=1,epc3=2,epc5=3
const int8 epc_to_epadd[]={0,1,1,2,2,3,3};

// *** protoypes of user functions
void usb_init(void);
int8 usbn_get_version(void);

// *** prototypes used by usb.c (token handling)
void usb_stall_ep(int8 endpoint, int1 direction);
void usb_unstall_ep(int8 endpoint, int1 direction);
int1 usb_endpoint_stalled(int8 endpoint, int1 direction);
void usb_set_address(int8 address);
void usb_set_configured(int config);
int8 usb_get_packet(int8 endpoint, int8 * ptr, int8 max);
int1 usb_put_packet(int endpoint, int * ptr, int len, PID_TOGGLE tgl);
#inline
void usb_wrongstate();

// *** prototypes (USB ISR)
void usb_isr(void);
void usb_check_warn(void);
void usb_check_alt(void);
void usb_check_alt_reset(void);
void usb_check_txev(void);
void usb_check_frame(void);
void usb_check_nak(void);
void usb_check_uld(void);
void usb_check_rxev(void);

// *** prototype of USBN960x specific functions used only in this file
void usb_reset(void);
void usb_enable_endpoint(int8 endpoint, int1 direction, int1 iso);
void usb_disable_endpoint(int8 endpoint, int1 direction);
void usbn_write(int8 address, int8 data);
int8 usbn_read(int8 address);
int8 usb_find_epc(int8 endpoint, int1 direction);
void usb_clear_ep0_buffer(void);

//DONT CHANGE THE FOLLOWING 3 CONSTANT ARRAYS
const char USBN_EPCx[]={USBN_EPC0,USBN_EPC1,USBN_EPC2,USBN_EPC3,USBN_EPC4,USBN_EPC5,USBN_EPC6}; //epc_address[x] finds the constant USBN_EPCx
const char USBN_TX_FIFOx[]={USBN_TXD0, USBN_TXD1, 0,         USBN_TXD2, 0,         USBN_TXD3, 0};          //ecp0,ecp1,ecp3,ecp5 have tx_fifos
const char USBN_RX_FIFOx[]={USBN_RXD0, 0,         USBN_RXD1, 0,         USBN_RXD2, 0,         USBN_RXD3};  //ecp0,ecp2,ecp4,ecp6 have rx_fifos


/// BEGIN User Functions

/*******************************************************************************
/* usb_init()
/*
/* Summary: Resets and initalizes USB code and USBN device.  You must call this
/*          first before using code.
/*          If you have debug enabled it will enable TBE interrupts on the PIC.
/*
/*          NOTE: this enables interrupts.
/*
/********************************************************************************/
void usb_init(void) {
   output_high(USBN_CS);
   output_float(USBN_A0);
   output_high(USBN_RD);
   output_high(USBN_WR);
   usbn_bus_float();

   output_high(USBN_RS);
   delay_ms(100);
   output_low(USBN_RS);
   delay_ms(10);
   output_high(USBN_RS);
   delay_ms(10);

   usbn_current_alt_mask=USBN_ALTMSK_ENABLES & 0x7F;  //make sure resume is off

   //turn on masks
   usbn_write(USBN_ALTMSK, usbn_current_alt_mask);
   usbn_write(USBN_TXMSK, USBN_TXMSK_ENABLES);
   usbn_write(USBN_RXMSK, USBN_RXMSK_ENABLES);

   usbn_write(USBN_NAKMSK, USBN_NAKMSK_ENABLES);
   usbn_write(USBN_FWMSK, USBN_FWMSK_ENABLES);
   usbn_write(USBN_MAMSK, USBN_MAMSK_ENABLES);

   usbn_write(USBN_EPC0, 0);
   usbn_write(USBN_FAR, 0x80);

   usbn_write(USBN_WKUP,0x0C);

   usbn_write(0x1F,0x40);             //3.3V regulator workaround

   usb_reset();
   delay_ms(10);

   ext_int_edge(H_TO_L);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);

   #IF USB_DO_DEBUG
      enable_interrupts(INT_TBE);
   #ENDIF

   usbn_write(USBN_MCNTRL, 0x04); //vge
   delay_ms(2);
   usbn_write(USBN_MCNTRL, 0xCC); //VGE, NAT, active low
}

/*******************************************************************************
/* usb_put_packet(endpoint,*ptr,len,toggle)
/*
/* Input: endpoint - endpoint to send packet to
/*        ptr - points to data to send
/*        len - amount of data to send
/*        toggle - whether to send data with a DATA0 pid, a DATA1 pid, or toggle from the last DATAx pid.
/*
/* Output: TRUE if data was sent correctly, FALSE if it was not.  It will return FALSE if you gave it
/*         an invalid endpoint, or because TX buffer is still busy sending last packet.  If TX buffer
/*         is still busy sending the last packet then you can keep calling usb_put_packet() until it returns
/*         TRUE.
/*
/* Summary: Sends a packet out the EP to the host.  Notice that there is a difference
/*          between a packet and a message.  If you wanted to send a 512 byte message you
/*          would accomplish this by sending 8 64-byte packets, followed by a 0 length packet.
/*          If the last (or only packet) being sent is less than the max packet size defined
/*          in your descriptor then you do not need to send a 0 length packet to identify an end of message.
/*
/*          usb_puts() (provided in usb.c) will send a multi-packet message correctly.
/*
/********************************************************************************/
int1 usb_put_packet(int endpoint, int * ptr, int len, PID_TOGGLE tgl) {
   int8 epc, address, status, tcount;
   int8 i;

   debug(debug_txb,"\r\nTX %X %X: ",endpoint,len);

   if (endpoint < 16) {
      epc=usb_find_epc(endpoint,1);

      if (epc != 0xFF) {
         address=USBN_TX_FIFOx[epc];  //address = USBN_TXDx
         address+=2; //TXCx
         status=usbn_read(address); //TXCx
         if ((!bit_test(status,1))||(!endpoint)) { //make sure last isnt set


            status |= 0x08;
            usbn_write(address,status); //FLUSH
            i=0;
            do {
               i++;
               status=usbn_read(address);
            } while ((bit_test(status,3))&&(i!=0)); //wait until flush is clear
            address-=2;

            if (i==0) {debug_txb('!');}

            status=usbn_read(address+1); //TXSx
            tcount=status & 0x1F;   //find open space on fifo buffer
            if (tcount==0) {
               debug(debug_txb,"BF ");
               return(0);
            }
            else {
               while (len != 0) {
                  debug(debug_txb,"%X ",*ptr);
                  usbn_write(address, *ptr);
                  ptr++;
                  len--;
               }
               debug_txb(' ');
               if (!endpoint) {  //if endpoint 0 we need to disable rx_en on RXC0
                  status=usbn_read(USBN_RXC0);
                  status &= 0xFE;
                  usbn_write(USBN_RXC0, status);       //disable RC_EN
               }
               status=usbn_read(address+2);  //TXCx

               if (endpoint) {status |= 0x02;}         //set LAST bit
               if (tgl==1) {status ^= 0x04;}   //toggle TOGGLE bit (TOGGLE DATAx)
               else if (tgl==0) {status |= 0x04;}  //set toggle (DATA1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -