ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_M453.cpp Source File

USBHAL_M453.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2015-2016 Nuvoton
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #if defined(TARGET_NUMAKER_PFM_M453)
00018 
00019 #include "USBHAL.h"
00020 #include "M451Series.h"
00021 #include "pinmap.h"
00022 
00023 /**
00024  * EP: mbed USBD defined endpoint, e.g. EP0OUT/IN, EP1OUT/IN, EP2OUT/IN.
00025  * EPX: BSP defined endpoint, e.g. CEP, EPA, EPB, EPC.
00026  */
00027 
00028 USBHAL * USBHAL::instance;
00029 
00030 /* Global variables for Control Pipe */
00031 extern uint8_t g_usbd_SetupPacket[];        /*!< Setup packet buffer */
00032 
00033 static volatile uint32_t s_ep_compl = 0;
00034 static volatile uint32_t s_ep_buf_ind = 8;
00035 static volatile uint8_t s_usb_addr = 0;
00036 static volatile uint8_t s_ep_data_bit[NUMBER_OF_PHYSICAL_ENDPOINTS] = {1};
00037 static volatile uint8_t s_ep_mxp[NUMBER_OF_PHYSICAL_ENDPOINTS] = {0};
00038 
00039 extern volatile uint8_t *g_usbd_CtrlInPointer;
00040 extern volatile uint32_t g_usbd_CtrlInSize;
00041 extern volatile uint8_t *g_usbd_CtrlOutPointer;
00042 extern volatile uint32_t g_usbd_CtrlOutSize;
00043 extern volatile uint32_t g_usbd_CtrlOutSizeLimit;
00044 extern volatile uint32_t g_usbd_UsbConfig;
00045 extern volatile uint32_t g_usbd_CtrlMaxPktSize;
00046 extern volatile uint32_t g_usbd_UsbAltInterface;
00047 volatile uint32_t g_usbd_CepTransferLen = 0;
00048 volatile uint32_t frame_cnt = 0;
00049 USBHAL::USBHAL(void)
00050 {
00051     SYS_UnlockReg();
00052 
00053     s_ep_buf_ind = 8;
00054 
00055     memset(epCallback, 0x00, sizeof (epCallback));
00056     epCallback[0] = &USBHAL::EP1_OUT_callback;
00057     epCallback[1] = &USBHAL::EP2_IN_callback;
00058     epCallback[2] = &USBHAL::EP3_OUT_callback;
00059     epCallback[3] = &USBHAL::EP4_IN_callback;
00060     epCallback[4] = &USBHAL::EP5_OUT_callback;
00061     epCallback[5] = &USBHAL::EP6_IN_callback;
00062 
00063     instance = this;
00064     /* Enable USBD module clock */
00065     CLK_EnableModuleClock(USBD_MODULE);
00066 
00067     CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV0_USB(3));
00068 
00069     /* Enable USB LDO33 */
00070     SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk;
00071 
00072     /* Initial USB engine */
00073     USBD->ATTR = 0x7D0;
00074 
00075     /* Set SE0 (disconnect) */
00076     USBD_SET_SE0();
00077 
00078     //NVIC_SetVector(OTG_FS_IRQn, (uint32_t) &_usbisr);
00079     NVIC_SetVector(USBD_IRQn, (uint32_t) &_usbisr);
00080     NVIC_EnableIRQ(USBD_IRQn);
00081 }
00082 
00083 USBHAL::~USBHAL(void)
00084 {
00085     NVIC_DisableIRQ(USBD_IRQn);
00086     USBD_SET_SE0();
00087     USBD_DISABLE_PHY();
00088 }
00089 
00090 void USBHAL::connect(void)
00091 {
00092     USBD->STBUFSEG = 0;
00093     frame_cnt = 0;
00094     /* EP0 ==> control IN endpoint, address 0 */
00095     USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | 0);
00096     /* Buffer range for EP0 */
00097     USBD_SET_EP_BUF_ADDR(EP0, s_ep_buf_ind);
00098 
00099     /* EP1 ==> control OUT endpoint, address 0 */
00100     USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | 0);
00101     /* Buffer range for EP1 */
00102     USBD_SET_EP_BUF_ADDR(EP1, s_ep_buf_ind);
00103 
00104     s_ep_buf_ind += MAX_PACKET_SIZE_EP0;
00105 
00106     /* Disable software-disconnect function */
00107     USBD_CLR_SE0();
00108 
00109     /* Clear USB-related interrupts before enable interrupt */
00110     USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
00111 
00112     /* Enable USB-related interrupts. */
00113     USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
00114 }
00115 
00116 void USBHAL::disconnect(void)
00117 {
00118     /* Set SE0 (disconnect) */
00119     USBD_SET_SE0();
00120 }
00121 
00122 void USBHAL::configureDevice(void)
00123 {
00124     /**
00125      * In USBDevice.cpp > USBDevice::requestSetConfiguration, configureDevice() is called after realiseEndpoint() (in USBCallback_setConfiguration()).
00126      * So we have the following USB buffer management policy:
00127      *  1. Allocate for CEP on connect().
00128      *  2. Allocate for EPX in realiseEndpoint().
00129      *  3. Deallocate all except for CEP in unconfigureDevice().
00130      */
00131 }
00132 
00133 void USBHAL::unconfigureDevice(void)
00134 {
00135     s_ep_buf_ind = 8;
00136 }
00137 
00138 void USBHAL::setAddress(uint8_t address)
00139 {
00140     // NOTE: Delay address setting; otherwise, USB controller won't ack.
00141     s_usb_addr = address;
00142 }
00143 
00144 void USBHAL::remoteWakeup(void)
00145 {
00146 #if 0
00147     USBD->OPER |= USBD_OPER_RESUMEEN_Msk;
00148 #endif
00149 }
00150 
00151 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
00152 {
00153     uint32_t ep_type = 0;
00154     uint32_t ep_hw_index = NU_EP2EPH(endpoint);
00155     uint32_t ep_logic_index = NU_EP2EPL(endpoint);
00156     uint32_t ep_dir = (NU_EP_DIR(endpoint) == NU_EP_DIR_IN) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT;
00157 
00158     if (ep_logic_index == 3 || ep_logic_index == 4)
00159         ep_type = USBD_CFG_TYPE_ISO;
00160 
00161     USBD_CONFIG_EP(ep_hw_index, ep_dir | ep_type | ep_logic_index);
00162     /* Buffer range */
00163     USBD_SET_EP_BUF_ADDR(ep_hw_index, s_ep_buf_ind);
00164 
00165     if (ep_dir == USBD_CFG_EPMODE_OUT)
00166         USBD_SET_PAYLOAD_LEN(ep_hw_index, maxPacket);
00167 
00168     s_ep_mxp[ep_logic_index] = maxPacket;
00169 
00170     s_ep_buf_ind += maxPacket;
00171 
00172     return true;
00173 }
00174 
00175 void USBHAL::EP0setup(uint8_t *buffer)
00176 {
00177     uint32_t sz;
00178     endpointReadResult(EP0OUT, buffer, &sz);
00179 }
00180 
00181 void USBHAL::EP0read(void)
00182 {
00183 
00184 
00185 }
00186 
00187 void USBHAL::EP0readStage(void)
00188 {
00189     // N/A
00190 
00191     USBD_PrepareCtrlOut(0,0);
00192 }
00193 
00194 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
00195 {
00196     uint32_t i;
00197     uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1));
00198     uint32_t ceprxcnt = USBD_GET_PAYLOAD_LEN(EP1);
00199     for (i = 0; i < ceprxcnt; i ++)
00200         buffer[i] = buf[i];
00201     USBD_SET_PAYLOAD_LEN(EP1, MAX_PACKET_SIZE_EP0);
00202     return ceprxcnt;
00203 }
00204 
00205 void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
00206 {
00207     if (buffer && size)
00208     {
00209         if (s_ep_data_bit[0] & 1)
00210             USBD_SET_DATA1(EP0);
00211         else
00212             USBD_SET_DATA0(EP0);
00213         s_ep_data_bit[0]++;
00214 
00215         USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), buffer, size);
00216         USBD_SET_PAYLOAD_LEN(EP0, size);
00217         if (size < MAX_PACKET_SIZE_EP0)
00218             s_ep_data_bit[0] = 1;
00219 
00220     }
00221     else
00222     {
00223         if (g_usbd_SetupPacket[0] & 0x80)   //Device to Host
00224         {
00225             // Status stage
00226             //          USBD_PrepareCtrlOut(0,0);
00227         } else
00228         {
00229             USBD_SET_DATA1(EP0);
00230             USBD_SET_PAYLOAD_LEN(EP0, 0);
00231         }
00232     }
00233 }
00234 
00235 void USBHAL::EP0getWriteResult(void)
00236 {
00237     // N/A
00238 }
00239 
00240 void USBHAL::EP0stall(void)
00241 {
00242     stallEndpoint(EP0OUT);
00243 }
00244 
00245 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
00246 {
00247     return EP_PENDING;
00248 }
00249 
00250 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) //spcheng
00251 {
00252     if (endpoint == EP0OUT)
00253     {
00254         USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8);
00255         if (buffer) {
00256             USBD_MemCopy(buffer, g_usbd_SetupPacket, 8);
00257         }
00258         USBD_SET_PAYLOAD_LEN(EP1, MAX_PACKET_SIZE_EP0);
00259     }
00260     else
00261     {
00262         uint32_t i;
00263         uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(NU_EP2EPH(endpoint)));
00264         uint32_t eprxcnt = USBD_GET_PAYLOAD_LEN(NU_EP2EPH(endpoint));
00265         for (i = 0; i < eprxcnt; i ++)
00266             buffer[i] = buf[i];
00267 
00268         *bytesRead = eprxcnt;
00269 
00270         USBD_SET_PAYLOAD_LEN(NU_EP2EPH(endpoint),s_ep_mxp[NU_EPH2EPL(NU_EP2EPL(endpoint))]);
00271     }
00272     return EP_COMPLETED;
00273 }
00274 
00275 
00276 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer)
00277 {
00278     return 0;
00279 }
00280 
00281 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
00282 {
00283     uint32_t ep_logic_index = NU_EP2EPL(endpoint);
00284     if (ep_logic_index == 0)
00285         return EP_INVALID;
00286     else
00287     {
00288         uint8_t *buf;
00289         uint32_t i=0;
00290         uint32_t ep_hw_index = NU_EP2EPH(endpoint);
00291         s_ep_compl |= (1 << ep_logic_index);
00292         buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(ep_hw_index));
00293         for (i=0;i<size;i++)
00294             buf[i] = data[i];
00295 
00296         /* Set transfer length and trigger IN transfer */
00297         USBD_SET_PAYLOAD_LEN(ep_hw_index, size);
00298 
00299     }
00300     return EP_PENDING;
00301 }
00302 
00303 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
00304 {
00305     if (!(s_ep_compl & (1 << NU_EP2EPL(endpoint))))
00306         return EP_COMPLETED;
00307     return EP_PENDING;
00308 }
00309 
00310 void USBHAL::stallEndpoint(uint8_t endpoint)
00311 {
00312     uint32_t ep_hw_index = NU_EP2EPH(endpoint);
00313     if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
00314         return;
00315 
00316     USBD_SetStall(NU_EPH2EPL(ep_hw_index));
00317 
00318 }
00319 
00320 void USBHAL::unstallEndpoint(uint8_t endpoint)
00321 {
00322     uint32_t ep_hw_index = NU_EP2EPH(endpoint);
00323     if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
00324         return;
00325     USBD_ClearStall(NU_EPH2EPL(ep_hw_index));
00326 }
00327 
00328 bool USBHAL::getEndpointStallState(uint8_t endpoint)
00329 {
00330     uint32_t ep_hw_index = NU_EP2EPH(endpoint);
00331     if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
00332         return false;
00333 
00334     return USBD_GetStall(NU_EPH2EPL(ep_hw_index)) ? 1 : 0;
00335 }
00336 
00337 void USBHAL::_usbisr(void)
00338 {
00339     MBED_ASSERT(instance);
00340     instance->usbisr();
00341 }
00342 
00343 void USBHAL::usbisr(void)
00344 {
00345     uint32_t u32IntSts = USBD_GET_INT_FLAG();
00346     uint32_t u32State = USBD_GET_BUS_STATE();
00347 
00348 //------------------------------------------------------------------
00349     if (u32IntSts & USBD_INTSTS_VBDETIF_Msk)
00350     {
00351         // Floating detect
00352         USBD_CLR_INT_FLAG(USBD_INTSTS_VBDETIF_Msk);
00353 
00354         if (USBD_IS_ATTACHED())
00355         {
00356             /* USB Plug In */
00357             USBD_ENABLE_USB();
00358         }
00359         else
00360         {
00361             /* USB Un-plug */
00362             USBD_DISABLE_USB();
00363         }
00364     }
00365 
00366 //------------------------------------------------------------------
00367     if (u32IntSts & USBD_INTSTS_BUSIF_Msk)
00368     {
00369         /* Clear event flag */
00370         USBD_CLR_INT_FLAG(USBD_INTSTS_BUSIF_Msk);
00371 
00372         if (u32State & USBD_ATTR_USBRST_Msk)
00373         {
00374             /* Bus reset */
00375             USBD_ENABLE_USB();
00376             USBD_SwReset();
00377         }
00378         if (u32State & USBD_ATTR_SUSPEND_Msk)
00379         {
00380             /* Enable USB but disable PHY */
00381             USBD_DISABLE_PHY();
00382         }
00383         if (u32State & USBD_ATTR_RESUME_Msk)
00384         {
00385             /* Enable USB and enable PHY */
00386             USBD_ENABLE_USB();
00387         }
00388     }
00389 
00390     if (u32IntSts & USBD_INTSTS_USBIF_Msk)
00391     {
00392         // USB event
00393         if (u32IntSts & USBD_INTSTS_SETUP_Msk)
00394         {
00395             // Setup packet
00396             /* Clear event flag */
00397             USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk);
00398 
00399             /* Clear the data IN/OUT ready flag of control end-points */
00400             USBD_STOP_TRANSACTION(EP0);
00401             USBD_STOP_TRANSACTION(EP1);
00402             EP0setupCallback();
00403         }
00404 
00405         // EP events
00406         if (u32IntSts & USBD_INTSTS_EP0)
00407         {
00408             /* Clear event flag */
00409             USBD_CLR_INT_FLAG(USBD_INTSTS_EP0);
00410             // control IN
00411             EP0in();
00412 
00413             // In ACK for Set address
00414             if ((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == USBD_SET_ADDRESS))
00415             {
00416                 if ((USBD_GET_ADDR() != s_usb_addr) && (USBD_GET_ADDR() == 0))
00417                 {
00418                     USBD_SET_ADDR(s_usb_addr);
00419                 }
00420             }
00421         }
00422         if (u32IntSts & USBD_INTSTS_EP1)
00423         {
00424             /* Clear event flag */
00425             USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);
00426 
00427             // control OUT
00428             EP0out();
00429         }
00430 
00431         uint32_t gintsts_epx = (u32IntSts >> 18) & 0x3F;
00432         uint32_t ep_hw_index = 2;
00433         while (gintsts_epx) {
00434             if (gintsts_epx & 0x01)
00435             {
00436                 uint32_t ep_status = (USBD_GET_EP_FLAG() >> (ep_hw_index * 3 + 8)) & 0x7;
00437                 /* Clear event flag */
00438                 USBD_CLR_INT_FLAG(1 << (ep_hw_index + 16));
00439 
00440                 if (ep_status == 0x02 || ep_status == 0x06 || (ep_status == 0x07 && NU_EPH2EPL(ep_hw_index) == 3))  //RX
00441                 {
00442                     if (ep_status == 0x07)
00443                         SOF(frame_cnt++);
00444                     if ((instance->*(epCallback[ep_hw_index-2]))())
00445                     {
00446 
00447                     }
00448                     USBD_SET_PAYLOAD_LEN(ep_hw_index,s_ep_mxp[NU_EPH2EPL(ep_hw_index)]);
00449                 }
00450                 else if (ep_status == 0x00 || ep_status == 0x07)    //TX
00451                 {
00452                     s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index)));
00453                     if ((instance->*(epCallback[ep_hw_index-2]))())
00454                     {
00455                     }
00456                 }
00457             }
00458 
00459             gintsts_epx = gintsts_epx >> 1;
00460             ep_hw_index++;
00461         }
00462     }
00463 }
00464 #endif
00465