Chris Arndt / USBDevice_STM32F103

Dependents:   STM32F103_USBMIDI_Switchbox mbed-os-usbserial-test

Fork of USBDevice_STM32F103 by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_STM32F1.cpp Source File

USBHAL_STM32F1.cpp

00001 /* Copyright (c) 2010-2015 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #include "USBDevice.h"
00020 
00021 #define USB_LP_IRQn USB_LP_CAN1_RX0_IRQn
00022 const uint8_t PCD_EP_TYPE_CTRL = EP_TYPE_CTRL;
00023 const uint8_t PCD_EP_TYPE_INTR = EP_TYPE_INTR;
00024 const uint8_t PCD_EP_TYPE_BULK = EP_TYPE_BULK;
00025 const uint8_t PCD_EP_TYPE_ISOC = EP_TYPE_ISOC;
00026 
00027 static PCD_HandleTypeDef hpcd_USB_FS;
00028 static volatile int epComplete = 0;
00029 
00030 USBHAL * USBHAL::instance;
00031 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {return 0;}
00032 
00033 USBHAL::USBHAL(void) {
00034     hpcd_USB_FS.pData = this;
00035     hpcd_USB_FS.Instance = USB;
00036     hpcd_USB_FS.Init.dev_endpoints = 8;
00037     hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
00038     hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
00039     hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
00040     hpcd_USB_FS.Init.Sof_enable = DISABLE;
00041     hpcd_USB_FS.Init.low_power_enable = DISABLE;
00042     hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
00043     NVIC_SetVector(USB_LP_IRQn, (uint32_t)&_usbisr);
00044     HAL_PCD_Init(&hpcd_USB_FS);
00045     HAL_PCD_Start(&hpcd_USB_FS);
00046 }
00047 
00048 void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) {
00049     __HAL_RCC_USB_CLK_ENABLE();
00050     HAL_NVIC_SetPriority(USB_LP_IRQn, 0, 0);
00051     HAL_NVIC_EnableIRQ(USB_LP_IRQn);
00052 }
00053 
00054 void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) {
00055     __HAL_RCC_USB_CLK_DISABLE(); // Peripheral clock disable
00056     HAL_NVIC_DisableIRQ(USB_LP_IRQn); // Peripheral interrupt Deinit
00057 }
00058 
00059 USBHAL::~USBHAL(void) {
00060     HAL_PCD_DeInit(&hpcd_USB_FS);
00061 }
00062 
00063 void USBHAL::connect(void) {
00064     HAL_PCD_DevConnect(&hpcd_USB_FS);
00065 }
00066 
00067 void USBHAL::disconnect(void) {
00068     HAL_PCD_DevDisconnect(&hpcd_USB_FS);
00069 }
00070 
00071 void USBHAL::configureDevice(void) {
00072     // Not needed
00073 }
00074 void USBHAL::unconfigureDevice(void) {
00075     // Not needed
00076 }
00077 
00078 void USBHAL::setAddress(uint8_t address) {
00079     HAL_PCD_SetAddress(&hpcd_USB_FS, address);
00080 }
00081 
00082 class PacketBufferAreaManager {
00083 public:
00084     PacketBufferAreaManager(int bufsize_):bufsize(bufsize_) {
00085         reset();
00086     }
00087     void reset() { 
00088         head = 0; 
00089         tail = bufsize; 
00090     }
00091     int allocBuf(int maxPacketSize) {
00092         head += 4;
00093         tail -= maxPacketSize;
00094         if (tail < head) {
00095             return 0;
00096         }
00097         return tail;
00098     }
00099 private:
00100     int head,tail;
00101     int bufsize;
00102 } PktBufArea(512);
00103 
00104 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
00105     int pmaadress = PktBufArea.allocBuf(maxPacket);
00106     MBED_ASSERT(pmaadress != 0);
00107     if (pmaadress == 0) {
00108         return false;
00109     }
00110     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00111     uint8_t ep_type;
00112     switch(endpoint) {
00113         case EP0OUT:
00114             HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, pmaadress);
00115             HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, PCD_EP_TYPE_CTRL);
00116             break;
00117         case EP0IN:
00118             HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, pmaadress);
00119             HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, PCD_EP_TYPE_CTRL);
00120             break;
00121         case EPINT_OUT:
00122             HAL_PCDEx_PMAConfig(hpcd, 0x01, PCD_SNG_BUF, pmaadress);
00123             HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, PCD_EP_TYPE_INTR);
00124             break;
00125         case EPINT_IN:
00126             HAL_PCDEx_PMAConfig(hpcd, 0x81, PCD_SNG_BUF, pmaadress);
00127             HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, PCD_EP_TYPE_INTR);
00128             break;
00129         case EPBULK_OUT:
00130             HAL_PCDEx_PMAConfig(hpcd, 0x02, PCD_SNG_BUF, pmaadress);
00131             HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, PCD_EP_TYPE_BULK);
00132             break;
00133         case EPBULK_IN:
00134             HAL_PCDEx_PMAConfig(hpcd, 0x82, PCD_SNG_BUF, pmaadress);
00135             HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, PCD_EP_TYPE_BULK);
00136             break;
00137         case EP3OUT:
00138             HAL_PCDEx_PMAConfig(hpcd, 0x03, PCD_SNG_BUF, pmaadress);
00139             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00140             HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type);
00141             break;
00142         case EP3IN:
00143             HAL_PCDEx_PMAConfig(hpcd, 0x83, PCD_SNG_BUF, pmaadress);
00144             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00145             HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, ep_type);
00146             break;
00147         default:
00148             MBED_ASSERT(0);
00149             return false;
00150     }
00151     return true;
00152 }
00153 
00154 // read setup packet
00155 void USBHAL::EP0setup(uint8_t *buffer) {
00156     memcpy(buffer, hpcd_USB_FS.Setup, 8);
00157 }
00158 
00159 void USBHAL::EP0readStage(void) {
00160 }
00161 
00162 void USBHAL::EP0read(void) {
00163     endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
00164 }
00165 
00166 class rxTempBufferManager {
00167     uint8_t buf0[MAX_PACKET_SIZE_EP0];
00168     uint8_t buf1[MAX_PACKET_SIZE_EP1];
00169     uint8_t buf2[MAX_PACKET_SIZE_EP2];
00170     uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO];
00171 public:
00172     uint8_t* ptr(uint8_t endpoint, int maxPacketSize) {
00173         switch(endpoint) {
00174             case EP0OUT:
00175                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP0);
00176                 break;
00177             case EP1OUT:
00178                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP1);
00179                 break;
00180             case EP2OUT:
00181                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP2);
00182                 break;
00183             case EP3OUT:
00184                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP3_ISO);
00185                 break;
00186         }
00187         return ptr(endpoint);
00188     }
00189     uint8_t* ptr(uint8_t endpoint) {
00190         switch(endpoint) {
00191             case EP0OUT: return buf0;
00192             case EP1OUT: return buf1;
00193             case EP2OUT: return buf2;
00194             case EP3OUT: return buf3;
00195         }
00196         MBED_ASSERT(0);
00197         return NULL;
00198     }
00199 } rxtmp;
00200 
00201 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00202     const uint8_t endpoint = EP0OUT;
00203     uint32_t length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00204     memcpy(buffer, rxtmp.ptr(endpoint), length);
00205     return length;
00206 }
00207 
00208 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00209     endpointWrite(EP0IN, buffer, size);
00210 }
00211 
00212 void USBHAL::EP0getWriteResult(void) {
00213 }
00214 
00215 void USBHAL::EP0stall(void) {
00216     // If we stall the out endpoint here then we have problems transferring
00217     // and setup requests after the (stalled) get device qualifier requests.
00218     // TODO: Find out if this is correct behavior, or whether we are doing
00219     // something else wrong
00220     stallEndpoint(EP0IN);
00221 //    stallEndpoint(EP0OUT);
00222 }
00223 
00224 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00225     HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize);
00226     epComplete &= ~(1 << endpoint);
00227     return EP_PENDING;
00228 }
00229 
00230 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
00231     if (!(epComplete & (1 << endpoint))) {
00232         return EP_PENDING;
00233     }
00234     int len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00235     memcpy(buffer, rxtmp.ptr(endpoint), len);
00236     *bytesRead = len;
00237     return EP_COMPLETED;
00238 }
00239 
00240 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00241     HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size);
00242     epComplete &= ~(1 << endpoint);
00243     return EP_PENDING;
00244 }
00245 
00246 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00247     if (epComplete & (1 << endpoint)) {
00248         epComplete &= ~(1 << endpoint);
00249         return EP_COMPLETED;
00250     }
00251     return EP_PENDING;
00252 }
00253 
00254 void USBHAL::stallEndpoint(uint8_t endpoint) {
00255     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00256     switch(endpoint) {
00257         case EP0IN:
00258             HAL_PCD_EP_SetStall(hpcd, 0x80);
00259             break;
00260         case EP0OUT:
00261             HAL_PCD_EP_SetStall(hpcd, 0x00);
00262             break;
00263         default:
00264             break;
00265     }
00266 }
00267 
00268 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00269 }
00270 
00271 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
00272     return false;
00273 }
00274 
00275 void USBHAL::remoteWakeup(void) {}
00276 
00277 void USBHAL::_usbisr(void) {
00278     HAL_PCD_IRQHandler(&hpcd_USB_FS);
00279 }
00280 
00281 void USBHAL::usbisr(void) {}
00282 
00283 void USBHAL::SetupStageCallback() {
00284     EP0setupCallback();
00285 }
00286 
00287 void USBHAL::DataInStageCallback(uint8_t epnum) {
00288     switch(epnum) {
00289         case 0: // EP0IN
00290             EP0in();
00291             break;
00292         case 1: 
00293             epComplete |= (1<<EP1IN);
00294             if (EP1_IN_callback()) {
00295                 epComplete &= ~(1<<EP1IN);
00296             }
00297             break;
00298         case 2:
00299             epComplete |= (1<<EP2IN);
00300             if (EP2_IN_callback()) {
00301                 epComplete &= ~(1<<EP2IN);
00302             }
00303             break;
00304         case 3: 
00305             epComplete |= (1<<EP3IN);
00306             if (EP3_IN_callback()) {
00307                 epComplete &= ~(1<<EP3IN);
00308             }
00309             break;
00310         default:
00311             MBED_ASSERT(0);
00312             break;
00313     }
00314 }
00315 
00316 void USBHAL::DataOutStageCallback(uint8_t epnum) {
00317     switch(epnum) {
00318         case 0: // EP0OUT
00319             if ((hpcd_USB_FS.Setup[0]&0x80) == 0x00) { // host to device ?
00320                 EP0out();
00321             }
00322             break;
00323         case 1:
00324             epComplete |= (1<<EP1OUT);
00325             if (EP1_OUT_callback()) {
00326                 epComplete &= ~(1<<EP1OUT);
00327             }
00328             break;
00329         case 2:
00330             epComplete |= (1<<EP2OUT);
00331             if (EP2_OUT_callback()) {
00332                 epComplete &= ~(1<<EP2OUT);
00333             }
00334             break;
00335         case 3:
00336             epComplete |= (1<<EP3OUT);
00337             if (EP3_OUT_callback()) {
00338                 epComplete &= ~(1<<EP3OUT);
00339             }
00340             break;
00341         default:
00342             MBED_ASSERT(0);
00343             break;
00344     }
00345 }
00346 
00347 void USBHAL::ResetCallback() {
00348     PktBufArea.reset();
00349     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
00350     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
00351 }
00352 
00353 void USBHAL::SOFCallback() {
00354     SOF(hpcd_USB_FS.Instance->FNR & USB_FNR_FN);
00355 }
00356 
00357 void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) {
00358     reinterpret_cast<USBHAL*>(hpcd->pData)->SetupStageCallback();
00359 }
00360 
00361 void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00362     reinterpret_cast<USBHAL*>(hpcd->pData)->DataInStageCallback(epnum);
00363 }
00364 
00365 void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00366     reinterpret_cast<USBHAL*>(hpcd->pData)->DataOutStageCallback(epnum);
00367 }
00368 
00369 void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) {
00370     reinterpret_cast<USBHAL*>(hpcd->pData)->ResetCallback();
00371 }
00372 
00373 void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
00374     reinterpret_cast<USBHAL*>(hpcd->pData)->SOFCallback();
00375 }
00376 
00377 void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) {
00378     if (hpcd->Init.low_power_enable) {
00379         SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
00380     }
00381 }