You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

usbdrvasm12.inc 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /* Name: usbdrvasm12.inc
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2004-12-29
  5. * Tabsize: 4
  6. * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
  7. * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
  8. * This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
  9. */
  10. /* Do not link this file! Link usbdrvasm.S instead, which includes the
  11. * appropriate implementation!
  12. */
  13. /*
  14. General Description:
  15. This file is the 12 MHz version of the asssembler part of the USB driver. It
  16. requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC
  17. oscillator).
  18. See usbdrv.h for a description of the entire driver.
  19. Since almost all of this code is timing critical, don't change unless you
  20. really know what you are doing! Many parts require not only a maximum number
  21. of CPU cycles, but even an exact number of cycles!
  22. Timing constraints according to spec (in bit times):
  23. timing subject min max CPUcycles
  24. ---------------------------------------------------------------------------
  25. EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2 16 16-128
  26. EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60
  27. DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60
  28. */
  29. ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
  30. ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
  31. ;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable
  32. ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes
  33. ;Numbers in brackets are maximum cycles since SOF.
  34. USB_INTR_VECTOR:
  35. ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt
  36. push YL ;2 [35] push only what is necessary to sync with edge ASAP
  37. in YL, SREG ;1 [37]
  38. push YL ;2 [39]
  39. ;----------------------------------------------------------------------------
  40. ; Synchronize with sync pattern:
  41. ;----------------------------------------------------------------------------
  42. ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
  43. ;sync up with J to K edge during sync pattern -- use fastest possible loops
  44. ;The first part waits at most 1 bit long since we must be in sync pattern.
  45. ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
  46. ;waitForJ, ensure that this prerequisite is met.
  47. waitForJ:
  48. inc YL
  49. sbis USBIN, USBMINUS
  50. brne waitForJ ; just make sure we have ANY timeout
  51. waitForK:
  52. ;The following code results in a sampling window of 1/4 bit which meets the spec.
  53. sbis USBIN, USBMINUS
  54. rjmp foundK
  55. sbis USBIN, USBMINUS
  56. rjmp foundK
  57. sbis USBIN, USBMINUS
  58. rjmp foundK
  59. sbis USBIN, USBMINUS
  60. rjmp foundK
  61. sbis USBIN, USBMINUS
  62. rjmp foundK
  63. #if USB_COUNT_SOF
  64. lds YL, usbSofCount
  65. inc YL
  66. sts usbSofCount, YL
  67. #endif /* USB_COUNT_SOF */
  68. #ifdef USB_SOF_HOOK
  69. USB_SOF_HOOK
  70. #endif
  71. rjmp sofError
  72. foundK:
  73. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
  74. ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
  75. ;are cycles from center of first sync (double K) bit after the instruction
  76. push YH ;2 [2]
  77. lds YL, usbInputBufOffset;2 [4]
  78. clr YH ;1 [5]
  79. subi YL, lo8(-(usbRxBuf));1 [6]
  80. sbci YH, hi8(-(usbRxBuf));1 [7]
  81. sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early]
  82. rjmp haveTwoBitsK ;2 [10]
  83. pop YH ;2 [11] undo the push from before
  84. rjmp waitForK ;2 [13] this was not the end of sync, retry
  85. haveTwoBitsK:
  86. ;----------------------------------------------------------------------------
  87. ; push more registers and initialize values while we sample the first bits:
  88. ;----------------------------------------------------------------------------
  89. push shift ;2 [16]
  90. push x1 ;2 [12]
  91. push x2 ;2 [14]
  92. in x1, USBIN ;1 [17] <-- sample bit 0
  93. ldi shift, 0xff ;1 [18]
  94. bst x1, USBMINUS ;1 [19]
  95. bld shift, 0 ;1 [20]
  96. push x3 ;2 [22]
  97. push cnt ;2 [24]
  98. in x2, USBIN ;1 [25] <-- sample bit 1
  99. ser x3 ;1 [26] [inserted init instruction]
  100. eor x1, x2 ;1 [27]
  101. bst x1, USBMINUS ;1 [28]
  102. bld shift, 1 ;1 [29]
  103. ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction]
  104. rjmp rxbit2 ;2 [32]
  105. ;----------------------------------------------------------------------------
  106. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  107. ;----------------------------------------------------------------------------
  108. unstuff0: ;1 (branch taken)
  109. andi x3, ~0x01 ;1 [15]
  110. mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit
  111. in x2, USBIN ;1 [17] <-- sample bit 1 again
  112. ori shift, 0x01 ;1 [18]
  113. rjmp didUnstuff0 ;2 [20]
  114. unstuff1: ;1 (branch taken)
  115. mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit
  116. andi x3, ~0x02 ;1 [22]
  117. ori shift, 0x02 ;1 [23]
  118. nop ;1 [24]
  119. in x1, USBIN ;1 [25] <-- sample bit 2 again
  120. rjmp didUnstuff1 ;2 [27]
  121. unstuff2: ;1 (branch taken)
  122. andi x3, ~0x04 ;1 [29]
  123. ori shift, 0x04 ;1 [30]
  124. mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit
  125. nop ;1 [32]
  126. in x2, USBIN ;1 [33] <-- sample bit 3
  127. rjmp didUnstuff2 ;2 [35]
  128. unstuff3: ;1 (branch taken)
  129. in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late]
  130. andi x3, ~0x08 ;1 [35]
  131. ori shift, 0x08 ;1 [36]
  132. rjmp didUnstuff3 ;2 [38]
  133. unstuff4: ;1 (branch taken)
  134. andi x3, ~0x10 ;1 [40]
  135. in x1, USBIN ;1 [41] <-- sample stuffed bit 4
  136. ori shift, 0x10 ;1 [42]
  137. rjmp didUnstuff4 ;2 [44]
  138. unstuff5: ;1 (branch taken)
  139. andi x3, ~0x20 ;1 [48]
  140. in x2, USBIN ;1 [49] <-- sample stuffed bit 5
  141. ori shift, 0x20 ;1 [50]
  142. rjmp didUnstuff5 ;2 [52]
  143. unstuff6: ;1 (branch taken)
  144. andi x3, ~0x40 ;1 [56]
  145. in x1, USBIN ;1 [57] <-- sample stuffed bit 6
  146. ori shift, 0x40 ;1 [58]
  147. rjmp didUnstuff6 ;2 [60]
  148. ; extra jobs done during bit interval:
  149. ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs]
  150. ; bit 1: se0 check
  151. ; bit 2: overflow check
  152. ; bit 3: recovery from delay [bit 0 tasks took too long]
  153. ; bit 4: none
  154. ; bit 5: none
  155. ; bit 6: none
  156. ; bit 7: jump, eor
  157. rxLoop:
  158. eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others
  159. in x1, USBIN ;1 [1] <-- sample bit 0
  160. st y+, x3 ;2 [3] store data
  161. ser x3 ;1 [4]
  162. nop ;1 [5]
  163. eor x2, x1 ;1 [6]
  164. bst x2, USBMINUS;1 [7]
  165. bld shift, 0 ;1 [8]
  166. in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed)
  167. andi x2, USBMASK ;1 [10]
  168. breq se0 ;1 [11] SE0 check for bit 1
  169. andi shift, 0xf9 ;1 [12]
  170. didUnstuff0:
  171. breq unstuff0 ;1 [13]
  172. eor x1, x2 ;1 [14]
  173. bst x1, USBMINUS;1 [15]
  174. bld shift, 1 ;1 [16]
  175. rxbit2:
  176. in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed)
  177. andi shift, 0xf3 ;1 [18]
  178. breq unstuff1 ;1 [19] do remaining work for bit 1
  179. didUnstuff1:
  180. subi cnt, 1 ;1 [20]
  181. brcs overflow ;1 [21] loop control
  182. eor x2, x1 ;1 [22]
  183. bst x2, USBMINUS;1 [23]
  184. bld shift, 2 ;1 [24]
  185. in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed)
  186. andi shift, 0xe7 ;1 [26]
  187. breq unstuff2 ;1 [27]
  188. didUnstuff2:
  189. eor x1, x2 ;1 [28]
  190. bst x1, USBMINUS;1 [29]
  191. bld shift, 3 ;1 [30]
  192. didUnstuff3:
  193. andi shift, 0xcf ;1 [31]
  194. breq unstuff3 ;1 [32]
  195. in x1, USBIN ;1 [33] <-- sample bit 4
  196. eor x2, x1 ;1 [34]
  197. bst x2, USBMINUS;1 [35]
  198. bld shift, 4 ;1 [36]
  199. didUnstuff4:
  200. andi shift, 0x9f ;1 [37]
  201. breq unstuff4 ;1 [38]
  202. nop2 ;2 [40]
  203. in x2, USBIN ;1 [41] <-- sample bit 5
  204. eor x1, x2 ;1 [42]
  205. bst x1, USBMINUS;1 [43]
  206. bld shift, 5 ;1 [44]
  207. didUnstuff5:
  208. andi shift, 0x3f ;1 [45]
  209. breq unstuff5 ;1 [46]
  210. nop2 ;2 [48]
  211. in x1, USBIN ;1 [49] <-- sample bit 6
  212. eor x2, x1 ;1 [50]
  213. bst x2, USBMINUS;1 [51]
  214. bld shift, 6 ;1 [52]
  215. didUnstuff6:
  216. cpi shift, 0x02 ;1 [53]
  217. brlo unstuff6 ;1 [54]
  218. nop2 ;2 [56]
  219. in x2, USBIN ;1 [57] <-- sample bit 7
  220. eor x1, x2 ;1 [58]
  221. bst x1, USBMINUS;1 [59]
  222. bld shift, 7 ;1 [60]
  223. didUnstuff7:
  224. cpi shift, 0x04 ;1 [61]
  225. brsh rxLoop ;2 [63] loop control
  226. unstuff7:
  227. andi x3, ~0x80 ;1 [63]
  228. ori shift, 0x80 ;1 [64]
  229. in x2, USBIN ;1 [65] <-- sample stuffed bit 7
  230. nop ;1 [66]
  231. rjmp didUnstuff7 ;2 [68]
  232. macro POP_STANDARD ; 12 cycles
  233. pop cnt
  234. pop x3
  235. pop x2
  236. pop x1
  237. pop shift
  238. pop YH
  239. endm
  240. macro POP_RETI ; 5 cycles
  241. pop YL
  242. out SREG, YL
  243. pop YL
  244. endm
  245. #include "asmcommon.inc"
  246. ;----------------------------------------------------------------------------
  247. ; Transmitting data
  248. ;----------------------------------------------------------------------------
  249. txByteLoop:
  250. txBitloop:
  251. stuffN1Delay: ; [03]
  252. ror shift ;[-5] [11] [59]
  253. brcc doExorN1 ;[-4] [60]
  254. subi x4, 1 ;[-3]
  255. brne commonN1 ;[-2]
  256. lsl shift ;[-1] compensate ror after rjmp stuffDelay
  257. nop ;[00] stuffing consists of just waiting 8 cycles
  258. rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
  259. sendNakAndReti: ;0 [-19] 19 cycles until SOP
  260. ldi x3, USBPID_NAK ;1 [-18]
  261. rjmp usbSendX3 ;2 [-16]
  262. sendAckAndReti: ;0 [-19] 19 cycles until SOP
  263. ldi x3, USBPID_ACK ;1 [-18]
  264. rjmp usbSendX3 ;2 [-16]
  265. sendCntAndReti: ;0 [-17] 17 cycles until SOP
  266. mov x3, cnt ;1 [-16]
  267. usbSendX3: ;0 [-16]
  268. ldi YL, 20 ;1 [-15] 'x3' is R20
  269. ldi YH, 0 ;1 [-14]
  270. ldi cnt, 2 ;1 [-13]
  271. ; rjmp usbSendAndReti fallthrough
  272. ; USB spec says:
  273. ; idle = J
  274. ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
  275. ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
  276. ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
  277. ;usbSend:
  278. ;pointer to data in 'Y'
  279. ;number of bytes in 'cnt' -- including sync byte
  280. ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt]
  281. ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
  282. usbSendAndReti:
  283. in x2, USBDDR ;[-12] 12 cycles until SOP
  284. ori x2, USBMASK ;[-11]
  285. sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
  286. out USBDDR, x2 ;[-8] <--- acquire bus
  287. in x1, USBOUT ;[-7] port mirror for tx loop
  288. ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror)
  289. ldi x2, USBMASK ;[-5]
  290. push x4 ;[-4]
  291. doExorN1:
  292. eor x1, x2 ;[-2] [06] [62]
  293. ldi x4, 6 ;[-1] [07] [63]
  294. commonN1:
  295. stuffN2Delay:
  296. out USBOUT, x1 ;[00] [08] [64] <--- set bit
  297. ror shift ;[01]
  298. brcc doExorN2 ;[02]
  299. subi x4, 1 ;[03]
  300. brne commonN2 ;[04]
  301. lsl shift ;[05] compensate ror after rjmp stuffDelay
  302. rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
  303. doExorN2:
  304. eor x1, x2 ;[04] [12]
  305. ldi x4, 6 ;[05] [13]
  306. commonN2:
  307. nop ;[06] [14]
  308. subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1
  309. out USBOUT, x1 ;[08] [16] <--- set bit
  310. brcs txBitloop ;[09] [25] [41]
  311. stuff6Delay:
  312. ror shift ;[42] [50]
  313. brcc doExor6 ;[43]
  314. subi x4, 1 ;[44]
  315. brne common6 ;[45]
  316. lsl shift ;[46] compensate ror after rjmp stuffDelay
  317. nop ;[47] stuffing consists of just waiting 8 cycles
  318. rjmp stuff6Delay ;[48] after ror, C bit is reliably clear
  319. doExor6:
  320. eor x1, x2 ;[45] [53]
  321. ldi x4, 6 ;[46]
  322. common6:
  323. stuff7Delay:
  324. ror shift ;[47] [55]
  325. out USBOUT, x1 ;[48] <--- set bit
  326. brcc doExor7 ;[49]
  327. subi x4, 1 ;[50]
  328. brne common7 ;[51]
  329. lsl shift ;[52] compensate ror after rjmp stuffDelay
  330. rjmp stuff7Delay ;[53] after ror, C bit is reliably clear
  331. doExor7:
  332. eor x1, x2 ;[51] [59]
  333. ldi x4, 6 ;[52]
  334. common7:
  335. ld shift, y+ ;[53]
  336. tst cnt ;[55]
  337. out USBOUT, x1 ;[56] <--- set bit
  338. brne txByteLoop ;[57]
  339. ;make SE0:
  340. cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles]
  341. lds x2, usbNewDeviceAddr;[59]
  342. lsl x2 ;[61] we compare with left shifted address
  343. subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3
  344. sbci YH, 0 ;[63]
  345. out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
  346. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  347. ;set address only after data packet was sent, not after handshake
  348. breq skipAddrAssign ;[01]
  349. sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
  350. skipAddrAssign:
  351. ;end of usbDeviceAddress transfer
  352. ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
  353. USB_STORE_PENDING(x2) ;[04]
  354. ori x1, USBIDLE ;[05]
  355. in x2, USBDDR ;[06]
  356. cbr x2, USBMASK ;[07] set both pins to input
  357. mov x3, x1 ;[08]
  358. cbr x3, USBMASK ;[09] configure no pullup on both pins
  359. pop x4 ;[10]
  360. nop2 ;[12]
  361. nop2 ;[14]
  362. out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
  363. out USBDDR, x2 ;[17] <-- release bus now
  364. out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
  365. rjmp doReturn