aboutsummaryrefslogtreecommitdiffstats
path: root/core/usb/usb.c
diff options
context:
space:
mode:
authorAJM <poslathian@poslathian.(none)>2010-04-20 14:35:58 -0400
committerbnewbold <bnewbold@robocracy.org>2010-05-20 22:09:15 -0400
commitbfb86b6c2ac84c691c150e20adcc1b77d57efd10 (patch)
treefeb5286f411417d6832a417e02e07fe1c775f4e7 /core/usb/usb.c
parent0db5696149d8f01275955c94ec55c9c43d7ca390 (diff)
downloadlibrambutan-bfb86b6c2ac84c691c150e20adcc1b77d57efd10.tar.gz
librambutan-bfb86b6c2ac84c691c150e20adcc1b77d57efd10.zip
finished the entire low level usb app for virtual com minus the precise handling of get/send data callbacks and toggle line state. completely undebugged for now.
Diffstat (limited to 'core/usb/usb.c')
-rw-r--r--core/usb/usb.c368
1 files changed, 307 insertions, 61 deletions
diff --git a/core/usb/usb.c b/core/usb/usb.c
index 8826858..2f458cc 100644
--- a/core/usb/usb.c
+++ b/core/usb/usb.c
@@ -1,85 +1,331 @@
-#include "libmaple.h"
+/* *****************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 LeafLabs LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * ****************************************************************************/
+
+/**
+ * @file usb.c
+ *
+ * @brief usb-specific hardware setup, NVIC, clocks, and usb activities
+ * in the pre-attached state. includes some of the lower level callbacks
+ * needed by the usb library, like suspend,resume,init,etc
+ */
+
#include "usb.h"
-#include "usb_regs.h"
-#include "bootVect.h"
+#include "gpio.h"
+#include "usb_callbacks.h"
+
+/* persistent usb structs */
+volatile uint32 bDeviceState = UNCONNECTED;
+volatile uint16 wIstr = 0;
+volatile bIntPackSOF = 0;
+
+DEVICE Device_Table =
+ {
+ NUM_ENDPTS,
+ 1
+ };
+
+DEVICE_PROP Device_Property =
+ {
+ usbInit,
+ usbReset,
+ usbStatusIn,
+ usbStatusOut,
+ usbDataSetup,
+ usbNoDataSetup,
+ usbGetInterfaceSetting,
+ usbGetDeviceDescriptor,
+ usbGetInterfaceDescriptor,
+ usbGetConfigDescriptor,
+ usbGetStringDescriptor,
+ usbGetFunctionalDescriptor,
+ 0,
+ bMaxPacketSize
+ };
+
+USER_STANDARD_REQUESTS User_Standard_Requests =
+ {
+ usbGetConfiguration,
+ usbSetConfiguration,
+ usbGetInterface,
+ usbSetInterface,
+ usbGetStatus,
+ usbClearFeature,
+ usbSetEndpointFeature,
+ usbSetDeviceFeature,
+ usbSetDeviceAddress
+ };
+
+void (*pEpInt_IN[7])(void) =
+{
+ vcomManagementCb,
+ vcomDataTxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+};
-void usb_lpIRQHandler(void)
+void (*pEpInt_OUT[7])(void) =
{
- typedef void (*funcPtr)(void);
-
- const uint32_t usbIsrAddr = *(uint32_t*)(USB_ISR_ADDR);
- void (*ptrToUsbISR)(void) = (funcPtr) usbIsrAddr;
- ptrToUsbISR();
-}
+ NOP_Process,
+ NOP_Process,
+ vcomDataRxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+};
-void usb_userToPMABufferCopy(uint8 *pbUsrBuf, uint16 wPMABufAddr, uint16 wNBytes)
+struct
{
- uint32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */
- uint32 i, temp1, temp2;
- uint16 *pdwVal;
- pdwVal = (uint16 *)(wPMABufAddr * 2 + PMAAddr);
- for (i = n; i != 0; i--)
- {
- temp1 = (uint16) * pbUsrBuf;
- pbUsrBuf++;
- temp2 = temp1 | (uint16) * pbUsrBuf << 8;
- *pdwVal++ = temp2;
- pdwVal++;
- pbUsrBuf++;
- }
+ volatile RESUME_STATE eState;
+ volatile uint8 bESOFcnt;
+} ResumeS;
+
+void setupUSB (void) {
+ gpio_set_mode(USB_DISC_BANK,
+ USB_DISC_PIN,
+ GPIO_MODE_OUTPUT_PP);
+
+ /* setup the apb1 clock for USB */
+ pRCC->APB1ENR |= 0x00800000;
+
+ /* initialize the usb application */
+ gpio_write_bit(USB_DISC_BANK,USB_DISC_PIN,0); /* present ourselves to the host */
+ USB_Init(); /* low level init routine provided by st lib */
+
}
-void usb_PMAToUserBufferCopy(uint8 *pbUsrBuf, uint16 wPMABufAddr, uint16 wNBytes)
-{
- uint32 n = (wNBytes + 1) >> 1;/* /2*/
- uint32 i;
- uint32 *pdwVal;
- pdwVal = (uint32 *)(wPMABufAddr * 2 + PMAAddr);
- for (i = n; i != 0; i--)
- {
- *(uint16*)pbUsrBuf++ = *pdwVal++;
- pbUsrBuf++;
- }
+void usbSuspend(void) {
+ u16 wCNTR;
+ wCNTR = _GetCNTR();
+ wCNTR |= CNTR_FSUSP | CNTR_LPMODE;
+ _SetCNTR(wCNTR);
+
+ /* run any power reduction handlers */
+ bDeviceState = SUSPENDED;
}
-void usb_serialWriteStr(const char* outStr) {
- uint8 offset=0;
- BootVectTable *bootVector = ((BootVectTable*)BOOTLOADER_VECT_TABLE);
+void usbResumeInit(void) {
+ u16 wCNTR;
- while ((outStr[offset] != '\0')
- && (offset < USB_SERIAL_BUF_SIZE)) {
- offset++;
- }
+ /* restart any clocks that had been stopped */
+
+ wCNTR = _GetCNTR();
+ wCNTR &= (~CNTR_LPMODE);
+ _SetCNTR(wCNTR);
+
+ /* undo power reduction handlers here */
- delay(offset*1);
+ _SetCNTR(ISR_MSK);
- bootVector->serial_count_in = (uint32*) &offset;
- usb_userToPMABufferCopy((uint8*)outStr,USB_SERIAL_ENDP_TXADDR,offset);
- _SetEPTxCount(USB_SERIAL_ENDP_TX,offset);
- _SetEPTxValid(USB_SERIAL_ENDP_TX);
+}
+
+void usbResume(RESUME_STATE eResumeSetVal) {
+ u16 wCNTR;
+ if (eResumeSetVal != RESUME_ESOF)
+ ResumeS.eState = eResumeSetVal;
+
+ switch (ResumeS.eState)
+ {
+ case RESUME_EXTERNAL:
+ usbResumeInit();
+ ResumeS.eState = RESUME_OFF;
+ break;
+ case RESUME_INTERNAL:
+ usbResumeInit();
+ ResumeS.eState = RESUME_START;
+ break;
+ case RESUME_LATER:
+ ResumeS.bESOFcnt = 2;
+ ResumeS.eState = RESUME_WAIT;
+ break;
+ case RESUME_WAIT:
+ ResumeS.bESOFcnt--;
+ if (ResumeS.bESOFcnt == 0)
+ ResumeS.eState = RESUME_START;
+ break;
+ case RESUME_START:
+ wCNTR = _GetCNTR();
+ wCNTR |= CNTR_RESUME;
+ _SetCNTR(wCNTR);
+ ResumeS.eState = RESUME_ON;
+ ResumeS.bESOFcnt = 10;
+ break;
+ case RESUME_ON:
+ ResumeS.bESOFcnt--;
+ if (ResumeS.bESOFcnt == 0)
+ {
+ wCNTR = _GetCNTR();
+ wCNTR &= (~CNTR_RESUME);
+ _SetCNTR(wCNTR);
+ ResumeS.eState = RESUME_OFF;
+ }
+ break;
+ case RESUME_OFF:
+ case RESUME_ESOF:
+ default:
+ ResumeS.eState = RESUME_OFF;
+ break;
+ }
}
-void usb_serialWriteChar(unsigned char ch) {
- BootVectTable *bootVector = ((BootVectTable*)BOOTLOADER_VECT_TABLE);
+RESULT usbPowerOn(void) {
+ u16 wRegVal;
+
+ wRegVal = CNTR_FRES;
+ _SetCNTR(wRegVal);
+
+ wInterrupt_Mask = 0;
+ _SetCNTR(wInterrupt_Mask);
+ _SetISTR(0);
+ wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; /* the bare minimum */
+ _SetCNTR(wInterrupt_Mask);
- delay(1);
+ return USB_SUCCESS;
+}
+
+RESULT usbPowerOff(void) {
+ _SetCNTR(CNTR_FRES);
+ _SetISTR(0);
+ _SetCNTR(CNTR_FRES + CNTR_PDWN);
- *(bootVector->serial_count_in) = 1;
- usb_userToPMABufferCopy((uint8*)(&ch),USB_SERIAL_ENDP_TXADDR,1);
- _SetEPTxCount(USB_SERIAL_ENDP_TX,1);
- _SetEPTxValid(USB_SERIAL_ENDP_TX);
+ /* note that all weve done here is powerdown the
+ usb peripheral. we have no disabled the clocks,
+ pulled the usb_disc pin back up, or reset the
+ application state machines */
+ return USB_SUCCESS;
}
-uint8 usb_serialGetRecvLen() {
- uint8 count_out =_GetEPRxCount(USB_SERIAL_ENDP_RX);
- return count_out;
+void usbEnbISR(void) {
+ NVIC_InitTypeDef NVIC_InitStructure;
+
+
+ NVIC_InitStructure.NVIC_IRQChannel = USB_LP_IRQ;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = TRUE;
+ nvicInit(&NVIC_InitStructure);
}
-void usb_copyRecvBuffer(unsigned char* dest, uint8 len) {
- ASSERT(len < USB_SERIAL_BUF_SIZE);
- usb_PMAToUserBufferCopy((uint8*)(dest),USB_SERIAL_ENDP_RXADDR,len);
- _SetEPRxValid(USB_SERIAL_ENDP_RX);
+void usbDsbISR(void) {
+ NVIC_InitTypeDef NVIC_InitStructure;
+ NVIC_InitStructure.NVIC_IRQChannel = USB_LP_IRQ;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = FALSE;
+ nvicInit(&NVIC_InitStructure);
}
+/* overloaded ISR routine, this is the main usb ISR */
+void usb_lpIRQHandler(void);
+wIstr = _GetISTR();
+
+/* go nuts with the preproc switches since this is an ISTR and must be FAST */
+#if (ISR_MSK & ISTR_RESET)
+if (wIstr & ISTR_RESET & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_RESET);
+ Device_Property.Reset();
+ }
+#endif
+
+
+#if (ISR_MSK & ISTR_DOVR)
+if (wIstr & ISTR_DOVR & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_DOVR);
+ }
+#endif
+
+
+#if (ISR_MSK & ISTR_ERR)
+if (wIstr & ISTR_ERR & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_ERR);
+ }
+#endif
+
+
+#if (ISR_MSK & ISTR_WKUP)
+if (wIstr & ISTR_WKUP & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_WKUP);
+ usbResume(RESUME_EXTERNAL);
+ }
+#endif
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+#if (ISR_MSK & ISTR_SUSP)
+if (wIstr & ISTR_SUSP & wInterrupt_Mask)
+ {
+
+ /* check if SUSPEND is possible */
+ if (F_SUSPEND_ENABLED)
+ {
+ usbSuspend();
+ }
+ else
+ {
+ /* if not possible then resume after xx ms */
+ usbResume(RESUME_LATER);
+ }
+ /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
+ _SetISTR((u16)CLR_SUSP);
+ }
+#endif
+
+
+#if (ISR_MSK & ISTR_SOF)
+if (wIstr & ISTR_SOF & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_SOF);
+ bIntPackSOF++;
+ }
+#endif
+
+
+#if (ISR_MSK & ISTR_ESOF)
+if (wIstr & ISTR_ESOF & wInterrupt_Mask)
+ {
+ _SetISTR((u16)CLR_ESOF);
+ /* resume handling timing is made with ESOFs */
+ usbResume(RESUME_ESOF); /* request without change of the machine state */
+ }
+#endif
+
+/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
+#if (ISR_MSK & ISTR_CTR)
+if (wIstr & ISTR_CTR & wInterrupt_Mask)
+ {
+ /* servicing of the endpoint correct transfer interrupt */
+ /* clear of the CTR flag into the sub */
+ CTR_LP(); /* low priority ISR defined in the usb core lib */
+ }
+#endif
+
+}