Ei kuvausta
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 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /* Name: usbdrvasm12.inc
  2. * Project: AVR USB driver
  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) or proprietary (CommercialLicense.txt)
  8. * This Revision: $Id: usbdrvasm12.inc 483 2008-02-05 15:05:32Z 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. ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
  45. waitForJ:
  46. sbis USBIN, USBMINUS ;1 [40] wait for D- == 1
  47. rjmp waitForJ ;2
  48. waitForK:
  49. ;The following code results in a sampling window of 1/4 bit which meets the spec.
  50. sbis USBIN, USBMINUS
  51. rjmp foundK
  52. sbis USBIN, USBMINUS
  53. rjmp foundK
  54. sbis USBIN, USBMINUS
  55. rjmp foundK
  56. sbis USBIN, USBMINUS
  57. rjmp foundK
  58. sbis USBIN, USBMINUS
  59. rjmp foundK
  60. #if USB_COUNT_SOF
  61. lds YL, usbSofCount
  62. inc YL
  63. sts usbSofCount, YL
  64. #endif /* USB_COUNT_SOF */
  65. rjmp sofError
  66. foundK:
  67. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
  68. ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
  69. ;are cycles from center of first sync (double K) bit after the instruction
  70. push YH ;2 [2]
  71. lds YL, usbInputBufOffset;2 [4]
  72. clr YH ;1 [5]
  73. subi YL, lo8(-(usbRxBuf));1 [6]
  74. sbci YH, hi8(-(usbRxBuf));1 [7]
  75. sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early]
  76. rjmp haveTwoBitsK ;2 [10]
  77. pop YH ;2 [11] undo the push from before
  78. rjmp waitForK ;2 [13] this was not the end of sync, retry
  79. haveTwoBitsK:
  80. ;----------------------------------------------------------------------------
  81. ; push more registers and initialize values while we sample the first bits:
  82. ;----------------------------------------------------------------------------
  83. push shift ;2 [16]
  84. push x1 ;2 [12]
  85. push x2 ;2 [14]
  86. in x1, USBIN ;1 [17] <-- sample bit 0
  87. ldi shift, 0xff ;1 [18]
  88. bst x1, USBMINUS ;1 [19]
  89. bld shift, 0 ;1 [20]
  90. push x3 ;2 [22]
  91. push cnt ;2 [24]
  92. in x2, USBIN ;1 [25] <-- sample bit 1
  93. ser x3 ;1 [26] [inserted init instruction]
  94. eor x1, x2 ;1 [27]
  95. bst x1, USBMINUS ;1 [28]
  96. bld shift, 1 ;1 [29]
  97. ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction]
  98. rjmp rxbit2 ;2 [32]
  99. ;----------------------------------------------------------------------------
  100. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  101. ;----------------------------------------------------------------------------
  102. unstuff0: ;1 (branch taken)
  103. andi x3, ~0x01 ;1 [15]
  104. mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit
  105. in x2, USBIN ;1 [17] <-- sample bit 1 again
  106. ori shift, 0x01 ;1 [18]
  107. rjmp didUnstuff0 ;2 [20]
  108. unstuff1: ;1 (branch taken)
  109. mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit
  110. andi x3, ~0x02 ;1 [22]
  111. ori shift, 0x02 ;1 [23]
  112. nop ;1 [24]
  113. in x1, USBIN ;1 [25] <-- sample bit 2 again
  114. rjmp didUnstuff1 ;2 [27]
  115. unstuff2: ;1 (branch taken)
  116. andi x3, ~0x04 ;1 [29]
  117. ori shift, 0x04 ;1 [30]
  118. mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit
  119. nop ;1 [32]
  120. in x2, USBIN ;1 [33] <-- sample bit 3
  121. rjmp didUnstuff2 ;2 [35]
  122. unstuff3: ;1 (branch taken)
  123. in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late]
  124. andi x3, ~0x08 ;1 [35]
  125. ori shift, 0x08 ;1 [36]
  126. rjmp didUnstuff3 ;2 [38]
  127. unstuff4: ;1 (branch taken)
  128. andi x3, ~0x10 ;1 [40]
  129. in x1, USBIN ;1 [41] <-- sample stuffed bit 4
  130. ori shift, 0x10 ;1 [42]
  131. rjmp didUnstuff4 ;2 [44]
  132. unstuff5: ;1 (branch taken)
  133. andi x3, ~0x20 ;1 [48]
  134. in x2, USBIN ;1 [49] <-- sample stuffed bit 5
  135. ori shift, 0x20 ;1 [50]
  136. rjmp didUnstuff5 ;2 [52]
  137. unstuff6: ;1 (branch taken)
  138. andi x3, ~0x40 ;1 [56]
  139. in x1, USBIN ;1 [57] <-- sample stuffed bit 6
  140. ori shift, 0x40 ;1 [58]
  141. rjmp didUnstuff6 ;2 [60]
  142. ; extra jobs done during bit interval:
  143. ; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs]
  144. ; bit 1: se0 check
  145. ; bit 2: overflow check
  146. ; bit 3: recovery from delay [bit 0 tasks took too long]
  147. ; bit 4: none
  148. ; bit 5: none
  149. ; bit 6: none
  150. ; bit 7: jump, eor
  151. rxLoop:
  152. eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others
  153. in x1, USBIN ;1 [1] <-- sample bit 0
  154. st y+, x3 ;2 [3] store data
  155. ser x3 ;1 [4]
  156. nop ;1 [5]
  157. eor x2, x1 ;1 [6]
  158. bst x2, USBMINUS;1 [7]
  159. bld shift, 0 ;1 [8]
  160. in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed)
  161. andi x2, USBMASK ;1 [10]
  162. breq se0 ;1 [11] SE0 check for bit 1
  163. andi shift, 0xf9 ;1 [12]
  164. didUnstuff0:
  165. breq unstuff0 ;1 [13]
  166. eor x1, x2 ;1 [14]
  167. bst x1, USBMINUS;1 [15]
  168. bld shift, 1 ;1 [16]
  169. rxbit2:
  170. in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed)
  171. andi shift, 0xf3 ;1 [18]
  172. breq unstuff1 ;1 [19] do remaining work for bit 1
  173. didUnstuff1:
  174. subi cnt, 1 ;1 [20]
  175. brcs overflow ;1 [21] loop control
  176. eor x2, x1 ;1 [22]
  177. bst x2, USBMINUS;1 [23]
  178. bld shift, 2 ;1 [24]
  179. in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed)
  180. andi shift, 0xe7 ;1 [26]
  181. breq unstuff2 ;1 [27]
  182. didUnstuff2:
  183. eor x1, x2 ;1 [28]
  184. bst x1, USBMINUS;1 [29]
  185. bld shift, 3 ;1 [30]
  186. didUnstuff3:
  187. andi shift, 0xcf ;1 [31]
  188. breq unstuff3 ;1 [32]
  189. in x1, USBIN ;1 [33] <-- sample bit 4
  190. eor x2, x1 ;1 [34]
  191. bst x2, USBMINUS;1 [35]
  192. bld shift, 4 ;1 [36]
  193. didUnstuff4:
  194. andi shift, 0x9f ;1 [37]
  195. breq unstuff4 ;1 [38]
  196. nop2 ;2 [40]
  197. in x2, USBIN ;1 [41] <-- sample bit 5
  198. eor x1, x2 ;1 [42]
  199. bst x1, USBMINUS;1 [43]
  200. bld shift, 5 ;1 [44]
  201. didUnstuff5:
  202. andi shift, 0x3f ;1 [45]
  203. breq unstuff5 ;1 [46]
  204. nop2 ;2 [48]
  205. in x1, USBIN ;1 [49] <-- sample bit 6
  206. eor x2, x1 ;1 [50]
  207. bst x2, USBMINUS;1 [51]
  208. bld shift, 6 ;1 [52]
  209. didUnstuff6:
  210. cpi shift, 0x02 ;1 [53]
  211. brlo unstuff6 ;1 [54]
  212. nop2 ;2 [56]
  213. in x2, USBIN ;1 [57] <-- sample bit 7
  214. eor x1, x2 ;1 [58]
  215. bst x1, USBMINUS;1 [59]
  216. bld shift, 7 ;1 [60]
  217. didUnstuff7:
  218. cpi shift, 0x04 ;1 [61]
  219. brsh rxLoop ;2 [63] loop control
  220. unstuff7:
  221. andi x3, ~0x80 ;1 [63]
  222. ori shift, 0x80 ;1 [64]
  223. in x2, USBIN ;1 [65] <-- sample stuffed bit 7
  224. nop ;1 [66]
  225. rjmp didUnstuff7 ;2 [68]
  226. macro POP_STANDARD ; 12 cycles
  227. pop cnt
  228. pop x3
  229. pop x2
  230. pop x1
  231. pop shift
  232. pop YH
  233. endm
  234. macro POP_RETI ; 5 cycles
  235. pop YL
  236. out SREG, YL
  237. pop YL
  238. endm
  239. #include "asmcommon.inc"
  240. ;----------------------------------------------------------------------------
  241. ; Transmitting data
  242. ;----------------------------------------------------------------------------
  243. bitstuff0: ;1 (for branch taken)
  244. eor x1, x4 ;1
  245. ldi x2, 0 ;1
  246. out USBOUT, x1 ;1 <-- out
  247. rjmp didStuff0 ;2 branch back 2 cycles earlier
  248. bitstuff1: ;1 (for branch taken)
  249. eor x1, x4 ;1
  250. rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2
  251. bitstuff2: ;1 (for branch taken)
  252. eor x1, x4 ;1
  253. rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2
  254. bitstuff3: ;1 (for branch taken)
  255. eor x1, x4 ;1
  256. rjmp didStuff3 ;2 jump back earlier and ror 0 into x2
  257. bitstuff4: ;1 (for branch taken)
  258. eor x1, x4 ;1
  259. ldi x2, 0 ;1
  260. out USBOUT, x1 ;1 <-- out
  261. rjmp didStuff4 ;2 jump back 2 cycles earlier
  262. sendNakAndReti: ;0 [-19] 19 cycles until SOP
  263. ldi x3, USBPID_NAK ;1 [-18]
  264. rjmp usbSendX3 ;2 [-16]
  265. sendAckAndReti: ;0 [-19] 19 cycles until SOP
  266. ldi x3, USBPID_ACK ;1 [-18]
  267. rjmp usbSendX3 ;2 [-16]
  268. sendCntAndReti: ;0 [-17] 17 cycles until SOP
  269. mov x3, cnt ;1 [-16]
  270. usbSendX3: ;0 [-16]
  271. ldi YL, 20 ;1 [-15] 'x3' is R20
  272. ldi YH, 0 ;1 [-14]
  273. ldi cnt, 2 ;1 [-13]
  274. ; rjmp usbSendAndReti fallthrough
  275. ; USB spec says:
  276. ; idle = J
  277. ; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
  278. ; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
  279. ; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
  280. ;usbSend:
  281. ;pointer to data in 'Y'
  282. ;number of bytes in 'cnt' -- including sync byte
  283. ;uses: x1...x4, shift, cnt, Y
  284. ;Numbers in brackets are time since first bit of sync pattern is sent
  285. usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP
  286. in x2, USBDDR ;1 [-12]
  287. ori x2, USBMASK ;1 [-11]
  288. sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups)
  289. in x1, USBOUT ;1 [-8] port mirror for tx loop
  290. out USBDDR, x2 ;1 [-7] <- acquire bus
  291. ; need not init x2 (bitstuff history) because sync starts with 0
  292. push x4 ;2 [-5]
  293. ldi x4, USBMASK ;1 [-4] exor mask
  294. ldi shift, 0x80 ;1 [-3] sync byte is first byte sent
  295. txLoop: ; [62]
  296. sbrs shift, 0 ;1 [-2] [62]
  297. eor x1, x4 ;1 [-1] [63]
  298. out USBOUT, x1 ;1 [0] <-- out bit 0
  299. ror shift ;1 [1]
  300. ror x2 ;1 [2]
  301. didStuff0:
  302. cpi x2, 0xfc ;1 [3]
  303. brsh bitstuff0 ;1 [4]
  304. sbrs shift, 0 ;1 [5]
  305. eor x1, x4 ;1 [6]
  306. ror shift ;1 [7]
  307. didStuff1:
  308. out USBOUT, x1 ;1 [8] <-- out bit 1
  309. ror x2 ;1 [9]
  310. cpi x2, 0xfc ;1 [10]
  311. brsh bitstuff1 ;1 [11]
  312. sbrs shift, 0 ;1 [12]
  313. eor x1, x4 ;1 [13]
  314. ror shift ;1 [14]
  315. didStuff2:
  316. ror x2 ;1 [15]
  317. out USBOUT, x1 ;1 [16] <-- out bit 2
  318. cpi x2, 0xfc ;1 [17]
  319. brsh bitstuff2 ;1 [18]
  320. sbrs shift, 0 ;1 [19]
  321. eor x1, x4 ;1 [20]
  322. ror shift ;1 [21]
  323. didStuff3:
  324. ror x2 ;1 [22]
  325. cpi x2, 0xfc ;1 [23]
  326. out USBOUT, x1 ;1 [24] <-- out bit 3
  327. brsh bitstuff3 ;1 [25]
  328. nop2 ;2 [27]
  329. ld x3, y+ ;2 [29]
  330. sbrs shift, 0 ;1 [30]
  331. eor x1, x4 ;1 [31]
  332. out USBOUT, x1 ;1 [32] <-- out bit 4
  333. ror shift ;1 [33]
  334. ror x2 ;1 [34]
  335. didStuff4:
  336. cpi x2, 0xfc ;1 [35]
  337. brsh bitstuff4 ;1 [36]
  338. sbrs shift, 0 ;1 [37]
  339. eor x1, x4 ;1 [38]
  340. ror shift ;1 [39]
  341. didStuff5:
  342. out USBOUT, x1 ;1 [40] <-- out bit 5
  343. ror x2 ;1 [41]
  344. cpi x2, 0xfc ;1 [42]
  345. brsh bitstuff5 ;1 [43]
  346. sbrs shift, 0 ;1 [44]
  347. eor x1, x4 ;1 [45]
  348. ror shift ;1 [46]
  349. didStuff6:
  350. ror x2 ;1 [47]
  351. out USBOUT, x1 ;1 [48] <-- out bit 6
  352. cpi x2, 0xfc ;1 [49]
  353. brsh bitstuff6 ;1 [50]
  354. sbrs shift, 0 ;1 [51]
  355. eor x1, x4 ;1 [52]
  356. ror shift ;1 [53]
  357. didStuff7:
  358. ror x2 ;1 [54]
  359. cpi x2, 0xfc ;1 [55]
  360. out USBOUT, x1 ;1 [56] <-- out bit 7
  361. brsh bitstuff7 ;1 [57]
  362. mov shift, x3 ;1 [58]
  363. dec cnt ;1 [59]
  364. brne txLoop ;1/2 [60/61]
  365. ;make SE0:
  366. cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles]
  367. pop x4 ;2 [63]
  368. ;brackets are cycles from start of SE0 now
  369. out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
  370. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  371. ;set address only after data packet was sent, not after handshake
  372. lds x2, usbNewDeviceAddr;2 [2]
  373. lsl x2; ;1 [3] we compare with left shifted address
  374. subi YL, 20 + 2 ;1 [4] Only assign address on data packets, not ACK/NAK in x3
  375. sbci YH, 0 ;1 [5]
  376. breq skipAddrAssign ;2 [7]
  377. sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
  378. skipAddrAssign:
  379. ;end of usbDeviceAddress transfer
  380. ldi x2, 1<<USB_INTR_PENDING_BIT;1 [8] int0 occurred during TX -- clear pending flag
  381. USB_STORE_PENDING(x2) ;1 [9]
  382. ori x1, USBIDLE ;1 [10]
  383. in x2, USBDDR ;1 [11]
  384. cbr x2, USBMASK ;1 [12] set both pins to input
  385. mov x3, x1 ;1 [13]
  386. cbr x3, USBMASK ;1 [14] configure no pullup on both pins
  387. out USBOUT, x1 ;1 [15] <-- out J (idle) -- end of SE0 (EOP signal)
  388. out USBDDR, x2 ;1 [16] <-- release bus now
  389. out USBOUT, x3 ;1 [17] <-- ensure no pull-up resistors are active
  390. rjmp doReturn
  391. bitstuff5: ;1 (for branch taken)
  392. eor x1, x4 ;1
  393. rjmp didStuff5 ;2 same trick as in bitstuff1...
  394. bitstuff6: ;1 (for branch taken)
  395. eor x1, x4 ;1
  396. rjmp didStuff6 ;2 same trick as above...
  397. bitstuff7: ;1 (for branch taken)
  398. eor x1, x4 ;1
  399. rjmp didStuff7 ;2 same trick as above...