Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
source/hic_hal/stm32/stm32f103xb/usbd_STM32F103.c@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 2 | * Copyright (c) 2004-2016 ARM Limited. All rights reserved. |
Pawel Zarembski |
0:01f31e923fe2 | 3 | * |
Pawel Zarembski |
0:01f31e923fe2 | 4 | * SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 5 | * |
Pawel Zarembski |
0:01f31e923fe2 | 6 | * Licensed under the Apache License, Version 2.0 (the License); you may |
Pawel Zarembski |
0:01f31e923fe2 | 7 | * not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 8 | * You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 9 | * |
Pawel Zarembski |
0:01f31e923fe2 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 11 | * |
Pawel Zarembski |
0:01f31e923fe2 | 12 | * Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 15 | * See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 16 | * limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 17 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 18 | |
Pawel Zarembski |
0:01f31e923fe2 | 19 | /*---------------------------------------------------------------------------- |
Pawel Zarembski |
0:01f31e923fe2 | 20 | * RL-ARM - USB |
Pawel Zarembski |
0:01f31e923fe2 | 21 | *---------------------------------------------------------------------------- |
Pawel Zarembski |
0:01f31e923fe2 | 22 | * Name: usbd_STM32F103.c |
Pawel Zarembski |
0:01f31e923fe2 | 23 | * Purpose: Hardware Layer module for ST STM32F103 |
Pawel Zarembski |
0:01f31e923fe2 | 24 | * Rev.: V4.70 |
Pawel Zarembski |
0:01f31e923fe2 | 25 | *---------------------------------------------------------------------------*/ |
Pawel Zarembski |
0:01f31e923fe2 | 26 | |
Pawel Zarembski |
0:01f31e923fe2 | 27 | /* Double Buffering is not supported */ |
Pawel Zarembski |
0:01f31e923fe2 | 28 | |
Pawel Zarembski |
0:01f31e923fe2 | 29 | #include <rl_usb.h> |
Pawel Zarembski |
0:01f31e923fe2 | 30 | #include "stm32f1xx.h" |
Pawel Zarembski |
0:01f31e923fe2 | 31 | #include "usbreg.h" |
Pawel Zarembski |
0:01f31e923fe2 | 32 | #include "IO_Config.h" |
Pawel Zarembski |
0:01f31e923fe2 | 33 | #include "cortex_m.h" |
Pawel Zarembski |
0:01f31e923fe2 | 34 | #include "string.h" |
Pawel Zarembski |
0:01f31e923fe2 | 35 | |
Pawel Zarembski |
0:01f31e923fe2 | 36 | #define __NO_USB_LIB_C |
Pawel Zarembski |
0:01f31e923fe2 | 37 | #include "usb_config.c" |
Pawel Zarembski |
0:01f31e923fe2 | 38 | |
Pawel Zarembski |
0:01f31e923fe2 | 39 | #define USB_ISTR_W0C_MASK (ISTR_PMAOVR | ISTR_ERR | ISTR_WKUP | ISTR_SUSP | ISTR_RESET | ISTR_SOF | ISTR_ESOF) |
Pawel Zarembski |
0:01f31e923fe2 | 40 | #define VAL_MASK 0xFFFF |
Pawel Zarembski |
0:01f31e923fe2 | 41 | #define VAL_SHIFT 16 |
Pawel Zarembski |
0:01f31e923fe2 | 42 | #define EP_NUM_MASK 0xFFFF |
Pawel Zarembski |
0:01f31e923fe2 | 43 | #define EP_NUM_SHIFT 0 |
Pawel Zarembski |
0:01f31e923fe2 | 44 | |
Pawel Zarembski |
0:01f31e923fe2 | 45 | #define USB_DBL_BUF_EP 0x0000 |
Pawel Zarembski |
0:01f31e923fe2 | 46 | |
Pawel Zarembski |
0:01f31e923fe2 | 47 | #define EP_BUF_ADDR (sizeof(EP_BUF_DSCR)*(USBD_EP_NUM+1)) /* Endpoint Buf Adr */ |
Pawel Zarembski |
0:01f31e923fe2 | 48 | |
Pawel Zarembski |
0:01f31e923fe2 | 49 | EP_BUF_DSCR *pBUF_DSCR = (EP_BUF_DSCR *)USB_PMA_ADDR; /* Ptr to EP Buf Desc */ |
Pawel Zarembski |
0:01f31e923fe2 | 50 | |
Pawel Zarembski |
0:01f31e923fe2 | 51 | U16 FreeBufAddr; /* Endpoint Free Buffer Address */ |
Pawel Zarembski |
0:01f31e923fe2 | 52 | |
Pawel Zarembski |
0:01f31e923fe2 | 53 | uint32_t StatQueue[(USBD_EP_NUM + 1) * 2 + 1]; |
Pawel Zarembski |
0:01f31e923fe2 | 54 | uint32_t StatQueueHead = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 55 | uint32_t StatQueueTail = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 56 | uint32_t LastIstr = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 57 | |
Pawel Zarembski |
0:01f31e923fe2 | 58 | |
Pawel Zarembski |
0:01f31e923fe2 | 59 | inline static void stat_enque(uint32_t stat) |
Pawel Zarembski |
0:01f31e923fe2 | 60 | { |
Pawel Zarembski |
0:01f31e923fe2 | 61 | cortex_int_state_t state; |
Pawel Zarembski |
0:01f31e923fe2 | 62 | state = cortex_int_get_and_disable(); |
Pawel Zarembski |
0:01f31e923fe2 | 63 | StatQueue[StatQueueTail] = stat; |
Pawel Zarembski |
0:01f31e923fe2 | 64 | StatQueueTail = (StatQueueTail + 1) % (sizeof(StatQueue) / sizeof(StatQueue[0])); |
Pawel Zarembski |
0:01f31e923fe2 | 65 | cortex_int_restore(state); |
Pawel Zarembski |
0:01f31e923fe2 | 66 | } |
Pawel Zarembski |
0:01f31e923fe2 | 67 | |
Pawel Zarembski |
0:01f31e923fe2 | 68 | inline static uint32_t stat_deque() |
Pawel Zarembski |
0:01f31e923fe2 | 69 | { |
Pawel Zarembski |
0:01f31e923fe2 | 70 | cortex_int_state_t state; |
Pawel Zarembski |
0:01f31e923fe2 | 71 | uint32_t stat; |
Pawel Zarembski |
0:01f31e923fe2 | 72 | state = cortex_int_get_and_disable(); |
Pawel Zarembski |
0:01f31e923fe2 | 73 | stat = StatQueue[StatQueueHead]; |
Pawel Zarembski |
0:01f31e923fe2 | 74 | StatQueueHead = (StatQueueHead + 1) % (sizeof(StatQueue) / sizeof(StatQueue[0])); |
Pawel Zarembski |
0:01f31e923fe2 | 75 | cortex_int_restore(state); |
Pawel Zarembski |
0:01f31e923fe2 | 76 | |
Pawel Zarembski |
0:01f31e923fe2 | 77 | return stat; |
Pawel Zarembski |
0:01f31e923fe2 | 78 | } |
Pawel Zarembski |
0:01f31e923fe2 | 79 | |
Pawel Zarembski |
0:01f31e923fe2 | 80 | inline static uint32_t stat_is_empty() |
Pawel Zarembski |
0:01f31e923fe2 | 81 | { |
Pawel Zarembski |
0:01f31e923fe2 | 82 | cortex_int_state_t state; |
Pawel Zarembski |
0:01f31e923fe2 | 83 | uint32_t empty; |
Pawel Zarembski |
0:01f31e923fe2 | 84 | state = cortex_int_get_and_disable(); |
Pawel Zarembski |
0:01f31e923fe2 | 85 | empty = StatQueueHead == StatQueueTail; |
Pawel Zarembski |
0:01f31e923fe2 | 86 | cortex_int_restore(state); |
Pawel Zarembski |
0:01f31e923fe2 | 87 | return empty; |
Pawel Zarembski |
0:01f31e923fe2 | 88 | } |
Pawel Zarembski |
0:01f31e923fe2 | 89 | |
Pawel Zarembski |
0:01f31e923fe2 | 90 | |
Pawel Zarembski |
0:01f31e923fe2 | 91 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 92 | * Reset Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 93 | * Parameters: EPNum: Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 94 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 95 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 96 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 97 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 98 | |
Pawel Zarembski |
0:01f31e923fe2 | 99 | void EP_Reset(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 100 | { |
Pawel Zarembski |
0:01f31e923fe2 | 101 | U32 num, val; |
Pawel Zarembski |
0:01f31e923fe2 | 102 | num = EPNum & 0x0F; |
Pawel Zarembski |
0:01f31e923fe2 | 103 | val = EPxREG(num); |
Pawel Zarembski |
0:01f31e923fe2 | 104 | |
Pawel Zarembski |
0:01f31e923fe2 | 105 | if (EPNum & 0x80) { /* IN Endpoint */ |
Pawel Zarembski |
0:01f31e923fe2 | 106 | EPxREG(num) = val & (EP_MASK | EP_DTOG_TX); |
Pawel Zarembski |
0:01f31e923fe2 | 107 | } else { /* OUT Endpoint */ |
Pawel Zarembski |
0:01f31e923fe2 | 108 | EPxREG(num) = val & (EP_MASK | EP_DTOG_RX); |
Pawel Zarembski |
0:01f31e923fe2 | 109 | } |
Pawel Zarembski |
0:01f31e923fe2 | 110 | } |
Pawel Zarembski |
0:01f31e923fe2 | 111 | |
Pawel Zarembski |
0:01f31e923fe2 | 112 | |
Pawel Zarembski |
0:01f31e923fe2 | 113 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 114 | * Set Endpoint Status |
Pawel Zarembski |
0:01f31e923fe2 | 115 | * Parameters: EPNum: Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 116 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 117 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 118 | * stat: New Status |
Pawel Zarembski |
0:01f31e923fe2 | 119 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 120 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 121 | |
Pawel Zarembski |
0:01f31e923fe2 | 122 | void EP_Status(U32 EPNum, U32 stat) |
Pawel Zarembski |
0:01f31e923fe2 | 123 | { |
Pawel Zarembski |
0:01f31e923fe2 | 124 | U32 num, val; |
Pawel Zarembski |
0:01f31e923fe2 | 125 | num = EPNum & 0x0F; |
Pawel Zarembski |
0:01f31e923fe2 | 126 | val = EPxREG(num); |
Pawel Zarembski |
0:01f31e923fe2 | 127 | |
Pawel Zarembski |
0:01f31e923fe2 | 128 | if (EPNum & 0x80) { /* IN Endpoint */ |
Pawel Zarembski |
0:01f31e923fe2 | 129 | EPxREG(num) = EP_VAL_UNCHANGED(val) | ((val ^ stat) & EP_STAT_TX); |
Pawel Zarembski |
0:01f31e923fe2 | 130 | } else { /* OUT Endpoint */ |
Pawel Zarembski |
0:01f31e923fe2 | 131 | EPxREG(num) = EP_VAL_UNCHANGED(val) | ((val ^ stat) & EP_STAT_RX); |
Pawel Zarembski |
0:01f31e923fe2 | 132 | } |
Pawel Zarembski |
0:01f31e923fe2 | 133 | } |
Pawel Zarembski |
0:01f31e923fe2 | 134 | |
Pawel Zarembski |
0:01f31e923fe2 | 135 | |
Pawel Zarembski |
0:01f31e923fe2 | 136 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 137 | * USB Device Interrupt enable |
Pawel Zarembski |
0:01f31e923fe2 | 138 | * Called by USBD_Init to enable the USB Interrupt |
Pawel Zarembski |
0:01f31e923fe2 | 139 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 140 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 141 | |
Pawel Zarembski |
0:01f31e923fe2 | 142 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 143 | void __svc(1) USBD_IntrEna(void); |
Pawel Zarembski |
0:01f31e923fe2 | 144 | void __SVC_1(void) |
Pawel Zarembski |
0:01f31e923fe2 | 145 | { |
Pawel Zarembski |
0:01f31e923fe2 | 146 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 147 | void USBD_IntrEna(void) |
Pawel Zarembski |
0:01f31e923fe2 | 148 | { |
Pawel Zarembski |
0:01f31e923fe2 | 149 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 150 | NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); |
Pawel Zarembski |
0:01f31e923fe2 | 151 | } |
Pawel Zarembski |
0:01f31e923fe2 | 152 | |
Pawel Zarembski |
0:01f31e923fe2 | 153 | |
Pawel Zarembski |
0:01f31e923fe2 | 154 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 155 | * USB Device Initialize Function |
Pawel Zarembski |
0:01f31e923fe2 | 156 | * Called by the User to initialize USB |
Pawel Zarembski |
0:01f31e923fe2 | 157 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 158 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 159 | |
Pawel Zarembski |
0:01f31e923fe2 | 160 | void USBD_Init(void) |
Pawel Zarembski |
0:01f31e923fe2 | 161 | { |
Pawel Zarembski |
0:01f31e923fe2 | 162 | RCC->APB1ENR |= (1 << 23); /* enable clock for USB */ |
Pawel Zarembski |
0:01f31e923fe2 | 163 | USBD_IntrEna(); /* Enable USB Interrupts */ |
Pawel Zarembski |
0:01f31e923fe2 | 164 | /* Control USB connecting via SW */ |
Pawel Zarembski |
0:01f31e923fe2 | 165 | USB_CONNECT_OFF(); |
Pawel Zarembski |
0:01f31e923fe2 | 166 | } |
Pawel Zarembski |
0:01f31e923fe2 | 167 | |
Pawel Zarembski |
0:01f31e923fe2 | 168 | |
Pawel Zarembski |
0:01f31e923fe2 | 169 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 170 | * USB Device Connect Function |
Pawel Zarembski |
0:01f31e923fe2 | 171 | * Called by the User to Connect/Disconnect USB Device |
Pawel Zarembski |
0:01f31e923fe2 | 172 | * Parameters: con: Connect/Disconnect |
Pawel Zarembski |
0:01f31e923fe2 | 173 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 174 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 175 | |
Pawel Zarembski |
0:01f31e923fe2 | 176 | void USBD_Connect(BOOL con) |
Pawel Zarembski |
0:01f31e923fe2 | 177 | { |
Pawel Zarembski |
0:01f31e923fe2 | 178 | if (con) { |
Pawel Zarembski |
0:01f31e923fe2 | 179 | CNTR = CNTR_FRES; /* Force USB Reset */ |
Pawel Zarembski |
0:01f31e923fe2 | 180 | CNTR = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 181 | ISTR = 0; /* Clear Interrupt Status */ |
Pawel Zarembski |
0:01f31e923fe2 | 182 | CNTR = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; /* USB Interrupt Mask */ |
Pawel Zarembski |
0:01f31e923fe2 | 183 | USB_CONNECT_ON(); |
Pawel Zarembski |
0:01f31e923fe2 | 184 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 185 | CNTR = CNTR_FRES | CNTR_PDWN; /* Switch Off USB Device */ |
Pawel Zarembski |
0:01f31e923fe2 | 186 | USB_CONNECT_OFF(); |
Pawel Zarembski |
0:01f31e923fe2 | 187 | } |
Pawel Zarembski |
0:01f31e923fe2 | 188 | } |
Pawel Zarembski |
0:01f31e923fe2 | 189 | |
Pawel Zarembski |
0:01f31e923fe2 | 190 | |
Pawel Zarembski |
0:01f31e923fe2 | 191 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 192 | * USB Device Reset Function |
Pawel Zarembski |
0:01f31e923fe2 | 193 | * Called automatically on USB Device Reset |
Pawel Zarembski |
0:01f31e923fe2 | 194 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 195 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 196 | |
Pawel Zarembski |
0:01f31e923fe2 | 197 | void USBD_Reset(void) |
Pawel Zarembski |
0:01f31e923fe2 | 198 | { |
Pawel Zarembski |
0:01f31e923fe2 | 199 | NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); |
Pawel Zarembski |
0:01f31e923fe2 | 200 | |
Pawel Zarembski |
0:01f31e923fe2 | 201 | /* Double Buffering is not yet supported */ |
Pawel Zarembski |
0:01f31e923fe2 | 202 | ISTR = 0; /* Clear Interrupt Status */ |
Pawel Zarembski |
0:01f31e923fe2 | 203 | CNTR = CNTR_CTRM | CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM | |
Pawel Zarembski |
0:01f31e923fe2 | 204 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 205 | ((USBD_RTX_DevTask != 0) ? CNTR_ERRM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 206 | ((USBD_RTX_DevTask != 0) ? CNTR_PMAOVRM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 207 | ((USBD_RTX_DevTask != 0) ? CNTR_SOFM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 208 | ((USBD_RTX_DevTask != 0) ? CNTR_ESOFM : 0); |
Pawel Zarembski |
0:01f31e923fe2 | 209 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 210 | ((USBD_P_Error_Event != 0) ? CNTR_ERRM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 211 | ((USBD_P_Error_Event != 0) ? CNTR_PMAOVRM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 212 | ((USBD_P_SOF_Event != 0) ? CNTR_SOFM : 0) | |
Pawel Zarembski |
0:01f31e923fe2 | 213 | ((USBD_P_SOF_Event != 0) ? CNTR_ESOFM : 0); |
Pawel Zarembski |
0:01f31e923fe2 | 214 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 215 | FreeBufAddr = EP_BUF_ADDR; |
Pawel Zarembski |
0:01f31e923fe2 | 216 | BTABLE = 0x00; /* set BTABLE Address */ |
Pawel Zarembski |
0:01f31e923fe2 | 217 | /* Setup Control Endpoint 0 */ |
Pawel Zarembski |
0:01f31e923fe2 | 218 | pBUF_DSCR->ADDR_TX = FreeBufAddr; |
Pawel Zarembski |
0:01f31e923fe2 | 219 | FreeBufAddr += USBD_MAX_PACKET0; |
Pawel Zarembski |
0:01f31e923fe2 | 220 | pBUF_DSCR->ADDR_RX = FreeBufAddr; |
Pawel Zarembski |
0:01f31e923fe2 | 221 | FreeBufAddr += USBD_MAX_PACKET0; |
Pawel Zarembski |
0:01f31e923fe2 | 222 | |
Pawel Zarembski |
0:01f31e923fe2 | 223 | if (USBD_MAX_PACKET0 > 62) { |
Pawel Zarembski |
0:01f31e923fe2 | 224 | pBUF_DSCR->COUNT_RX = ((USBD_MAX_PACKET0 << 5) - 1) | 0x8000; |
Pawel Zarembski |
0:01f31e923fe2 | 225 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 226 | pBUF_DSCR->COUNT_RX = USBD_MAX_PACKET0 << 9; |
Pawel Zarembski |
0:01f31e923fe2 | 227 | } |
Pawel Zarembski |
0:01f31e923fe2 | 228 | |
Pawel Zarembski |
0:01f31e923fe2 | 229 | EPxREG(0) = EP_CONTROL | EP_RX_VALID; |
Pawel Zarembski |
0:01f31e923fe2 | 230 | DADDR = DADDR_EF | 0; /* Enable USB Default Address */ |
Pawel Zarembski |
0:01f31e923fe2 | 231 | |
Pawel Zarembski |
0:01f31e923fe2 | 232 | NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); |
Pawel Zarembski |
0:01f31e923fe2 | 233 | } |
Pawel Zarembski |
0:01f31e923fe2 | 234 | |
Pawel Zarembski |
0:01f31e923fe2 | 235 | |
Pawel Zarembski |
0:01f31e923fe2 | 236 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 237 | * USB Device Suspend Function |
Pawel Zarembski |
0:01f31e923fe2 | 238 | * Called automatically on USB Device Suspend |
Pawel Zarembski |
0:01f31e923fe2 | 239 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 240 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 241 | |
Pawel Zarembski |
0:01f31e923fe2 | 242 | void USBD_Suspend(void) |
Pawel Zarembski |
0:01f31e923fe2 | 243 | { |
Pawel Zarembski |
0:01f31e923fe2 | 244 | CNTR |= CNTR_FSUSP; /* Force Suspend */ |
Pawel Zarembski |
0:01f31e923fe2 | 245 | CNTR |= CNTR_LPMODE; /* Low Power Mode */ |
Pawel Zarembski |
0:01f31e923fe2 | 246 | } |
Pawel Zarembski |
0:01f31e923fe2 | 247 | |
Pawel Zarembski |
0:01f31e923fe2 | 248 | |
Pawel Zarembski |
0:01f31e923fe2 | 249 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 250 | * USB Device Resume Function |
Pawel Zarembski |
0:01f31e923fe2 | 251 | * Called automatically on USB Device Resume |
Pawel Zarembski |
0:01f31e923fe2 | 252 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 253 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 254 | |
Pawel Zarembski |
0:01f31e923fe2 | 255 | void USBD_Resume(void) |
Pawel Zarembski |
0:01f31e923fe2 | 256 | { |
Pawel Zarembski |
0:01f31e923fe2 | 257 | /* Performed by Hardware */ |
Pawel Zarembski |
0:01f31e923fe2 | 258 | } |
Pawel Zarembski |
0:01f31e923fe2 | 259 | |
Pawel Zarembski |
0:01f31e923fe2 | 260 | |
Pawel Zarembski |
0:01f31e923fe2 | 261 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 262 | * USB Device Remote Wakeup Function |
Pawel Zarembski |
0:01f31e923fe2 | 263 | * Called automatically on USB Device Remote Wakeup |
Pawel Zarembski |
0:01f31e923fe2 | 264 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 265 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 266 | |
Pawel Zarembski |
0:01f31e923fe2 | 267 | void USBD_WakeUp(void) |
Pawel Zarembski |
0:01f31e923fe2 | 268 | { |
Pawel Zarembski |
0:01f31e923fe2 | 269 | CNTR &= ~CNTR_FSUSP; /* Clear Suspend */ |
Pawel Zarembski |
0:01f31e923fe2 | 270 | } |
Pawel Zarembski |
0:01f31e923fe2 | 271 | |
Pawel Zarembski |
0:01f31e923fe2 | 272 | |
Pawel Zarembski |
0:01f31e923fe2 | 273 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 274 | * USB Device Remote Wakeup Configuration Function |
Pawel Zarembski |
0:01f31e923fe2 | 275 | * Parameters: cfg: Device Enable/Disable |
Pawel Zarembski |
0:01f31e923fe2 | 276 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 277 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 278 | |
Pawel Zarembski |
0:01f31e923fe2 | 279 | void USBD_WakeUpCfg(BOOL cfg) |
Pawel Zarembski |
0:01f31e923fe2 | 280 | { |
Pawel Zarembski |
0:01f31e923fe2 | 281 | /* Not needed */ |
Pawel Zarembski |
0:01f31e923fe2 | 282 | } |
Pawel Zarembski |
0:01f31e923fe2 | 283 | |
Pawel Zarembski |
0:01f31e923fe2 | 284 | |
Pawel Zarembski |
0:01f31e923fe2 | 285 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 286 | * USB Device Set Address Function |
Pawel Zarembski |
0:01f31e923fe2 | 287 | * Parameters: adr: USB Device Address |
Pawel Zarembski |
0:01f31e923fe2 | 288 | * setup: Called in setup stage (!=0), else after status stage |
Pawel Zarembski |
0:01f31e923fe2 | 289 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 290 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 291 | |
Pawel Zarembski |
0:01f31e923fe2 | 292 | void USBD_SetAddress(U32 adr, U32 setup) |
Pawel Zarembski |
0:01f31e923fe2 | 293 | { |
Pawel Zarembski |
0:01f31e923fe2 | 294 | if (setup) { |
Pawel Zarembski |
0:01f31e923fe2 | 295 | return; |
Pawel Zarembski |
0:01f31e923fe2 | 296 | } |
Pawel Zarembski |
0:01f31e923fe2 | 297 | |
Pawel Zarembski |
0:01f31e923fe2 | 298 | DADDR = DADDR_EF | adr; |
Pawel Zarembski |
0:01f31e923fe2 | 299 | } |
Pawel Zarembski |
0:01f31e923fe2 | 300 | |
Pawel Zarembski |
0:01f31e923fe2 | 301 | |
Pawel Zarembski |
0:01f31e923fe2 | 302 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 303 | * USB Device Configure Function |
Pawel Zarembski |
0:01f31e923fe2 | 304 | * Parameters: cfg: Device Configure/Deconfigure |
Pawel Zarembski |
0:01f31e923fe2 | 305 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 306 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 307 | |
Pawel Zarembski |
0:01f31e923fe2 | 308 | void USBD_Configure(BOOL cfg) |
Pawel Zarembski |
0:01f31e923fe2 | 309 | { |
Pawel Zarembski |
0:01f31e923fe2 | 310 | if (cfg == __FALSE) { |
Pawel Zarembski |
0:01f31e923fe2 | 311 | FreeBufAddr = EP_BUF_ADDR; |
Pawel Zarembski |
0:01f31e923fe2 | 312 | FreeBufAddr += 2 * USBD_MAX_PACKET0; /* reset Buffer address */ |
Pawel Zarembski |
0:01f31e923fe2 | 313 | } |
Pawel Zarembski |
0:01f31e923fe2 | 314 | } |
Pawel Zarembski |
0:01f31e923fe2 | 315 | |
Pawel Zarembski |
0:01f31e923fe2 | 316 | |
Pawel Zarembski |
0:01f31e923fe2 | 317 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 318 | * Configure USB Device Endpoint according to Descriptor |
Pawel Zarembski |
0:01f31e923fe2 | 319 | * Parameters: pEPD: Pointer to Device Endpoint Descriptor |
Pawel Zarembski |
0:01f31e923fe2 | 320 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 321 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 322 | |
Pawel Zarembski |
0:01f31e923fe2 | 323 | void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD) |
Pawel Zarembski |
0:01f31e923fe2 | 324 | { |
Pawel Zarembski |
0:01f31e923fe2 | 325 | /* Double Buffering is not yet supported */ |
Pawel Zarembski |
0:01f31e923fe2 | 326 | U32 num, val; |
Pawel Zarembski |
0:01f31e923fe2 | 327 | num = pEPD->bEndpointAddress & 0x0F; |
Pawel Zarembski |
0:01f31e923fe2 | 328 | val = pEPD->wMaxPacketSize; |
Pawel Zarembski |
0:01f31e923fe2 | 329 | |
Pawel Zarembski |
0:01f31e923fe2 | 330 | if (pEPD->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) { |
Pawel Zarembski |
0:01f31e923fe2 | 331 | (pBUF_DSCR + num)->ADDR_TX = FreeBufAddr; |
Pawel Zarembski |
0:01f31e923fe2 | 332 | val = (val + 1) & ~1; |
Pawel Zarembski |
0:01f31e923fe2 | 333 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 334 | (pBUF_DSCR + num)->ADDR_RX = FreeBufAddr; |
Pawel Zarembski |
0:01f31e923fe2 | 335 | |
Pawel Zarembski |
0:01f31e923fe2 | 336 | if (val > 62) { |
Pawel Zarembski |
0:01f31e923fe2 | 337 | val = (val + 31) & ~31; |
Pawel Zarembski |
0:01f31e923fe2 | 338 | (pBUF_DSCR + num)->COUNT_RX = ((val << 5) - 1) | 0x8000; |
Pawel Zarembski |
0:01f31e923fe2 | 339 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 340 | val = (val + 1) & ~1; |
Pawel Zarembski |
0:01f31e923fe2 | 341 | (pBUF_DSCR + num)->COUNT_RX = val << 9; |
Pawel Zarembski |
0:01f31e923fe2 | 342 | } |
Pawel Zarembski |
0:01f31e923fe2 | 343 | } |
Pawel Zarembski |
0:01f31e923fe2 | 344 | |
Pawel Zarembski |
0:01f31e923fe2 | 345 | FreeBufAddr += val; |
Pawel Zarembski |
0:01f31e923fe2 | 346 | |
Pawel Zarembski |
0:01f31e923fe2 | 347 | switch (pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK) { |
Pawel Zarembski |
0:01f31e923fe2 | 348 | case USB_ENDPOINT_TYPE_CONTROL: |
Pawel Zarembski |
0:01f31e923fe2 | 349 | val = EP_CONTROL; |
Pawel Zarembski |
0:01f31e923fe2 | 350 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 351 | |
Pawel Zarembski |
0:01f31e923fe2 | 352 | case USB_ENDPOINT_TYPE_ISOCHRONOUS: |
Pawel Zarembski |
0:01f31e923fe2 | 353 | val = EP_ISOCHRONOUS; |
Pawel Zarembski |
0:01f31e923fe2 | 354 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 355 | |
Pawel Zarembski |
0:01f31e923fe2 | 356 | case USB_ENDPOINT_TYPE_BULK: |
Pawel Zarembski |
0:01f31e923fe2 | 357 | val = EP_BULK; |
Pawel Zarembski |
0:01f31e923fe2 | 358 | |
Pawel Zarembski |
0:01f31e923fe2 | 359 | if (USB_DBL_BUF_EP & (1 << num)) { |
Pawel Zarembski |
0:01f31e923fe2 | 360 | val |= EP_KIND; |
Pawel Zarembski |
0:01f31e923fe2 | 361 | } |
Pawel Zarembski |
0:01f31e923fe2 | 362 | |
Pawel Zarembski |
0:01f31e923fe2 | 363 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 364 | |
Pawel Zarembski |
0:01f31e923fe2 | 365 | case USB_ENDPOINT_TYPE_INTERRUPT: |
Pawel Zarembski |
0:01f31e923fe2 | 366 | val = EP_INTERRUPT; |
Pawel Zarembski |
0:01f31e923fe2 | 367 | break; |
Pawel Zarembski |
0:01f31e923fe2 | 368 | } |
Pawel Zarembski |
0:01f31e923fe2 | 369 | |
Pawel Zarembski |
0:01f31e923fe2 | 370 | val |= num; |
Pawel Zarembski |
0:01f31e923fe2 | 371 | EPxREG(num) = val; |
Pawel Zarembski |
0:01f31e923fe2 | 372 | } |
Pawel Zarembski |
0:01f31e923fe2 | 373 | |
Pawel Zarembski |
0:01f31e923fe2 | 374 | |
Pawel Zarembski |
0:01f31e923fe2 | 375 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 376 | * Set Direction for USB Device Control Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 377 | * Parameters: dir: Out (dir == 0), In (dir <> 0) |
Pawel Zarembski |
0:01f31e923fe2 | 378 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 379 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 380 | |
Pawel Zarembski |
0:01f31e923fe2 | 381 | void USBD_DirCtrlEP(U32 dir) |
Pawel Zarembski |
0:01f31e923fe2 | 382 | { |
Pawel Zarembski |
0:01f31e923fe2 | 383 | /* Not needed */ |
Pawel Zarembski |
0:01f31e923fe2 | 384 | } |
Pawel Zarembski |
0:01f31e923fe2 | 385 | |
Pawel Zarembski |
0:01f31e923fe2 | 386 | |
Pawel Zarembski |
0:01f31e923fe2 | 387 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 388 | * Enable USB Device Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 389 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 390 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 391 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 392 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 393 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 394 | |
Pawel Zarembski |
0:01f31e923fe2 | 395 | void USBD_EnableEP(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 396 | { |
Pawel Zarembski |
0:01f31e923fe2 | 397 | EP_Status(EPNum, EP_TX_NAK | EP_RX_VALID); /* EP is able to receive */ |
Pawel Zarembski |
0:01f31e923fe2 | 398 | } |
Pawel Zarembski |
0:01f31e923fe2 | 399 | |
Pawel Zarembski |
0:01f31e923fe2 | 400 | |
Pawel Zarembski |
0:01f31e923fe2 | 401 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 402 | * Disable USB Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 403 | * Parameters: EPNum: Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 404 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 405 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 406 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 407 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 408 | |
Pawel Zarembski |
0:01f31e923fe2 | 409 | void USBD_DisableEP(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 410 | { |
Pawel Zarembski |
0:01f31e923fe2 | 411 | EP_Status(EPNum, EP_TX_DIS | EP_RX_DIS); |
Pawel Zarembski |
0:01f31e923fe2 | 412 | } |
Pawel Zarembski |
0:01f31e923fe2 | 413 | |
Pawel Zarembski |
0:01f31e923fe2 | 414 | |
Pawel Zarembski |
0:01f31e923fe2 | 415 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 416 | * Reset USB Device Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 417 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 418 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 419 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 420 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 421 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 422 | |
Pawel Zarembski |
0:01f31e923fe2 | 423 | void USBD_ResetEP(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 424 | { |
Pawel Zarembski |
0:01f31e923fe2 | 425 | EP_Reset(EPNum); |
Pawel Zarembski |
0:01f31e923fe2 | 426 | } |
Pawel Zarembski |
0:01f31e923fe2 | 427 | |
Pawel Zarembski |
0:01f31e923fe2 | 428 | |
Pawel Zarembski |
0:01f31e923fe2 | 429 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 430 | * Set Stall for USB Device Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 431 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 432 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 433 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 434 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 435 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 436 | |
Pawel Zarembski |
0:01f31e923fe2 | 437 | void USBD_SetStallEP(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 438 | { |
Pawel Zarembski |
0:01f31e923fe2 | 439 | EP_Status(EPNum, EP_TX_STALL | EP_RX_STALL); |
Pawel Zarembski |
0:01f31e923fe2 | 440 | } |
Pawel Zarembski |
0:01f31e923fe2 | 441 | |
Pawel Zarembski |
0:01f31e923fe2 | 442 | |
Pawel Zarembski |
0:01f31e923fe2 | 443 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 444 | * Clear Stall for USB Device Endpoint |
Pawel Zarembski |
0:01f31e923fe2 | 445 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 446 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 447 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 448 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 449 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 450 | |
Pawel Zarembski |
0:01f31e923fe2 | 451 | void USBD_ClrStallEP(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 452 | { |
Pawel Zarembski |
0:01f31e923fe2 | 453 | EP_Reset(EPNum); /* reset DTog Bits */ |
Pawel Zarembski |
0:01f31e923fe2 | 454 | EP_Status(EPNum, EP_TX_VALID | EP_RX_VALID); |
Pawel Zarembski |
0:01f31e923fe2 | 455 | } |
Pawel Zarembski |
0:01f31e923fe2 | 456 | |
Pawel Zarembski |
0:01f31e923fe2 | 457 | |
Pawel Zarembski |
0:01f31e923fe2 | 458 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 459 | * Clear USB Device Endpoint Buffer |
Pawel Zarembski |
0:01f31e923fe2 | 460 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 461 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 462 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 463 | * Return Value: None |
Pawel Zarembski |
0:01f31e923fe2 | 464 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 465 | |
Pawel Zarembski |
0:01f31e923fe2 | 466 | void USBD_ClearEPBuf(U32 EPNum) |
Pawel Zarembski |
0:01f31e923fe2 | 467 | { |
Pawel Zarembski |
0:01f31e923fe2 | 468 | ; |
Pawel Zarembski |
0:01f31e923fe2 | 469 | } |
Pawel Zarembski |
0:01f31e923fe2 | 470 | |
Pawel Zarembski |
0:01f31e923fe2 | 471 | |
Pawel Zarembski |
0:01f31e923fe2 | 472 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 473 | * Read USB Device Endpoint Data |
Pawel Zarembski |
0:01f31e923fe2 | 474 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 475 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 476 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 477 | * pData: Pointer to Data Buffer |
Pawel Zarembski |
0:01f31e923fe2 | 478 | * Return Value: Number of bytes read |
Pawel Zarembski |
0:01f31e923fe2 | 479 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 480 | |
Pawel Zarembski |
0:01f31e923fe2 | 481 | U32 USBD_ReadEP(U32 EPNum, U8 *pData, U32 bufsz) |
Pawel Zarembski |
0:01f31e923fe2 | 482 | { |
Pawel Zarembski |
0:01f31e923fe2 | 483 | /* Double Buffering is not yet supported */ |
Pawel Zarembski |
0:01f31e923fe2 | 484 | U32 num, cnt, *pv, n; |
Pawel Zarembski |
0:01f31e923fe2 | 485 | num = EPNum & 0x0F; |
Pawel Zarembski |
0:01f31e923fe2 | 486 | pv = (U32 *)(USB_PMA_ADDR + 2 * ((pBUF_DSCR + num)->ADDR_RX)); |
Pawel Zarembski |
0:01f31e923fe2 | 487 | cnt = (pBUF_DSCR + num)->COUNT_RX & EP_COUNT_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 488 | if (cnt > bufsz) { |
Pawel Zarembski |
0:01f31e923fe2 | 489 | cnt = bufsz; |
Pawel Zarembski |
0:01f31e923fe2 | 490 | } |
Pawel Zarembski |
0:01f31e923fe2 | 491 | |
Pawel Zarembski |
0:01f31e923fe2 | 492 | for (n = 0; n < (cnt + 1) / 2; n++) { |
Pawel Zarembski |
0:01f31e923fe2 | 493 | *((__packed U16 *)pData) = *pv++; |
Pawel Zarembski |
0:01f31e923fe2 | 494 | pData += 2; |
Pawel Zarembski |
0:01f31e923fe2 | 495 | } |
Pawel Zarembski |
0:01f31e923fe2 | 496 | |
Pawel Zarembski |
0:01f31e923fe2 | 497 | EP_Status(EPNum, EP_RX_VALID); |
Pawel Zarembski |
0:01f31e923fe2 | 498 | return (cnt); |
Pawel Zarembski |
0:01f31e923fe2 | 499 | } |
Pawel Zarembski |
0:01f31e923fe2 | 500 | |
Pawel Zarembski |
0:01f31e923fe2 | 501 | |
Pawel Zarembski |
0:01f31e923fe2 | 502 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 503 | * Write USB Device Endpoint Data |
Pawel Zarembski |
0:01f31e923fe2 | 504 | * Parameters: EPNum: Device Endpoint Number |
Pawel Zarembski |
0:01f31e923fe2 | 505 | * EPNum.0..3: Address |
Pawel Zarembski |
0:01f31e923fe2 | 506 | * EPNum.7: Dir |
Pawel Zarembski |
0:01f31e923fe2 | 507 | * pData: Pointer to Data Buffer |
Pawel Zarembski |
0:01f31e923fe2 | 508 | * cnt: Number of bytes to write |
Pawel Zarembski |
0:01f31e923fe2 | 509 | * Return Value: Number of bytes written |
Pawel Zarembski |
0:01f31e923fe2 | 510 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 511 | |
Pawel Zarembski |
0:01f31e923fe2 | 512 | U32 USBD_WriteEP(U32 EPNum, U8 *pData, U32 cnt) |
Pawel Zarembski |
0:01f31e923fe2 | 513 | { |
Pawel Zarembski |
0:01f31e923fe2 | 514 | /* Double Buffering is not yet supported */ |
Pawel Zarembski |
0:01f31e923fe2 | 515 | U32 num, *pv, n; |
Pawel Zarembski |
0:01f31e923fe2 | 516 | U16 statusEP; |
Pawel Zarembski |
0:01f31e923fe2 | 517 | num = EPNum & 0x0F; |
Pawel Zarembski |
0:01f31e923fe2 | 518 | pv = (U32 *)(USB_PMA_ADDR + 2 * ((pBUF_DSCR + num)->ADDR_TX)); |
Pawel Zarembski |
0:01f31e923fe2 | 519 | |
Pawel Zarembski |
0:01f31e923fe2 | 520 | for (n = 0; n < (cnt + 1) / 2; n++) { |
Pawel Zarembski |
0:01f31e923fe2 | 521 | *pv++ = *((__packed U16 *)pData); |
Pawel Zarembski |
0:01f31e923fe2 | 522 | pData += 2; |
Pawel Zarembski |
0:01f31e923fe2 | 523 | } |
Pawel Zarembski |
0:01f31e923fe2 | 524 | |
Pawel Zarembski |
0:01f31e923fe2 | 525 | (pBUF_DSCR + num)->COUNT_TX = cnt; |
Pawel Zarembski |
0:01f31e923fe2 | 526 | statusEP = EPxREG(num); |
Pawel Zarembski |
0:01f31e923fe2 | 527 | |
Pawel Zarembski |
0:01f31e923fe2 | 528 | if ((statusEP & EP_STAT_TX) != EP_TX_STALL) { |
Pawel Zarembski |
0:01f31e923fe2 | 529 | EP_Status(EPNum, EP_TX_VALID); /* do not make EP valid if stalled */ |
Pawel Zarembski |
0:01f31e923fe2 | 530 | } |
Pawel Zarembski |
0:01f31e923fe2 | 531 | |
Pawel Zarembski |
0:01f31e923fe2 | 532 | return (cnt); |
Pawel Zarembski |
0:01f31e923fe2 | 533 | } |
Pawel Zarembski |
0:01f31e923fe2 | 534 | |
Pawel Zarembski |
0:01f31e923fe2 | 535 | |
Pawel Zarembski |
0:01f31e923fe2 | 536 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 537 | * Get USB Device Last Frame Number |
Pawel Zarembski |
0:01f31e923fe2 | 538 | * Parameters: None |
Pawel Zarembski |
0:01f31e923fe2 | 539 | * Return Value: Frame Number |
Pawel Zarembski |
0:01f31e923fe2 | 540 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 541 | |
Pawel Zarembski |
0:01f31e923fe2 | 542 | U32 USBD_GetFrame(void) |
Pawel Zarembski |
0:01f31e923fe2 | 543 | { |
Pawel Zarembski |
0:01f31e923fe2 | 544 | return (FNR & FNR_FN); |
Pawel Zarembski |
0:01f31e923fe2 | 545 | } |
Pawel Zarembski |
0:01f31e923fe2 | 546 | |
Pawel Zarembski |
0:01f31e923fe2 | 547 | |
Pawel Zarembski |
0:01f31e923fe2 | 548 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 549 | U32 LastError; /* Last Error */ |
Pawel Zarembski |
0:01f31e923fe2 | 550 | |
Pawel Zarembski |
0:01f31e923fe2 | 551 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 552 | * Get USB Last Error Code |
Pawel Zarembski |
0:01f31e923fe2 | 553 | * Parameters: None |
Pawel Zarembski |
0:01f31e923fe2 | 554 | * Return Value: Error Code |
Pawel Zarembski |
0:01f31e923fe2 | 555 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 556 | |
Pawel Zarembski |
0:01f31e923fe2 | 557 | U32 USBD_GetError(void) |
Pawel Zarembski |
0:01f31e923fe2 | 558 | { |
Pawel Zarembski |
0:01f31e923fe2 | 559 | return (LastError); |
Pawel Zarembski |
0:01f31e923fe2 | 560 | } |
Pawel Zarembski |
0:01f31e923fe2 | 561 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 562 | |
Pawel Zarembski |
0:01f31e923fe2 | 563 | |
Pawel Zarembski |
0:01f31e923fe2 | 564 | /* |
Pawel Zarembski |
0:01f31e923fe2 | 565 | * USB Device Interrupt Service Routine |
Pawel Zarembski |
0:01f31e923fe2 | 566 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 567 | |
Pawel Zarembski |
0:01f31e923fe2 | 568 | void USB_LP_CAN1_RX0_IRQHandler(void) |
Pawel Zarembski |
0:01f31e923fe2 | 569 | { |
Pawel Zarembski |
0:01f31e923fe2 | 570 | uint32_t istr; |
Pawel Zarembski |
0:01f31e923fe2 | 571 | uint32_t num; |
Pawel Zarembski |
0:01f31e923fe2 | 572 | uint32_t val; |
Pawel Zarembski |
0:01f31e923fe2 | 573 | |
Pawel Zarembski |
0:01f31e923fe2 | 574 | istr = ISTR; |
Pawel Zarembski |
0:01f31e923fe2 | 575 | // Zero out endpoint ID since this is read from the queue |
Pawel Zarembski |
0:01f31e923fe2 | 576 | LastIstr |= istr & ~(ISTR_DIR | ISTR_EP_ID); |
Pawel Zarembski |
0:01f31e923fe2 | 577 | // Clear interrupts that are pending |
Pawel Zarembski |
0:01f31e923fe2 | 578 | ISTR = ~(istr & USB_ISTR_W0C_MASK); |
Pawel Zarembski |
0:01f31e923fe2 | 579 | if (istr & ISTR_CTR) { |
Pawel Zarembski |
0:01f31e923fe2 | 580 | while ((istr = ISTR) & ISTR_CTR) { |
Pawel Zarembski |
0:01f31e923fe2 | 581 | num = istr & ISTR_EP_ID; |
Pawel Zarembski |
0:01f31e923fe2 | 582 | val = EPxREG(num); |
Pawel Zarembski |
0:01f31e923fe2 | 583 | |
Pawel Zarembski |
0:01f31e923fe2 | 584 | // Process and filter out the zero length status out endpoint to prevent |
Pawel Zarembski |
0:01f31e923fe2 | 585 | // the next SETUP packet from being dropped. |
Pawel Zarembski |
0:01f31e923fe2 | 586 | if ((0 == num) && (val & EP_CTR_RX) && !(val & EP_SETUP) |
Pawel Zarembski |
0:01f31e923fe2 | 587 | && (0 == ((pBUF_DSCR + num)->COUNT_RX & EP_COUNT_MASK))) { |
Pawel Zarembski |
0:01f31e923fe2 | 588 | if (val & EP_CTR_TX) { |
Pawel Zarembski |
0:01f31e923fe2 | 589 | // Drop the RX event but not TX |
Pawel Zarembski |
0:01f31e923fe2 | 590 | stat_enque((((val & VAL_MASK) & ~EP_CTR_RX) << VAL_SHIFT) | |
Pawel Zarembski |
0:01f31e923fe2 | 591 | ((num & EP_NUM_MASK) << EP_NUM_SHIFT)); |
Pawel Zarembski |
0:01f31e923fe2 | 592 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 593 | // Drop the event |
Pawel Zarembski |
0:01f31e923fe2 | 594 | } |
Pawel Zarembski |
0:01f31e923fe2 | 595 | } else { |
Pawel Zarembski |
0:01f31e923fe2 | 596 | stat_enque(((val & VAL_MASK) << VAL_SHIFT) | |
Pawel Zarembski |
0:01f31e923fe2 | 597 | ((num & EP_NUM_MASK) << EP_NUM_SHIFT)); |
Pawel Zarembski |
0:01f31e923fe2 | 598 | } |
Pawel Zarembski |
0:01f31e923fe2 | 599 | |
Pawel Zarembski |
0:01f31e923fe2 | 600 | |
Pawel Zarembski |
0:01f31e923fe2 | 601 | if (val & EP_CTR_RX) { |
Pawel Zarembski |
0:01f31e923fe2 | 602 | EPxREG(num) = EP_VAL_UNCHANGED(val) & ~EP_CTR_RX; |
Pawel Zarembski |
0:01f31e923fe2 | 603 | } |
Pawel Zarembski |
0:01f31e923fe2 | 604 | |
Pawel Zarembski |
0:01f31e923fe2 | 605 | if (val & EP_CTR_TX) { |
Pawel Zarembski |
0:01f31e923fe2 | 606 | EPxREG(num) = EP_VAL_UNCHANGED(val) & ~EP_CTR_TX; |
Pawel Zarembski |
0:01f31e923fe2 | 607 | } |
Pawel Zarembski |
0:01f31e923fe2 | 608 | } |
Pawel Zarembski |
0:01f31e923fe2 | 609 | } |
Pawel Zarembski |
0:01f31e923fe2 | 610 | |
Pawel Zarembski |
0:01f31e923fe2 | 611 | USBD_SignalHandler(); |
Pawel Zarembski |
0:01f31e923fe2 | 612 | } |
Pawel Zarembski |
0:01f31e923fe2 | 613 | |
Pawel Zarembski |
0:01f31e923fe2 | 614 | void USBD_Handler(void) |
Pawel Zarembski |
0:01f31e923fe2 | 615 | { |
Pawel Zarembski |
0:01f31e923fe2 | 616 | U32 istr, num, val, num_val; |
Pawel Zarembski |
0:01f31e923fe2 | 617 | cortex_int_state_t state; |
Pawel Zarembski |
0:01f31e923fe2 | 618 | |
Pawel Zarembski |
0:01f31e923fe2 | 619 | // Get ISTR |
Pawel Zarembski |
0:01f31e923fe2 | 620 | state = cortex_int_get_and_disable(); |
Pawel Zarembski |
0:01f31e923fe2 | 621 | istr = LastIstr; |
Pawel Zarembski |
0:01f31e923fe2 | 622 | LastIstr = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 623 | cortex_int_restore(state); |
Pawel Zarembski |
0:01f31e923fe2 | 624 | |
Pawel Zarembski |
0:01f31e923fe2 | 625 | /* USB Reset Request */ |
Pawel Zarembski |
0:01f31e923fe2 | 626 | if (istr & ISTR_RESET) { |
Pawel Zarembski |
0:01f31e923fe2 | 627 | USBD_Reset(); |
Pawel Zarembski |
0:01f31e923fe2 | 628 | usbd_reset_core(); |
Pawel Zarembski |
0:01f31e923fe2 | 629 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 630 | |
Pawel Zarembski |
0:01f31e923fe2 | 631 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 632 | isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 633 | } |
Pawel Zarembski |
0:01f31e923fe2 | 634 | |
Pawel Zarembski |
0:01f31e923fe2 | 635 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 636 | |
Pawel Zarembski |
0:01f31e923fe2 | 637 | if (USBD_P_Reset_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 638 | USBD_P_Reset_Event(); |
Pawel Zarembski |
0:01f31e923fe2 | 639 | } |
Pawel Zarembski |
0:01f31e923fe2 | 640 | |
Pawel Zarembski |
0:01f31e923fe2 | 641 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 642 | } |
Pawel Zarembski |
0:01f31e923fe2 | 643 | |
Pawel Zarembski |
0:01f31e923fe2 | 644 | /* USB Suspend Request */ |
Pawel Zarembski |
0:01f31e923fe2 | 645 | if (istr & ISTR_SUSP) { |
Pawel Zarembski |
0:01f31e923fe2 | 646 | USBD_Suspend(); |
Pawel Zarembski |
0:01f31e923fe2 | 647 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 648 | |
Pawel Zarembski |
0:01f31e923fe2 | 649 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 650 | isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 651 | } |
Pawel Zarembski |
0:01f31e923fe2 | 652 | |
Pawel Zarembski |
0:01f31e923fe2 | 653 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 654 | |
Pawel Zarembski |
0:01f31e923fe2 | 655 | if (USBD_P_Suspend_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 656 | USBD_P_Suspend_Event(); |
Pawel Zarembski |
0:01f31e923fe2 | 657 | } |
Pawel Zarembski |
0:01f31e923fe2 | 658 | |
Pawel Zarembski |
0:01f31e923fe2 | 659 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 660 | } |
Pawel Zarembski |
0:01f31e923fe2 | 661 | |
Pawel Zarembski |
0:01f31e923fe2 | 662 | /* USB Wakeup */ |
Pawel Zarembski |
0:01f31e923fe2 | 663 | if (istr & ISTR_WKUP) { |
Pawel Zarembski |
0:01f31e923fe2 | 664 | USBD_WakeUp(); |
Pawel Zarembski |
0:01f31e923fe2 | 665 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 666 | |
Pawel Zarembski |
0:01f31e923fe2 | 667 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 668 | isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 669 | } |
Pawel Zarembski |
0:01f31e923fe2 | 670 | |
Pawel Zarembski |
0:01f31e923fe2 | 671 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 672 | |
Pawel Zarembski |
0:01f31e923fe2 | 673 | if (USBD_P_Resume_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 674 | USBD_P_Resume_Event(); |
Pawel Zarembski |
0:01f31e923fe2 | 675 | } |
Pawel Zarembski |
0:01f31e923fe2 | 676 | |
Pawel Zarembski |
0:01f31e923fe2 | 677 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 678 | } |
Pawel Zarembski |
0:01f31e923fe2 | 679 | |
Pawel Zarembski |
0:01f31e923fe2 | 680 | /* Start of Frame */ |
Pawel Zarembski |
0:01f31e923fe2 | 681 | if (istr & ISTR_SOF) { |
Pawel Zarembski |
0:01f31e923fe2 | 682 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 683 | |
Pawel Zarembski |
0:01f31e923fe2 | 684 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 685 | isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 686 | } |
Pawel Zarembski |
0:01f31e923fe2 | 687 | |
Pawel Zarembski |
0:01f31e923fe2 | 688 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 689 | |
Pawel Zarembski |
0:01f31e923fe2 | 690 | if (USBD_P_SOF_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 691 | USBD_P_SOF_Event(); |
Pawel Zarembski |
0:01f31e923fe2 | 692 | } |
Pawel Zarembski |
0:01f31e923fe2 | 693 | |
Pawel Zarembski |
0:01f31e923fe2 | 694 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 695 | } |
Pawel Zarembski |
0:01f31e923fe2 | 696 | |
Pawel Zarembski |
0:01f31e923fe2 | 697 | /* PMA Over/underrun */ |
Pawel Zarembski |
0:01f31e923fe2 | 698 | if (istr & ISTR_PMAOVR) { |
Pawel Zarembski |
0:01f31e923fe2 | 699 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 700 | LastError = 2; |
Pawel Zarembski |
0:01f31e923fe2 | 701 | |
Pawel Zarembski |
0:01f31e923fe2 | 702 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 703 | isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 704 | } |
Pawel Zarembski |
0:01f31e923fe2 | 705 | |
Pawel Zarembski |
0:01f31e923fe2 | 706 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 707 | |
Pawel Zarembski |
0:01f31e923fe2 | 708 | if (USBD_P_Error_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 709 | USBD_P_Error_Event(2); |
Pawel Zarembski |
0:01f31e923fe2 | 710 | } |
Pawel Zarembski |
0:01f31e923fe2 | 711 | |
Pawel Zarembski |
0:01f31e923fe2 | 712 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 713 | } |
Pawel Zarembski |
0:01f31e923fe2 | 714 | |
Pawel Zarembski |
0:01f31e923fe2 | 715 | /* Error: No Answer, CRC Error, Bit Stuff Error, Frame Format Error */ |
Pawel Zarembski |
0:01f31e923fe2 | 716 | if (istr & ISTR_ERR) { |
Pawel Zarembski |
0:01f31e923fe2 | 717 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 718 | LastError = 1; |
Pawel Zarembski |
0:01f31e923fe2 | 719 | |
Pawel Zarembski |
0:01f31e923fe2 | 720 | if (USBD_RTX_DevTask) { |
Pawel Zarembski |
0:01f31e923fe2 | 721 | isr_evt_set(USBD_EVT_ERROR, USBD_RTX_DevTask); |
Pawel Zarembski |
0:01f31e923fe2 | 722 | } |
Pawel Zarembski |
0:01f31e923fe2 | 723 | |
Pawel Zarembski |
0:01f31e923fe2 | 724 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 725 | |
Pawel Zarembski |
0:01f31e923fe2 | 726 | if (USBD_P_Error_Event) { |
Pawel Zarembski |
0:01f31e923fe2 | 727 | USBD_P_Error_Event(1); |
Pawel Zarembski |
0:01f31e923fe2 | 728 | } |
Pawel Zarembski |
0:01f31e923fe2 | 729 | |
Pawel Zarembski |
0:01f31e923fe2 | 730 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 731 | } |
Pawel Zarembski |
0:01f31e923fe2 | 732 | |
Pawel Zarembski |
0:01f31e923fe2 | 733 | /* Endpoint Interrupts */ |
Pawel Zarembski |
0:01f31e923fe2 | 734 | while ((istr & ISTR_CTR) && !stat_is_empty()) { |
Pawel Zarembski |
0:01f31e923fe2 | 735 | num_val = stat_deque(); |
Pawel Zarembski |
0:01f31e923fe2 | 736 | num = (num_val >> EP_NUM_SHIFT) & EP_NUM_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 737 | val = (num_val >> VAL_SHIFT) & VAL_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 738 | if (val & EP_CTR_TX) { |
Pawel Zarembski |
0:01f31e923fe2 | 739 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 740 | |
Pawel Zarembski |
0:01f31e923fe2 | 741 | if (USBD_RTX_EPTask[num]) { |
Pawel Zarembski |
0:01f31e923fe2 | 742 | isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[num]); |
Pawel Zarembski |
0:01f31e923fe2 | 743 | } |
Pawel Zarembski |
0:01f31e923fe2 | 744 | |
Pawel Zarembski |
0:01f31e923fe2 | 745 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 746 | |
Pawel Zarembski |
0:01f31e923fe2 | 747 | if (USBD_P_EP[num]) { |
Pawel Zarembski |
0:01f31e923fe2 | 748 | USBD_P_EP[num](USBD_EVT_IN); |
Pawel Zarembski |
0:01f31e923fe2 | 749 | } |
Pawel Zarembski |
0:01f31e923fe2 | 750 | |
Pawel Zarembski |
0:01f31e923fe2 | 751 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 752 | } |
Pawel Zarembski |
0:01f31e923fe2 | 753 | |
Pawel Zarembski |
0:01f31e923fe2 | 754 | if (val & EP_CTR_RX) { |
Pawel Zarembski |
0:01f31e923fe2 | 755 | #ifdef __RTX |
Pawel Zarembski |
0:01f31e923fe2 | 756 | |
Pawel Zarembski |
0:01f31e923fe2 | 757 | if (USBD_RTX_EPTask[num]) { |
Pawel Zarembski |
0:01f31e923fe2 | 758 | isr_evt_set((val & EP_SETUP) ? USBD_EVT_SETUP : USBD_EVT_OUT, USBD_RTX_EPTask[num]); |
Pawel Zarembski |
0:01f31e923fe2 | 759 | } |
Pawel Zarembski |
0:01f31e923fe2 | 760 | |
Pawel Zarembski |
0:01f31e923fe2 | 761 | #else |
Pawel Zarembski |
0:01f31e923fe2 | 762 | |
Pawel Zarembski |
0:01f31e923fe2 | 763 | if (USBD_P_EP[num]) { |
Pawel Zarembski |
0:01f31e923fe2 | 764 | USBD_P_EP[num]((val & EP_SETUP) ? USBD_EVT_SETUP : USBD_EVT_OUT); |
Pawel Zarembski |
0:01f31e923fe2 | 765 | } |
Pawel Zarembski |
0:01f31e923fe2 | 766 | |
Pawel Zarembski |
0:01f31e923fe2 | 767 | #endif |
Pawel Zarembski |
0:01f31e923fe2 | 768 | } |
Pawel Zarembski |
0:01f31e923fe2 | 769 | } |
Pawel Zarembski |
0:01f31e923fe2 | 770 | } |