USBDevice for STM support

Dependents:   Nucleo_Usb_JoyMouse Nucleo_usbmouse ELEC350_1-referral-2018-usb-hid USBJoystick_HelloWorld2_wip ... more

This library contains all mbed usb device library (mbed-os\features\unsupported\USBDevice).

Committer:
frq08711@LMECWL0871.LME.ST.COM
Date:
Tue Mar 28 11:00:57 2017 +0200
Branch:
master
Revision:
4:50ec00aa4515
Parent:
1:2a3ae13b45ef
update for 5.4.2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 2 *
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 4 * and associated documentation files (the "Software"), to deal in the Software without
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 7 * Software is furnished to do so, subject to the following conditions:
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 8 *
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 9 * The above copyright notice and this permission notice shall be included in all copies or
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 10 * substantial portions of the Software.
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 11 *
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 17 */
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 18
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 19 #if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D50M) | defined(TARGET_K64F) | defined(TARGET_K22F) | defined(TARGET_TEENSY3_1)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 20
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 21 #if defined(TARGET_KSDK2_MCUS)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 22 #include "fsl_common.h"
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 23 #endif
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 24 #include "USBHAL.h"
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 25
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 26 USBHAL * USBHAL::instance;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 27
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 28 static volatile int epComplete = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 29
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 30 // Convert physical endpoint number to register bit
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 31 #define EP(endpoint) (1<<(endpoint))
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 32
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 33 // Convert physical to logical
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 34 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 35
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 36 // Get endpoint direction
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 37 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 38 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 39
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 40 #define BD_OWN_MASK (1<<7)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 41 #define BD_DATA01_MASK (1<<6)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 42 #define BD_KEEP_MASK (1<<5)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 43 #define BD_NINC_MASK (1<<4)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 44 #define BD_DTS_MASK (1<<3)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 45 #define BD_STALL_MASK (1<<2)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 46
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 47 #define TX 1
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 48 #define RX 0
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 49 #define ODD 0
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 50 #define EVEN 1
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 51 // this macro waits a physical endpoint number
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 52 #define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd)))
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 53
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 54 #define SETUP_TOKEN 0x0D
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 55 #define IN_TOKEN 0x09
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 56 #define OUT_TOKEN 0x01
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 57 #define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 58
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 59 // for each endpt: 8 bytes
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 60 typedef struct BDT {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 61 uint8_t info; // BD[0:7]
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 62 uint8_t dummy; // RSVD: BD[8:15]
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 63 uint16_t byte_count; // BD[16:32]
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 64 uint32_t address; // Addr
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 65 } BDT;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 66
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 67
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 68 // there are:
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 69 // * 16 bidirectionnal endpt -> 32 physical endpt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 70 // * as there are ODD and EVEN buffer -> 32*2 bdt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 71 MBED_ALIGN(512) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; // 512 bytes aligned!
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 72
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 73 uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 74 uint8_t * endpoint_buffer_iso[2*2];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 75
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 76 static uint8_t set_addr = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 77 static uint8_t addr = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 78
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 79 static uint32_t Data1 = 0x55555555;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 80
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 81 static uint32_t frameNumber() {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 82 return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 83 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 84
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 85 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 86 return 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 87 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 88
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 89 USBHAL::USBHAL(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 90 // Disable IRQ
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 91 NVIC_DisableIRQ(USB0_IRQn);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 92
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 93 #if (defined(FSL_FEATURE_SOC_MPU_COUNT) && (FSL_FEATURE_SOC_MPU_COUNT > 0U))
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 94 MPU->CESR=0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 95 #endif
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 96 // fill in callback array
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 97 epCallback[0] = &USBHAL::EP1_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 98 epCallback[1] = &USBHAL::EP1_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 99 epCallback[2] = &USBHAL::EP2_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 100 epCallback[3] = &USBHAL::EP2_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 101 epCallback[4] = &USBHAL::EP3_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 102 epCallback[5] = &USBHAL::EP3_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 103 epCallback[6] = &USBHAL::EP4_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 104 epCallback[7] = &USBHAL::EP4_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 105 epCallback[8] = &USBHAL::EP5_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 106 epCallback[9] = &USBHAL::EP5_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 107 epCallback[10] = &USBHAL::EP6_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 108 epCallback[11] = &USBHAL::EP6_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 109 epCallback[12] = &USBHAL::EP7_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 110 epCallback[13] = &USBHAL::EP7_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 111 epCallback[14] = &USBHAL::EP8_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 112 epCallback[15] = &USBHAL::EP8_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 113 epCallback[16] = &USBHAL::EP9_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 114 epCallback[17] = &USBHAL::EP9_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 115 epCallback[18] = &USBHAL::EP10_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 116 epCallback[19] = &USBHAL::EP10_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 117 epCallback[20] = &USBHAL::EP11_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 118 epCallback[21] = &USBHAL::EP11_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 119 epCallback[22] = &USBHAL::EP12_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 120 epCallback[23] = &USBHAL::EP12_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 121 epCallback[24] = &USBHAL::EP13_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 122 epCallback[25] = &USBHAL::EP13_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 123 epCallback[26] = &USBHAL::EP14_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 124 epCallback[27] = &USBHAL::EP14_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 125 epCallback[28] = &USBHAL::EP15_OUT_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 126 epCallback[29] = &USBHAL::EP15_IN_callback;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 127
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 128 #if defined(TARGET_KL43Z) || defined(TARGET_K22F) || defined(TARGET_K64F)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 129 // enable USBFS clock
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 130 CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 131 #else
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 132 // choose usb src as PLL
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 133 SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 134 SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | (1 << SIM_SOPT2_PLLFLLSEL_SHIFT));
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 135
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 136 // enable OTG clock
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 137 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 138 #endif
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 139
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 140 // Attach IRQ
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 141 instance = this;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 142 NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 143 NVIC_EnableIRQ(USB0_IRQn);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 144
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 145 // USB Module Configuration
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 146 // Set BDT Base Register
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 147 USB0->BDTPAGE1 = (uint8_t)((uint32_t)bdt>>8);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 148 USB0->BDTPAGE2 = (uint8_t)((uint32_t)bdt>>16);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 149 USB0->BDTPAGE3 = (uint8_t)((uint32_t)bdt>>24);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 150
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 151 // Clear interrupt flag
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 152 USB0->ISTAT = 0xff;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 153
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 154 // USB Interrupt Enablers
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 155 USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK |
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 156 USB_INTEN_SOFTOKEN_MASK |
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 157 USB_INTEN_ERROREN_MASK |
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 158 USB_INTEN_USBRSTEN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 159
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 160 // Disable weak pull downs
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 161 USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 162
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 163 USB0->USBTRC0 |= 0x40;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 164 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 165
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 166 USBHAL::~USBHAL(void) { }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 167
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 168 void USBHAL::connect(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 169 // enable USB
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 170 USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 171 // Pull up enable
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 172 USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 173 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 174
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 175 void USBHAL::disconnect(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 176 // disable USB
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 177 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 178 // Pull up disable
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 179 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 180
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 181 //Free buffers if required:
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 182 for (int i = 0; i<(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 183 free(endpoint_buffer[i]);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 184 endpoint_buffer[i] = NULL;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 185 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 186 free(endpoint_buffer_iso[2]);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 187 endpoint_buffer_iso[2] = NULL;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 188 free(endpoint_buffer_iso[0]);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 189 endpoint_buffer_iso[0] = NULL;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 190 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 191
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 192 void USBHAL::configureDevice(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 193 // not needed
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 194 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 195
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 196 void USBHAL::unconfigureDevice(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 197 // not needed
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 198 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 199
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 200 void USBHAL::setAddress(uint8_t address) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 201 // we don't set the address now otherwise the usb controller does not ack
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 202 // we set a flag instead
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 203 // see usbisr when an IN token is received
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 204 set_addr = 1;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 205 addr = address;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 206 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 207
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 208 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 209 uint32_t handshake_flag = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 210 uint8_t * buf;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 211
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 212 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 213 return false;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 214 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 215
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 216 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 217
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 218 if ((flags & ISOCHRONOUS) == 0) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 219 handshake_flag = USB_ENDPT_EPHSHK_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 220 if (IN_EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 221 if (endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] == NULL)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 222 endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] = (uint8_t *) malloc (64);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 223 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 224 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 225 if (endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] == NULL)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 226 endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] = (uint8_t *) malloc (64);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 227 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 228 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 229 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 230 if (IN_EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 231 if (endpoint_buffer_iso[2] == NULL)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 232 endpoint_buffer_iso[2] = (uint8_t *) malloc (1023);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 233 buf = &endpoint_buffer_iso[2][0];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 234 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 235 if (endpoint_buffer_iso[0] == NULL)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 236 endpoint_buffer_iso[0] = (uint8_t *) malloc (1023);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 237 buf = &endpoint_buffer_iso[0][0];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 238 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 239 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 240
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 241 // IN endpt -> device to host (TX)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 242 if (IN_EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 243 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 244 USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 245 bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 246 bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 247 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 248 // OUT endpt -> host to device (RX)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 249 else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 250 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 251 USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 252 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 253 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 254 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 255 bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 256 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 257
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 258 Data1 |= (1 << endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 259
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 260 return true;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 261 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 262
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 263 // read setup packet
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 264 void USBHAL::EP0setup(uint8_t *buffer) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 265 uint32_t sz;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 266 endpointReadResult(EP0OUT, buffer, &sz);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 267 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 268
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 269 void USBHAL::EP0readStage(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 270 Data1 &= ~1UL; // set DATA0
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 271 bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 272 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 273
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 274 void USBHAL::EP0read(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 275 uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 276 bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 277 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 278
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 279 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 280 uint32_t sz;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 281 endpointReadResult(EP0OUT, buffer, &sz);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 282 return sz;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 283 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 284
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 285 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 286 endpointWrite(EP0IN, buffer, size);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 287 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 288
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 289 void USBHAL::EP0getWriteResult(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 290 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 291
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 292 void USBHAL::EP0stall(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 293 stallEndpoint(EP0OUT);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 294 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 295
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 296 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 297 endpoint = PHY_TO_LOG(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 298 uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 299 bdt[idx].byte_count = maximumSize;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 300 return EP_PENDING;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 301 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 302
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 303 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 304 uint32_t n, sz, idx, setup = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 305 uint8_t not_iso;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 306 uint8_t * ep_buf;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 307
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 308 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 309
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 310 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 311 return EP_INVALID;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 312 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 313
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 314 // if read on a IN endpoint -> error
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 315 if (IN_EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 316 return EP_INVALID;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 317 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 318
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 319 idx = EP_BDT_IDX(log_endpoint, RX, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 320 sz = bdt[idx].byte_count;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 321 not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 322
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 323 //for isochronous endpoint, we don't wait an interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 324 if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 325 return EP_PENDING;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 326 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 327
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 328 if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 329 setup = 1;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 330 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 331
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 332 // non iso endpoint
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 333 if (not_iso) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 334 ep_buf = endpoint_buffer[idx];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 335 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 336 ep_buf = endpoint_buffer_iso[0];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 337 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 338
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 339 for (n = 0; n < sz; n++) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 340 buffer[n] = ep_buf[n];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 341 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 342
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 343 if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 344 if (setup && (buffer[6] == 0)) // if no setup data stage,
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 345 Data1 &= ~1UL; // set DATA0
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 346 else
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 347 Data1 ^= (1 << endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 348 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 349
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 350 if (((Data1 >> endpoint) & 1)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 351 bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 352 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 353 else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 354 bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 355 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 356
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 357 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 358 *bytesRead = sz;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 359
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 360 epComplete &= ~EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 361 return EP_COMPLETED;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 362 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 363
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 364 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 365 uint32_t idx, n;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 366 uint8_t * ep_buf;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 367
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 368 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 369 return EP_INVALID;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 370 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 371
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 372 // if write on a OUT endpoint -> error
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 373 if (OUT_EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 374 return EP_INVALID;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 375 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 376
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 377 idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 378 bdt[idx].byte_count = size;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 379
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 380
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 381 // non iso endpoint
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 382 if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 383 ep_buf = endpoint_buffer[idx];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 384 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 385 ep_buf = endpoint_buffer_iso[2];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 386 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 387
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 388 for (n = 0; n < size; n++) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 389 ep_buf[n] = data[n];
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 390 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 391
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 392 if ((Data1 >> endpoint) & 1) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 393 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 394 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 395 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 396 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 397
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 398 Data1 ^= (1 << endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 399
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 400 return EP_PENDING;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 401 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 402
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 403 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 404 if (epComplete & EP(endpoint)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 405 epComplete &= ~EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 406 return EP_COMPLETED;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 407 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 408
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 409 return EP_PENDING;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 410 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 411
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 412 void USBHAL::stallEndpoint(uint8_t endpoint) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 413 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 414 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 415
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 416 void USBHAL::unstallEndpoint(uint8_t endpoint) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 417 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 418 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 419
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 420 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 421 uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 422 return (stall) ? true : false;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 423 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 424
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 425 void USBHAL::remoteWakeup(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 426 // [TODO]
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 427 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 428
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 429
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 430 void USBHAL::_usbisr(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 431 instance->usbisr();
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 432 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 433
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 434
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 435 void USBHAL::usbisr(void) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 436 uint8_t i;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 437 uint8_t istat = USB0->ISTAT;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 438
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 439 // reset interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 440 if (istat & USB_ISTAT_USBRST_MASK) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 441 // disable all endpt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 442 for(i = 0; i < 16; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 443 USB0->ENDPOINT[i].ENDPT = 0x00;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 444 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 445
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 446 // enable control endpoint
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 447 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 448 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 449
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 450 Data1 = 0x55555555;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 451 USB0->CTL |= USB_CTL_ODDRST_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 452
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 453 USB0->ISTAT = 0xFF; // clear all interrupt status flags
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 454 USB0->ERRSTAT = 0xFF; // clear all error flags
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 455 USB0->ERREN = 0xFF; // enable error interrupt sources
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 456 USB0->ADDR = 0x00; // set default address
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 457
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 458 return;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 459 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 460
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 461 // resume interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 462 if (istat & USB_ISTAT_RESUME_MASK) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 463 USB0->ISTAT = USB_ISTAT_RESUME_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 464 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 465
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 466 // SOF interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 467 if (istat & USB_ISTAT_SOFTOK_MASK) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 468 USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 469 // SOF event, read frame number
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 470 SOF(frameNumber());
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 471 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 472
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 473 // stall interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 474 if (istat & 1<<7) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 475 if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 476 USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 477 USB0->ISTAT |= USB_ISTAT_STALL_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 478 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 479
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 480 // token interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 481 if (istat & 1<<3) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 482 uint32_t num = (USB0->STAT >> 4) & 0x0F;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 483 uint32_t dir = (USB0->STAT >> 3) & 0x01;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 484 uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 485 int endpoint = (num << 1) | dir;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 486
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 487 // setup packet
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 488 if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 489 Data1 &= ~0x02;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 490 bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 491 bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 492
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 493 // EP0 SETUP event (SETUP data received)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 494 EP0setupCallback();
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 495
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 496 } else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 497 // OUT packet
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 498 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 499 if (num == 0)
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 500 EP0out();
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 501 else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 502 epComplete |= EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 503 if ((instance->*(epCallback[endpoint - 2]))()) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 504 epComplete &= ~EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 505 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 506 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 507 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 508
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 509 // IN packet
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 510 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 511 if (num == 0) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 512 EP0in();
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 513 if (set_addr == 1) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 514 USB0->ADDR = addr & 0x7F;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 515 set_addr = 0;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 516 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 517 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 518 else {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 519 epComplete |= EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 520 if ((instance->*(epCallback[endpoint - 2]))()) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 521 epComplete &= ~EP(endpoint);
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 522 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 523 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 524 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 525 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 526
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 527 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 528 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 529
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 530 // sleep interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 531 if (istat & 1<<4) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 532 USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 533 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 534
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 535 // error interrupt
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 536 if (istat & USB_ISTAT_ERROR_MASK) {
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 537 USB0->ERRSTAT = 0xFF;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 538 USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 539 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 540 }
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 541
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 542
frq08711@LMECWL0871.LME.ST.COM 1:2a3ae13b45ef 543 #endif