embkernel
 All Classes Functions Variables Typedefs Groups Pages
UsbHw.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "UsbHw.hpp"
7 #include "RtosInclude.hpp"
8 #include "UsbDevice.hpp"
9 #include "UsbMacros.hpp"
10 
11 UsbHw* UsbHw::sInstance;
12 
13 void UsbHw::init() {
14  sInstance = this;
15  reset();
16 }
17 
18 void UsbHw::reset() {
19  disableInterrupts();
20 
21  USB_DEVICE->DADDR = 0;
22  USB_DEVICE->CNTR = REG_CNTR_PDWN | REG_CNTR_FRES; //Power down and reset
24  USB_DEVICE->CNTR &= ~REG_CNTR_PDWN; //Exit power down
26  USB_DEVICE->CNTR &= ~REG_CNTR_FRES; //Exit reset
28  USB_DEVICE->ISTR = 0; //Reset any pending interrupt
29  USB_DEVICE->CNTR |= REG_CNTR_RESETM | REG_CNTR_SUSPM | REG_CNTR_WKUPM | REG_CNTR_CTRM;
30  USB_DEVICE->BTABLE = 0;
31 
32  epResetAll();
33 
34  NVIC ->IP[USB_HP_CAN1_TX_IRQn] = RTOS_INT_PRI;
35  NVIC ->IP[USB_LP_CAN1_RX0_IRQn] = RTOS_INT_PRI;
36  NVIC ->IP[USBWakeUp_IRQn] = RTOS_INT_PRI;
37  enableInterrupts();
38 
39  setAddress(0);
40 }
41 
42 void UsbHw::setAddress(int address) {
43  USB_DEVICE->DADDR = address | REG_DADDR_EF;
44 }
45 
46 void UsbHw::processEvents() {
47  uint16_t status = USB_DEVICE->ISTR;
48  if (status & REG_ISTR_CTR) {
49  uint8_t epIdx = status & REG_ISTR_EP_ID;
50  if (status & REG_ISTR_DIR) { //OUT direction
51  bool isSetup = ((USB_DEVICE->EPnR[epIdx].value & REG_EPXR_SETUP) != 0);
52  UsbDevice::onDataOut(epIdx, isSetup, USB_TABLE->EP[epIdx].COUNT_RX.countRx);
53  //Clear CTR_RX
54  USB_DEVICE->EPnR[epIdx].value = USB_DEVICE->EPnR[epIdx].value & (REG_EPXR_CTR_TX | REG_EPXR_EA | REG_EPXR_EP_KIND | REG_EPXR_EP_TYPE);
55  setEpRxStatus(epIdx, EP_STAT_RX_VALID);
56  }
57  else { //IN direction
58  //Clear CTR_TX
59  setEpTxStatus(epIdx, EP_STAT_TX_NAK);
60  USB_DEVICE->EPnR[epIdx].value = USB_DEVICE->EPnR[epIdx].value & (REG_EPXR_CTR_RX | REG_EPXR_EA | REG_EPXR_EP_KIND | REG_EPXR_EP_TYPE);
61  UsbDevice::onDataIn(epIdx, USB_TABLE->EP[epIdx].COUNT_TX);
62  }
63  }
64  enableInterrupts();
65 }
66 
67 uint16_t UsbHw::readEp(uint8_t ep, uint8_t* dst, uint16_t len) {
68  if (len > USB_TABLE->EP[ep].COUNT_RX.countRx) {
69  len = USB_TABLE->EP[ep].COUNT_RX.countRx;
70  }
71  readPktMem(dst, USB_TABLE->EP[ep].ADDR_RX, len);
72  return len;
73 }
74 
75 uint16_t UsbHw::writeEp(uint8_t ep, const uint8_t* src, uint16_t len) {
76  if (len > UsbDefs::MAX_PACKET_SIZE) {
77  len = UsbDefs::MAX_PACKET_SIZE;
78  }
79  writePktMem(src, USB_TABLE->EP[ep].ADDR_TX, len);
80  USB_TABLE->EP[ep].COUNT_TX = len;
81  setEpTxStatus(ep, EP_STAT_TX_VALID);
82  return len;
83 }
84 
85 uint16_t UsbHw::getEpInFree(uint8_t ep) {
86  if ((USB_DEVICE->EPnR[ep].value & REG_EPXR_STAT_TX) == EP_STAT_TX_VALID) {
87  return 0;
88  }
89  return mMaxInPktSize[ep];
90 }
91 
92 void UsbHw::epResetAll() {
93 //Init
94  USB_TABLE->EP[0].ADDR_RX = sizeof(*USB_TABLE);
95  USB_TABLE->EP[0].COUNT_RX.blSize = 1;
96  USB_TABLE->EP[0].COUNT_RX.numBlock = 1;
97  USB_TABLE->EP[0].ADDR_TX = sizeof(*USB_TABLE) + 64;
98  USB_TABLE->EP[0].COUNT_TX = 0;
99  USB_DEVICE->EPnR[0].value = EP_TYPE_CONTROL;
100  setEpTxStatus(0, EP_STAT_TX_NAK);
101  setEpRxStatus(0, EP_STAT_RX_VALID);
102 
103  mPacketMemPosition = sizeof(*USB_TABLE) + 128;
104 
105  for (unsigned int i = 1; i < (sizeof(USB_TABLE->EP) / sizeof(USB_TABLE->EP[0])); i++) {
106  setEpTxStatus(i, EP_STAT_TX_DISABLED);
107  setEpRxStatus(i, EP_STAT_RX_DISABLED);
108  USB_DEVICE->EPnR[i].value = i;
109  }
110 }
111 
112 void UsbHw::epConfig(const UsbDefs::USB_DESC_EP* epDesc) {
113  USB_ASSERT((mPacketMemPosition + epDesc->wMaxPacketSize) < PACKET_MEM_SIZE);
114  USB_ASSERT((epDesc->bEndpointAddress.epn > 0) && (epDesc->bEndpointAddress.epn <(sizeof(USB_TABLE->EP) / sizeof(USB_TABLE->EP[0]))))
115 
116  uint16_t epn = epDesc->bEndpointAddress.epn;
117  uint16_t epType = 0;
118  switch (epDesc->bmAttributes.transferType) {
119  case UsbDefs::EP_TRANSF_TYPE_CTRL:
120  epType = EP_TYPE_CONTROL;
121  break;
122  case UsbDefs::EP_TRANSF_TYPE_ISO:
123  epType = EP_TYPE_ISO;
124  break;
125  case UsbDefs::EP_TRANSF_TYPE_BULK:
126  epType = EP_TYPE_BULK;
127  break;
128  case UsbDefs::EP_TRANSF_TYPE_INT:
129  epType = EP_TYPE_INTERRUPT;
130  break;
131  }
132 
133  USB_DEVICE->EPnR[epn].value = (USB_DEVICE->EPnR[epn].value & (REG_EPXR_EA | REG_EPXR_EP_KIND)) | epType;
134 
135  if (epDesc->bEndpointAddress.dir == UsbDefs::DIR_DEVICE_TO_HOST) { //IN
136  USB_TABLE->EP[epn].ADDR_TX = mPacketMemPosition;
137  USB_TABLE->EP[epn].COUNT_TX = 0;
138  mMaxInPktSize[epn] = epDesc->wMaxPacketSize;
139  setEpTxStatus(epn, EP_STAT_TX_NAK);
140  }
141  else { //OUT
142  USB_TABLE->EP[epn].ADDR_RX = mPacketMemPosition;
143  if (epDesc->wMaxPacketSize < 62) {
144  USB_TABLE->EP[epn].COUNT_RX.blSize = 0;
145  USB_TABLE->EP[epn].COUNT_RX.numBlock = epDesc->wMaxPacketSize >> 1;
146  }
147  else {
148  USB_TABLE->EP[epn].COUNT_RX.blSize = 1;
149  USB_TABLE->EP[epn].COUNT_RX.numBlock = (epDesc->wMaxPacketSize >> 5) - 1;
150  }
151  setEpRxStatus(epn, EP_STAT_RX_VALID);
152  }
153  mPacketMemPosition += epDesc->wMaxPacketSize;
154 }
155 
156 void UsbHw::setEpRxStatus(uint8_t ep, uint16_t status) {
157  uint32_t toogler = (USB_DEVICE->EPnR[ep].value & REG_EPXR_STAT_RX) ^ status;
158  USB_DEVICE->EPnR[ep].value = (USB_DEVICE->EPnR[ep].value & (REG_EPXR_EA | REG_EPXR_EP_KIND | REG_EPXR_EP_TYPE)) | toogler;
159 }
160 
161 void UsbHw::setEpTxStatus(uint8_t ep, uint16_t status) {
162  uint32_t toogler = (USB_DEVICE->EPnR[ep].value & REG_EPXR_STAT_TX) ^ status;
163  USB_DEVICE->EPnR[ep].value = (USB_DEVICE->EPnR[ep].value & (REG_EPXR_EA | REG_EPXR_EP_KIND | REG_EPXR_EP_TYPE)) | toogler;
164 }
165 
166 void UsbHw::enableInterrupts() {
168  NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
169  NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
170  NVIC_EnableIRQ(USBWakeUp_IRQn);
172 }
173 
174 void UsbHw::disableInterrupts() {
176  NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
177  NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
178  NVIC_DisableIRQ(USBWakeUp_IRQn);
180 }
181 
182 void UsbHw::writePktMem(const uint8_t *src, uint16_t dstAddr, uint16_t len) {
183  uint32_t n = (len + 1) >> 1;
184  uint32_t i, temp1, temp2;
185  uint16_t *val;
186  val = (uint16_t *) (dstAddr * 2 + PACKET_MEM_BASE);
187  for (i = n; i != 0; i--) {
188  temp1 = (uint16_t) *src;
189  src++;
190  temp2 = temp1 | (uint16_t) *src << 8;
191  *val++ = temp2;
192  val++;
193  src++;
194  }
195 }
196 
197 void UsbHw::readPktMem(uint8_t *dst, uint16_t addr, uint16_t len) {
198  uint32_t n = (len + 1) >> 1;
199  uint32_t i;
200  uint32_t *val;
201  val = (uint32_t *) (addr * 2 + PACKET_MEM_BASE);
202  for (i = n; i != 0; i--) {
203  *(uint16_t*) dst++ = *val++;
204  dst++;
205  }
206 }
207 
208 void UsbHw::onEvent() {
209  uint16_t status = USB_DEVICE->ISTR;
210  if (status & REG_ISTR_RESET) {
211  reset();
212  }
213  else {
214  if (status & REG_ISTR_ESOF) {
215  Rtos::nop();
216  }
217  if (status & REG_ISTR_SOF) {
218  Rtos::nop();
219  }
220  if (status & REG_ISTR_RESET) {
221  Rtos::nop();
222  }
223  if (status & REG_ISTR_SUSP) {
224  reset();
225  UsbDevice::onReset();
226  }
227  if (status & REG_ISTR_WKUP) {
228  Rtos::nop();
229  }
230  if (status & REG_ISTR_ERR) {
231  Rtos::nop();
232  }
233  if (status & REG_ISTR_PMAOVR) {
234  Rtos::nop();
235  }
236  if (status & REG_ISTR_CTR) {
237  UsbDevice::onEventInterrupt();
238  disableInterrupts();
239  }
240  }
241 }
242 
243 void RtosInterrupt::IRQ_USB_HP_CAN1_TX() {
244  UsbHw::sInstance->onEvent();
245 }
246 
247 void RtosInterrupt::IRQ_USB_LP_CAN1_RX0() {
248  UsbHw::sInstance->onEvent();
249 }
250 
251 void RtosInterrupt::IRQ_USBWakeUp() {
252  Rtos::nop();
253 }
254