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

📄 usb.c

📁 Freescale的S08BDM开发工具制作资料
💻 C
📖 第 1 页 / 共 2 页
字号:
  }
}

/* EP2 Tx */
void USB_ep2_tx(void) {
  UCR2_TX2E=0;      /* disable EP2 transmitter */
  UIR2_TXD2FR = 1;  /* clear the interrupt flag to make sure the packet transmits */
  if (usb_ep2_dcntT==0) return; /* no data to transmit - return without enabling the transmitter */
  /* transmit data from the buffer (must be in Zero Page) */
  UE2D0 = *(usb_dptr++); /* copy all 8 bytes, packet might be shorter than 8 bytes */
  UE2D1 = *(usb_dptr++);
  UE2D2 = *(usb_dptr++);
  UE2D3 = *(usb_dptr++);
  UE2D4 = *(usb_dptr++);
  UE2D5 = *(usb_dptr++);
  UE2D6 = *(usb_dptr++);
  UE2D7 = *(usb_dptr++);
  if (usb_ep2_dcntT>8) {
    UCR2 = ((UCR2^UCR2_T2SEQ_MASK)&UCR2_T2SEQ_MASK) | UCR2_TX2E_MASK | UCR2_RX2E_MASK + 8; /* enable transmission on EP2, toggle DATA0/1, length 8 (more data in buffer) */
    usb_ep2_dcntT-=8;
  } else {
    UCR2 = ((UCR2^UCR2_T2SEQ_MASK)&UCR2_T2SEQ_MASK) | UCR2_TX2E_MASK | UCR2_RX2E_MASK + usb_ep2_dcntT; /* enable transmission on EP2, toggle DATA0/1, length according to count */
    usb_ep2_dcntT = 0;  /* no more data to transmit */
  }
}

/* EP0 Rx */
void USB_ep0_rx(void) {
  unsigned char * ptr=&UE0D0;
  while ((ptr<((&UE0D0)+8))&&(usb_ep0_dcntR)) {
    *(usb_dptr++) = *(ptr++);  /* copy data */
    usb_ep0_dcntR--;           /* decrement count */   
  }
  if (usb_ep0_dcntR==0) {
    /* command reception complete */  
    command_exec();
    usb_ep0_dcntT=0xff;   /* make sure the Tx routine does not interpret the subsequent IRQ incorrectly */
    usb_ep0_zeroterm=0;   /* switch zero-length termination off */      
    UCR0 = UCR0_TOSEQ_MASK | UCR0_TX0E_MASK | UCR0_RX0E_MASK; /* enable transmission on EP0, DATA1, lenght 0 (status packet for the control transfer) */
  }
}

/* EP2 Rx */
void USB_ep2_rx(void) {
  /* EP2 receives the messages in raw format (size of cmd+data, cmd, data0, data1, ...) */
  unsigned char * ptr=&UE2D0;
  if (usb_ep2_dcntR==0) {
    /* if the routine is called with no data to be received, it must be beginning of a message */
    UCR2_TX2E=0;      /* disable EP2 transmitter */
    usb_ep2_dcntR=UE2D0; 
    usb_dptr=command_buffer;
    ptr = &UE2D1; /* skip copying the size */
  }
  while ((ptr<((&UE2D0)+8))&&(usb_ep2_dcntR)) {
    *(usb_dptr++) = *(ptr++);  /* copy data */
    usb_ep2_dcntR--;                /* decrement count */   
  }
  if (usb_ep2_dcntR==0) {
    /* command reception complete */  
    usb_ep2_dcntT = command_exec();
    usb_dptr = command_buffer;
    USB_ep2_tx();     /* start transmitting the data */
  }
}

/* handles the set-up frame */
void USB_Setup(void) {
  usb_ep0_dcntT=0xff;   /* stop any data transfer in progress upon reception of a new setup packet */
  usb_ep0_zeroterm=0;   /* switch zero-length termination off */      
  if (USR0!=USR0_SETUP_MASK + 8) {  /* check whether it is valid setup request (DATA0 && size==8) */
    UCR3 = UCR3_ISTALL0_MASK | UCR3_OSTALL0_MASK;   /* stall EP0 communication and wait for new setup */
  } else {
    UCR0_TOSEQ=0; /* each setup transaction needs to start with DATA1 response (DATA0/1 inverted in tx) */
    if (((*(setup_packet*)&UE0D0).bmRequestType&0x60)==0) { /* standard request? */
      switch ((*(setup_packet*)&UE0D0).bRequest) {
        case SET_CONFIGURATION:
          if ((*(setup_packet*)&UE0D0).wValue.lo) {
            /* non-zero configuration number */
            /* initialise EP2 */
            UCR3 |= UCR3_ENABLE2_MASK;  /* enable EP2 */            
            UCR2 = UCR2_T2SEQ_MASK | UCR2_RX2E_MASK; /* enable EP2 receiver, transaction starts with DATA0 and the flag is inverted before transmitting */
            usb_ep0_dcntT=0xff;         /* bring the state machine into a known idle state */
            usb_ep0_dcntR=0;
            usb_ep2_dcntT=0;
            usb_ep2_dcntR=0;
            USB_State = US_CONFIGURED;  /* change state */  
          } else {
            /* configuration zero means back to addressed state */
            USB_State = US_ADDRESSED;
          }
          /* next send back the confirmation... */
        case SET_INTERFACE:
          /* do nothing, just send back a confirmation */
        case SET_ADDRESS:
          /* Note: address of the device is going to change only after this transmission is completed */
        case CLEAR_FEATURE:
          /* clear feature does nothing, just sends a confirmation */
          UCR0 = UCR0_TOSEQ_MASK | UCR0_TX0E_MASK | UCR0_RX0E_MASK; /* enable transmission on EP0, DATA1, lenght 0 (confirmation of new address reception) */
          return;
        case GET_CONFIGURATION:
          if (USB_State == US_CONFIGURED) UE0D0 = 1; else UE0D0 = 0;
          UCR0 = UCR0_TOSEQ_MASK | UCR0_TX0E_MASK | UCR0_RX0E_MASK + 1; /* enable transmission on EP0, DATA1, lenght 1 */
        case GET_DESCRIPTOR: 
          {
            unsigned char requested_length;
            if ((*(setup_packet*)&UE0D0).wLength.hi) requested_length=0xff; else  /* no descriptor is longer than 255 bytes... */
              requested_length=(*(setup_packet*)&UE0D0).wLength.lo;  
            /* which descriptor? */
            switch ((*(setup_packet*)&UE0D0).wValue.hi) {
              case DT_DEVICE:     /* device descriptor */
                copydown(sizeof(device_descriptor), &DeviceDesc, command_buffer); /* copy descriptor to the buffer */
  							usb_ep0_dcntT = sizeof(device_descriptor); /* update count */
                usb_dptr = command_buffer;                 /* data to transmit */
                if (usb_ep0_dcntT>=requested_length) {
                  usb_ep0_dcntT=requested_length;
                } else {
                  usb_ep0_zeroterm=1;
                }
  							USB_ep0_tx();     /* start transmitting the data */
  							break;
  						case DT_CONFIGURATION:
                copydown(sizeof(config_data), &config_data, command_buffer); /* copy descriptor to the buffer */
  							usb_ep0_dcntT = sizeof(config_data); /* update count */
                usb_dptr = command_buffer;			 /* data to transmit */
                if (usb_ep0_dcntT>=requested_length) {
                  usb_ep0_dcntT=requested_length;
                } else {
                  usb_ep0_zeroterm=1;
                }
  							USB_ep0_tx();     /* start transmitting the data */
  							break;
  						case DT_STRING:
                usb_ep0_dcntT = copystring((*(setup_packet*)&UE0D0).wValue.lo, command_buffer);
                usb_dptr = command_buffer; /* data to transmit */
                if (usb_ep0_dcntT>=requested_length) {
                  usb_ep0_dcntT=requested_length;
                } else {
                  usb_ep0_zeroterm=1;
                }
  							USB_ep0_tx();     /* start transmitting the data */
  							break;
            }
          }
          return;
      }
    } else if (((*(setup_packet*)&UE0D0).bmRequestType&0x60)==0x40) { /* vendor specific request? */
      if ((*(setup_packet*)&UE0D0).bmRequestType&0x80) {
        /* transfer dir device->host (it will be a command which reads data from the target or command which has 5 or less bytes) */  
        /* transfer 5 bytes from the status frame to the buffer */
        command_buffer[1]=UE0D1;  /* cmd */
        command_buffer[2]=UE0D2;  /* data0 */
        command_buffer[3]=UE0D3;  /* data1 */
        command_buffer[4]=UE0D4;  /* data2 */
        command_buffer[5]=UE0D5;  /* data3 */
        usb_ep0_dcntT=(*(setup_packet*)&UE0D0).wLength.lo; /* save transmit size, the host MUST NOT request more than 254 bytes! */
        command_exec();
        usb_dptr = command_buffer; /* point to data to return to the host */
				USB_ep0_tx();              /* start transmitting the data (or send an empty status frame in case there is no data to transmit) */
      } else {
        /* transfer dir host->device (it will be a command which writes data to the target) */
        /* transfer size is 5+length (5 first bytes are thransferred in the setup frame) */
        command_buffer[1]=UE0D1;  /* cmd */
        command_buffer[2]=UE0D2;  /* data0 */
        command_buffer[3]=UE0D3;  /* data1 */
        command_buffer[4]=UE0D4;  /* data2 */
        command_buffer[5]=UE0D5;  /* data3 */
        usb_ep0_dcntR=(*(setup_packet*)&UE0D0).wLength.lo;  /* the host MUST NOT send more data than will fit into the buffer!! */
        if (usb_ep0_dcntR==0) {
          /* no more data to follow */
          USB_ep0_rx(); /* the routine will not copy any data, but will launch command execution and status frame transmit */
                        /* this is cleaner as this code is in one place only */
          return;
        }
        /* data to follow, set-up pointer */  
				usb_dptr = command_buffer+6;  /* first 5 bytes stored already starting from position 1 */
      }
      return;
    }
    /* non-standard or unsupported request */
    UCR3 = UCR3_ISTALL0_MASK | UCR3_OSTALL0_MASK;   /* stall EP0 communication and wait for new setup */
  }
}

/* USB interrupt service routine */
void interrupt usb_isr(void) {
  suspend_timer=0;              /* keep the device out of stop */
  if (UIR1_EOPF) {
    usb_1ms_tick();             /* call timing routine */
    UIR2_EOPFR = 1;             /* clear the flag */
  } else {
    if (led_timer<255) led_timer++; /* interrupt request has a different reason, perform correction of LED tick (it is not going to be accurate, but this is better than nothing) */
    if (UIR1_RXD0F) {           /* EP0 Rx complete */
      UCR0_RX0E=0;              /* deactivate receiver */
      if (USR0_SETUP) {         /* was it a setup frame? */
        USB_Setup();            /* handle the setup frame */        
      } else {                  /* other EP0 Rx */
        if (USR0_RP0SIZ) USB_ep0_rx();  /* EP0 receives either zero-length status frames or valid data */ 
      }
      UIR2_RXD0FR = 1;          /* clear the flag and enable further reception */
      UCR0_RX0E=1;              /* reactivate receiver */
    } else if (UIR1_TXD0F) {    /* EP0 Tx complete */
      USB_ep0_tx();             /* handle Tx on EP0 */
      UIR2_TXD0FR = 1;          /* clear the flag */
    } else if (UIR1_RXD2F) {    /* EP2 Rx complete */
      UCR2_RX2E=0;              /* deactivate receiver */
      USB_ep2_rx();             /* receive the data */ 
      UIR2_RXD2FR = 1;          /* clear the flag and enable further reception */
      UCR2_RX2E=1;              /* reactivate receiver */
    } else if (UIR1_TXD2F) {    /* EP2 Tx complete */
      USB_ep2_tx();             /* handle Tx on EP0 */
      UIR2_TXD2FR = 1;          /* clear the flag */
    } else if (UIR1_RSTF) {     /* bus reset */
      usb_init();               /* soft reset the USB interface */
      USB_State = US_DEFAULT;   /* change the state to reflect the reset has occured */
      UCR0 = UCR0_RX0E_MASK;    /* enable EP0 reception */
      UIR2_RSTFR = 1;           /* clear the flag */
    } else if (UIR1_RESUMF) {   /* resume interrupt */
      UIR0_SUSPND = 0;          /* clear the suspend flag */
      UIR2_RESUMFR = 1;         /* clear the interrupt flag */
      usb_ep0_dcntT=0xff;       /* special meaning - means no transmission in progress */
      usb_ep0_dcntR=0;          /* no data to receive */
      usb_ep2_dcntT=0;          /* no data to transmit */
      usb_ep2_dcntR=0;          /* no data to receive */
			led_timer=0;
      led_state=LED_ON;
    }
  }
}

/* initialise the USB peripheral */
void usb_init(void) {
  usb_ep0_dcntT=0xff;       /* special meaning - means no transmission in progress */
  usb_ep0_dcntR=0;          /* no data to receive */
  usb_ep2_dcntT=0;          /* no data to transmit */
  usb_ep2_dcntR=0;          /* no data to receive */
  led_timer=0;
  led_state=LED_ON;
  LED_INIT;                 /* usb interrupt drives the LED, so make sure it is initialised */
  UADDR = UADDR_USBEN_MASK; /* enable the USB module, assign address to the default value (0) */  
  UIR0 = UIR0_RXD2IE_MASK | UIR0_RXD0IE_MASK | UIR0_TXD2IE_MASK | UIR0_TXD0IE_MASK | UIR0_EOPIE_MASK;  /* enable Rx&Tx interupts on EP0 & EP2, enable end of frame interrupt */
  UCR0 = 0;                 /* reset EP0 */
  UCR1 = 0;                 /* reset EP1 */
  UCR2 = 0;                 /* reset EP2 */
  UCR4 = 0;                 /* normal operation */
  UCR3 = UCR3_TX1STR_MASK ; /*NO Pullup clear TX1ST & enable internal pull-up */

	USB_State = US_POWERED;		/* must be powered when running this code... */
}

⌨️ 快捷键说明

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