USB device stack for NUCLEO-F042K6, NUCLEO-L152RE and NUCLEO-F103RB.

Dependents:   LPE-SEM01

Fork of L152RE_USBDevice by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_STM32L1.cpp Source File

USBHAL_STM32L1.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 #if defined(TARGET_STM32L1)||defined(TARGET_STM32F1)||defined(TARGET_STM32F0)
00020 #include "USBDevice.h"
00021 
00022 #if defined(TARGET_STM32F1)
00023 #define USB_LP_IRQn USB_LP_CAN1_RX0_IRQn
00024 const uint8_t PCD_EP_TYPE_CTRL = EP_TYPE_CTRL;
00025 const uint8_t PCD_EP_TYPE_INTR = EP_TYPE_INTR;
00026 const uint8_t PCD_EP_TYPE_BULK = EP_TYPE_BULK;
00027 const uint8_t PCD_EP_TYPE_ISOC = EP_TYPE_ISOC;
00028 
00029 #elif defined(TARGET_STM32L1)
00030 void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) {
00031     __SYSCFG_CLK_ENABLE(); // for SYSCFG_PMC_USB_PU
00032     if (state == 1) {
00033         __HAL_SYSCFG_USBPULLUP_ENABLE();
00034     } else {
00035         __HAL_SYSCFG_USBPULLUP_DISABLE();
00036     } 
00037 }
00038 
00039 #elif defined(TARGET_STM32L0)||defined(TARGET_STM32F0)
00040 #define USB_LP_IRQn USB_IRQn
00041 void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) {
00042     if (state == 1) {
00043         SET_BIT(USB->BCDR, USB_BCDR_DPPU); // DP Pull-up
00044     } else {
00045         CLEAR_BIT(USB->BCDR, USB_BCDR_DPPU);
00046     } 
00047 }
00048 
00049 #elif defined(TARGET_STM32F3)
00050 #define USB_LP_IRQn USB_LP_CAN1_RX0_IRQn
00051 #endif
00052 
00053 static PCD_HandleTypeDef hpcd_USB_FS;
00054 static volatile int epComplete = 0;
00055 
00056 USBHAL * USBHAL::instance;
00057 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {return 0;}
00058 
00059 USBHAL::USBHAL(void) {
00060     hpcd_USB_FS.pData = this;
00061     hpcd_USB_FS.Instance = USB;
00062     hpcd_USB_FS.Init.dev_endpoints = 8;
00063     hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
00064     hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
00065     hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
00066     hpcd_USB_FS.Init.Sof_enable = DISABLE;
00067     hpcd_USB_FS.Init.low_power_enable = DISABLE;
00068     hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
00069     NVIC_SetVector(USB_LP_IRQn, (uint32_t)&_usbisr);
00070     HAL_PCD_Init(&hpcd_USB_FS);
00071     HAL_PCD_Start(&hpcd_USB_FS);
00072 }
00073 
00074 void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) {
00075     __USB_CLK_ENABLE();
00076     HAL_NVIC_SetPriority(USB_LP_IRQn, 0, 0);
00077     HAL_NVIC_EnableIRQ(USB_LP_IRQn);
00078 }
00079 
00080 void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) {
00081     __USB_CLK_DISABLE(); // Peripheral clock disable
00082     HAL_NVIC_DisableIRQ(USB_LP_IRQn); // Peripheral interrupt Deinit
00083 }
00084 
00085 USBHAL::~USBHAL(void) {
00086     HAL_PCD_DeInit(&hpcd_USB_FS);
00087 }
00088 
00089 void USBHAL::connect(void) {
00090     HAL_PCD_DevConnect(&hpcd_USB_FS);
00091 }
00092 
00093 void USBHAL::disconnect(void) {
00094     HAL_PCD_DevDisconnect(&hpcd_USB_FS);
00095 }
00096 
00097 void USBHAL::configureDevice(void) {
00098     // Not needed
00099 }
00100 void USBHAL::unconfigureDevice(void) {
00101     // Not needed
00102 }
00103 
00104 void USBHAL::setAddress(uint8_t address) {
00105     HAL_PCD_SetAddress(&hpcd_USB_FS, address);
00106 }
00107 
00108 class PacketBufferAreaManager {
00109 public:
00110     PacketBufferAreaManager(int bufsize_):bufsize(bufsize_) {
00111         reset();
00112     }
00113     void reset() { 
00114         head = 0; 
00115         tail = bufsize; 
00116     }
00117     int allocBuf(int maxPacketSize) {
00118         head += 4;
00119         tail -= maxPacketSize;
00120         if (tail < head) {
00121             return 0;
00122         }
00123         return tail;
00124     }
00125 private:
00126     int head,tail;
00127     int bufsize;
00128 } PktBufArea(512);
00129 
00130 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
00131     int pmaadress = PktBufArea.allocBuf(maxPacket);
00132     MBED_ASSERT(pmaadress != 0);
00133     if (pmaadress == 0) {
00134         return false;
00135     }
00136     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00137     uint8_t ep_type;
00138     switch(endpoint) {
00139         case EP0OUT:
00140             HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, pmaadress);
00141             HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, PCD_EP_TYPE_CTRL);
00142             break;
00143         case EP0IN:
00144             HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, pmaadress);
00145             HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, PCD_EP_TYPE_CTRL);
00146             break;
00147         case EPINT_OUT:
00148             HAL_PCDEx_PMAConfig(hpcd, 0x01, PCD_SNG_BUF, pmaadress);
00149             HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, PCD_EP_TYPE_INTR);
00150             break;
00151         case EPINT_IN:
00152             HAL_PCDEx_PMAConfig(hpcd, 0x81, PCD_SNG_BUF, pmaadress);
00153             HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, PCD_EP_TYPE_INTR);
00154             break;
00155         case EPBULK_OUT:
00156             HAL_PCDEx_PMAConfig(hpcd, 0x02, PCD_SNG_BUF, pmaadress);
00157             HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, PCD_EP_TYPE_BULK);
00158             break;
00159         case EPBULK_IN:
00160             HAL_PCDEx_PMAConfig(hpcd, 0x82, PCD_SNG_BUF, pmaadress);
00161             HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, PCD_EP_TYPE_BULK);
00162             break;
00163         case EP3OUT:
00164             HAL_PCDEx_PMAConfig(hpcd, 0x03, PCD_SNG_BUF, pmaadress);
00165             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00166             HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type);
00167             break;
00168         case EP3IN:
00169             HAL_PCDEx_PMAConfig(hpcd, 0x83, PCD_SNG_BUF, pmaadress);
00170             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00171             HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, ep_type);
00172             break;
00173         default:
00174             MBED_ASSERT(0);
00175             return false;
00176     }
00177     return true;
00178 }
00179 
00180 // read setup packet
00181 void USBHAL::EP0setup(uint8_t *buffer) {
00182     memcpy(buffer, hpcd_USB_FS.Setup, 8);
00183 }
00184 
00185 void USBHAL::EP0readStage(void) {
00186 }
00187 
00188 void USBHAL::EP0read(void) {
00189     endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
00190 }
00191 
00192 class rxTempBufferManager {
00193     uint8_t buf0[MAX_PACKET_SIZE_EP0];
00194     uint8_t buf1[MAX_PACKET_SIZE_EP1];
00195     uint8_t buf2[MAX_PACKET_SIZE_EP2];
00196     uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO];
00197 public:
00198     uint8_t* ptr(uint8_t endpoint, int maxPacketSize) {
00199         switch(endpoint) {
00200             case EP0OUT:
00201                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP0);
00202                 break;
00203             case EP1OUT:
00204                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP1);
00205                 break;
00206             case EP2OUT:
00207                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP2);
00208                 break;
00209             case EP3OUT:
00210                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP3_ISO);
00211                 break;
00212         }
00213         return ptr(endpoint);
00214     }
00215     uint8_t* ptr(uint8_t endpoint) {
00216         switch(endpoint) {
00217             case EP0OUT: return buf0;
00218             case EP1OUT: return buf1;
00219             case EP2OUT: return buf2;
00220             case EP3OUT: return buf3;
00221         }
00222         MBED_ASSERT(0);
00223         return NULL;
00224     }
00225 } rxtmp;
00226 
00227 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00228     const uint8_t endpoint = EP0OUT;
00229     uint32_t length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00230     memcpy(buffer, rxtmp.ptr(endpoint), length);
00231     return length;
00232 }
00233 
00234 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00235     endpointWrite(EP0IN, buffer, size);
00236 }
00237 
00238 void USBHAL::EP0getWriteResult(void) {
00239 }
00240 
00241 void USBHAL::EP0stall(void) {
00242     // If we stall the out endpoint here then we have problems transferring
00243     // and setup requests after the (stalled) get device qualifier requests.
00244     // TODO: Find out if this is correct behavior, or whether we are doing
00245     // something else wrong
00246     stallEndpoint(EP0IN);
00247 //    stallEndpoint(EP0OUT);
00248 }
00249 
00250 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00251     HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize);
00252     epComplete &= ~(1 << endpoint);
00253     return EP_PENDING;
00254 }
00255 
00256 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
00257     if (!(epComplete & (1 << endpoint))) {
00258         return EP_PENDING;
00259     }
00260     int len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00261     memcpy(buffer, rxtmp.ptr(endpoint), len);
00262     *bytesRead = len;
00263     return EP_COMPLETED;
00264 }
00265 
00266 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00267     HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size);
00268     epComplete &= ~(1 << endpoint);
00269     return EP_PENDING;
00270 }
00271 
00272 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00273     if (epComplete & (1 << endpoint)) {
00274         epComplete &= ~(1 << endpoint);
00275         return EP_COMPLETED;
00276     }
00277     return EP_PENDING;
00278 }
00279 
00280 void USBHAL::stallEndpoint(uint8_t endpoint) {
00281     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00282     switch(endpoint) {
00283         case EP0IN:
00284             HAL_PCD_EP_SetStall(hpcd, 0x80);
00285             break;
00286         case EP0OUT:
00287             HAL_PCD_EP_SetStall(hpcd, 0x00);
00288             break;
00289         default:
00290             break;
00291     }
00292 }
00293 
00294 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00295 }
00296 
00297 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
00298     return false;
00299 }
00300 
00301 void USBHAL::remoteWakeup(void) {}
00302 
00303 void USBHAL::_usbisr(void) {
00304     HAL_PCD_IRQHandler(&hpcd_USB_FS);
00305 }
00306 
00307 void USBHAL::usbisr(void) {}
00308 
00309 void USBHAL::SetupStageCallback() {
00310     EP0setupCallback();
00311 }
00312 
00313 void USBHAL::DataInStageCallback(uint8_t epnum) {
00314     switch(epnum) {
00315         case 0: // EP0IN
00316             EP0in();
00317             break;
00318         case 1: 
00319             epComplete |= (1<<EP1IN);
00320             if (EP1_IN_callback()) {
00321                 epComplete &= ~(1<<EP1IN);
00322             }
00323             break;
00324         case 2:
00325             epComplete |= (1<<EP2IN);
00326             if (EP2_IN_callback()) {
00327                 epComplete &= ~(1<<EP2IN);
00328             }
00329             break;
00330         case 3: 
00331             epComplete |= (1<<EP3IN);
00332             if (EP3_IN_callback()) {
00333                 epComplete &= ~(1<<EP3IN);
00334             }
00335             break;
00336         default:
00337             MBED_ASSERT(0);
00338             break;
00339     }
00340 }
00341 
00342 void USBHAL::DataOutStageCallback(uint8_t epnum) {
00343     switch(epnum) {
00344         case 0: // EP0OUT
00345             if ((hpcd_USB_FS.Setup[0]&0x80) == 0x00) { // host to device ?
00346                 EP0out();
00347             }
00348             break;
00349         case 1:
00350             epComplete |= (1<<EP1OUT);
00351             if (EP1_OUT_callback()) {
00352                 epComplete &= ~(1<<EP1OUT);
00353             }
00354             break;
00355         case 2:
00356             epComplete |= (1<<EP2OUT);
00357             if (EP2_OUT_callback()) {
00358                 epComplete &= ~(1<<EP2OUT);
00359             }
00360             break;
00361         case 3:
00362             epComplete |= (1<<EP3OUT);
00363             if (EP3_OUT_callback()) {
00364                 epComplete &= ~(1<<EP3OUT);
00365             }
00366             break;
00367         default:
00368             MBED_ASSERT(0);
00369             break;
00370     }
00371 }
00372 
00373 void USBHAL::ResetCallback() {
00374     PktBufArea.reset();
00375     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
00376     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
00377 }
00378 
00379 void USBHAL::SOFCallback() {
00380     SOF(hpcd_USB_FS.Instance->FNR & USB_FNR_FN);
00381 }
00382 
00383 void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) {
00384     reinterpret_cast<USBHAL*>(hpcd->pData)->SetupStageCallback();
00385 }
00386 
00387 void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00388     reinterpret_cast<USBHAL*>(hpcd->pData)->DataInStageCallback(epnum);
00389 }
00390 
00391 void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00392     reinterpret_cast<USBHAL*>(hpcd->pData)->DataOutStageCallback(epnum);
00393 }
00394 
00395 void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) {
00396     reinterpret_cast<USBHAL*>(hpcd->pData)->ResetCallback();
00397 }
00398 
00399 void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
00400     reinterpret_cast<USBHAL*>(hpcd->pData)->SOFCallback();
00401 }
00402 
00403 void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) {
00404     if (hpcd->Init.low_power_enable) {
00405         SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
00406     }
00407 }
00408 
00409 #endif