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.

usbdrvasm165.inc 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /* Name: usbdrvasm165.inc
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-04-22
  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. * Revision: $Id: usbdrvasm165.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 16.5 MHz version of the USB driver. It is intended for the
  16. ATTiny45 and similar controllers running on 16.5 MHz internal RC oscillator.
  17. This version contains a phase locked loop in the receiver routine to cope with
  18. slight clock rate deviations of up to +/- 1%.
  19. See usbdrv.h for a description of the entire driver.
  20. Since almost all of this code is timing critical, don't change unless you
  21. really know what you are doing! Many parts require not only a maximum number
  22. of CPU cycles, but even an exact number of cycles!
  23. */
  24. ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
  25. ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
  26. ;max allowable interrupt latency: 59 cycles -> max 52 cycles interrupt disable
  27. ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes
  28. ;nominal frequency: 16.5 MHz -> 11 cycles per bit
  29. ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%)
  30. ; Numbers in brackets are clocks counted from center of last sync bit
  31. ; when instruction starts
  32. USB_INTR_VECTOR:
  33. ;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt
  34. push YL ;[-23] push only what is necessary to sync with edge ASAP
  35. in YL, SREG ;[-21]
  36. push YL ;[-20]
  37. ;----------------------------------------------------------------------------
  38. ; Synchronize with sync pattern:
  39. ;----------------------------------------------------------------------------
  40. ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
  41. ;sync up with J to K edge during sync pattern -- use fastest possible loops
  42. ;The first part waits at most 1 bit long since we must be in sync pattern.
  43. ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
  44. ;waitForJ, ensure that this prerequisite is met.
  45. waitForJ:
  46. inc YL
  47. sbis USBIN, USBMINUS
  48. brne waitForJ ; just make sure we have ANY timeout
  49. waitForK:
  50. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
  51. sbis USBIN, USBMINUS ;[-15]
  52. rjmp foundK ;[-14]
  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: ;[-12]
  73. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 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 r0 ;[-12]
  77. ; [---] ;[-11]
  78. push YH ;[-10]
  79. ; [---] ;[-9]
  80. lds YL, usbInputBufOffset;[-8]
  81. ; [---] ;[-7]
  82. clr YH ;[-6]
  83. subi YL, lo8(-(usbRxBuf));[-5] [rx loop init]
  84. sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init]
  85. mov r0, x2 ;[-3] [rx loop init]
  86. sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
  87. rjmp haveTwoBitsK ;[-1]
  88. pop YH ;[0] undo the pushes from before
  89. pop r0 ;[2]
  90. rjmp waitForK ;[4] this was not the end of sync, retry
  91. ; The entire loop from waitForK until rjmp waitForK above must not exceed two
  92. ; bit times (= 22 cycles).
  93. ;----------------------------------------------------------------------------
  94. ; push more registers and initialize values while we sample the first bits:
  95. ;----------------------------------------------------------------------------
  96. haveTwoBitsK: ;[1]
  97. push shift ;[1]
  98. push x1 ;[3]
  99. push x2 ;[5]
  100. push x3 ;[7]
  101. ldi shift, 0xff ;[9] [rx loop init]
  102. ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag
  103. in x1, USBIN ;[11] <-- sample bit 0
  104. bst x1, USBMINUS ;[12]
  105. bld shift, 0 ;[13]
  106. push x4 ;[14] == phase
  107. ; [---] ;[15]
  108. push cnt ;[16]
  109. ; [---] ;[17]
  110. ldi phase, 0 ;[18] [rx loop init]
  111. ldi cnt, USB_BUFSIZE;[19] [rx loop init]
  112. rjmp rxbit1 ;[20]
  113. ; [---] ;[21]
  114. ;----------------------------------------------------------------------------
  115. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  116. ;----------------------------------------------------------------------------
  117. /*
  118. byte oriented operations done during loop:
  119. bit 0: store data
  120. bit 1: SE0 check
  121. bit 2: overflow check
  122. bit 3: catch up
  123. bit 4: rjmp to achieve conditional jump range
  124. bit 5: PLL
  125. bit 6: catch up
  126. bit 7: jump, fixup bitstuff
  127. ; 87 [+ 2] cycles
  128. ------------------------------------------------------------------
  129. */
  130. continueWithBit5:
  131. in x2, USBIN ;[055] <-- bit 5
  132. eor r0, x2 ;[056]
  133. or phase, r0 ;[057]
  134. sbrc phase, USBMINUS ;[058]
  135. lpm ;[059] optional nop3; modifies r0
  136. in phase, USBIN ;[060] <-- phase
  137. eor x1, x2 ;[061]
  138. bst x1, USBMINUS ;[062]
  139. bld shift, 5 ;[063]
  140. andi shift, 0x3f ;[064]
  141. in x1, USBIN ;[065] <-- bit 6
  142. breq unstuff5 ;[066] *** unstuff escape
  143. eor phase, x1 ;[067]
  144. eor x2, x1 ;[068]
  145. bst x2, USBMINUS ;[069]
  146. bld shift, 6 ;[070]
  147. didUnstuff6: ;[ ]
  148. in r0, USBIN ;[071] <-- phase
  149. cpi shift, 0x02 ;[072]
  150. brlo unstuff6 ;[073] *** unstuff escape
  151. didUnstuff5: ;[ ]
  152. nop2 ;[074]
  153. ; [---] ;[075]
  154. in x2, USBIN ;[076] <-- bit 7
  155. eor x1, x2 ;[077]
  156. bst x1, USBMINUS ;[078]
  157. bld shift, 7 ;[079]
  158. didUnstuff7: ;[ ]
  159. eor r0, x2 ;[080]
  160. or phase, r0 ;[081]
  161. in r0, USBIN ;[082] <-- phase
  162. cpi shift, 0x04 ;[083]
  163. brsh rxLoop ;[084]
  164. ; [---] ;[085]
  165. unstuff7: ;[ ]
  166. andi x3, ~0x80 ;[085]
  167. ori shift, 0x80 ;[086]
  168. in x2, USBIN ;[087] <-- sample stuffed bit 7
  169. nop ;[088]
  170. rjmp didUnstuff7 ;[089]
  171. ; [---] ;[090]
  172. ;[080]
  173. unstuff5: ;[067]
  174. eor phase, x1 ;[068]
  175. andi x3, ~0x20 ;[069]
  176. ori shift, 0x20 ;[070]
  177. in r0, USBIN ;[071] <-- phase
  178. mov x2, x1 ;[072]
  179. nop ;[073]
  180. nop2 ;[074]
  181. ; [---] ;[075]
  182. in x1, USBIN ;[076] <-- bit 6
  183. eor r0, x1 ;[077]
  184. or phase, r0 ;[078]
  185. eor x2, x1 ;[079]
  186. bst x2, USBMINUS ;[080]
  187. bld shift, 6 ;[081] no need to check bitstuffing, we just had one
  188. in r0, USBIN ;[082] <-- phase
  189. rjmp didUnstuff5 ;[083]
  190. ; [---] ;[084]
  191. ;[074]
  192. unstuff6: ;[074]
  193. andi x3, ~0x40 ;[075]
  194. in x1, USBIN ;[076] <-- bit 6 again
  195. ori shift, 0x40 ;[077]
  196. nop2 ;[078]
  197. ; [---] ;[079]
  198. rjmp didUnstuff6 ;[080]
  199. ; [---] ;[081]
  200. ;[071]
  201. unstuff0: ;[013]
  202. eor r0, x2 ;[014]
  203. or phase, r0 ;[015]
  204. andi x2, USBMASK ;[016] check for SE0
  205. in r0, USBIN ;[017] <-- phase
  206. breq didUnstuff0 ;[018] direct jump to se0 would be too long
  207. andi x3, ~0x01 ;[019]
  208. ori shift, 0x01 ;[020]
  209. mov x1, x2 ;[021] mov existing sample
  210. in x2, USBIN ;[022] <-- bit 1 again
  211. rjmp didUnstuff0 ;[023]
  212. ; [---] ;[024]
  213. ;[014]
  214. unstuff1: ;[024]
  215. eor r0, x1 ;[025]
  216. or phase, r0 ;[026]
  217. andi x3, ~0x02 ;[027]
  218. in r0, USBIN ;[028] <-- phase
  219. ori shift, 0x02 ;[029]
  220. mov x2, x1 ;[030]
  221. rjmp didUnstuff1 ;[031]
  222. ; [---] ;[032]
  223. ;[022]
  224. unstuff2: ;[035]
  225. eor r0, x2 ;[036]
  226. or phase, r0 ;[037]
  227. andi x3, ~0x04 ;[038]
  228. in r0, USBIN ;[039] <-- phase
  229. ori shift, 0x04 ;[040]
  230. mov x1, x2 ;[041]
  231. rjmp didUnstuff2 ;[042]
  232. ; [---] ;[043]
  233. ;[033]
  234. unstuff3: ;[043]
  235. in x2, USBIN ;[044] <-- bit 3 again
  236. eor r0, x2 ;[045]
  237. or phase, r0 ;[046]
  238. andi x3, ~0x08 ;[047]
  239. ori shift, 0x08 ;[048]
  240. nop ;[049]
  241. in r0, USBIN ;[050] <-- phase
  242. rjmp didUnstuff3 ;[051]
  243. ; [---] ;[052]
  244. ;[042]
  245. unstuff4: ;[053]
  246. andi x3, ~0x10 ;[054]
  247. in x1, USBIN ;[055] <-- bit 4 again
  248. ori shift, 0x10 ;[056]
  249. rjmp didUnstuff4 ;[057]
  250. ; [---] ;[058]
  251. ;[048]
  252. rxLoop: ;[085]
  253. eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others
  254. in x1, USBIN ;[000] <-- bit 0
  255. st y+, x3 ;[001]
  256. ; [---] ;[002]
  257. eor r0, x1 ;[003]
  258. or phase, r0 ;[004]
  259. eor x2, x1 ;[005]
  260. in r0, USBIN ;[006] <-- phase
  261. ser x3 ;[007]
  262. bst x2, USBMINUS ;[008]
  263. bld shift, 0 ;[009]
  264. andi shift, 0xf9 ;[010]
  265. rxbit1: ;[ ]
  266. in x2, USBIN ;[011] <-- bit 1
  267. breq unstuff0 ;[012] *** unstuff escape
  268. andi x2, USBMASK ;[013] SE0 check for bit 1
  269. didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff
  270. breq se0 ;[014]
  271. eor r0, x2 ;[015]
  272. or phase, r0 ;[016]
  273. in r0, USBIN ;[017] <-- phase
  274. eor x1, x2 ;[018]
  275. bst x1, USBMINUS ;[019]
  276. bld shift, 1 ;[020]
  277. andi shift, 0xf3 ;[021]
  278. didUnstuff1: ;[ ]
  279. in x1, USBIN ;[022] <-- bit 2
  280. breq unstuff1 ;[023] *** unstuff escape
  281. eor r0, x1 ;[024]
  282. or phase, r0 ;[025]
  283. subi cnt, 1 ;[026] overflow check
  284. brcs overflow ;[027]
  285. in r0, USBIN ;[028] <-- phase
  286. eor x2, x1 ;[029]
  287. bst x2, USBMINUS ;[030]
  288. bld shift, 2 ;[031]
  289. andi shift, 0xe7 ;[032]
  290. didUnstuff2: ;[ ]
  291. in x2, USBIN ;[033] <-- bit 3
  292. breq unstuff2 ;[034] *** unstuff escape
  293. eor r0, x2 ;[035]
  294. or phase, r0 ;[036]
  295. eor x1, x2 ;[037]
  296. bst x1, USBMINUS ;[038]
  297. in r0, USBIN ;[039] <-- phase
  298. bld shift, 3 ;[040]
  299. andi shift, 0xcf ;[041]
  300. didUnstuff3: ;[ ]
  301. breq unstuff3 ;[042] *** unstuff escape
  302. nop ;[043]
  303. in x1, USBIN ;[044] <-- bit 4
  304. eor x2, x1 ;[045]
  305. bst x2, USBMINUS ;[046]
  306. bld shift, 4 ;[047]
  307. didUnstuff4: ;[ ]
  308. eor r0, x1 ;[048]
  309. or phase, r0 ;[049]
  310. in r0, USBIN ;[050] <-- phase
  311. andi shift, 0x9f ;[051]
  312. breq unstuff4 ;[052] *** unstuff escape
  313. rjmp continueWithBit5;[053]
  314. ; [---] ;[054]
  315. macro POP_STANDARD ; 16 cycles
  316. pop cnt
  317. pop x4
  318. pop x3
  319. pop x2
  320. pop x1
  321. pop shift
  322. pop YH
  323. pop r0
  324. endm
  325. macro POP_RETI ; 5 cycles
  326. pop YL
  327. out SREG, YL
  328. pop YL
  329. endm
  330. #include "asmcommon.inc"
  331. ; USB spec says:
  332. ; idle = J
  333. ; J = (D+ = 0), (D- = 1)
  334. ; K = (D+ = 1), (D- = 0)
  335. ; Spec allows 7.5 bit times from EOP to SOP for replies
  336. bitstuff7:
  337. eor x1, x4 ;[4]
  338. ldi x2, 0 ;[5]
  339. nop2 ;[6] C is zero (brcc)
  340. rjmp didStuff7 ;[8]
  341. bitstuffN:
  342. eor x1, x4 ;[5]
  343. ldi x2, 0 ;[6]
  344. lpm ;[7] 3 cycle NOP, modifies r0
  345. out USBOUT, x1 ;[10] <-- out
  346. rjmp didStuffN ;[0]
  347. #define bitStatus x3
  348. sendNakAndReti:
  349. ldi cnt, USBPID_NAK ;[-19]
  350. rjmp sendCntAndReti ;[-18]
  351. sendAckAndReti:
  352. ldi cnt, USBPID_ACK ;[-17]
  353. sendCntAndReti:
  354. mov r0, cnt ;[-16]
  355. ldi YL, 0 ;[-15] R0 address is 0
  356. ldi YH, 0 ;[-14]
  357. ldi cnt, 2 ;[-13]
  358. ; rjmp usbSendAndReti fallthrough
  359. ;usbSend:
  360. ;pointer to data in 'Y'
  361. ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
  362. ;uses: x1...x4, shift, cnt, Y
  363. ;Numbers in brackets are time since first bit of sync pattern is sent
  364. usbSendAndReti: ; 12 cycles until SOP
  365. in x2, USBDDR ;[-12]
  366. ori x2, USBMASK ;[-11]
  367. sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
  368. in x1, USBOUT ;[-8] port mirror for tx loop
  369. out USBDDR, x2 ;[-7] <- acquire bus
  370. ; need not init x2 (bitstuff history) because sync starts with 0
  371. ldi x4, USBMASK ;[-6] exor mask
  372. ldi shift, 0x80 ;[-5] sync byte is first byte sent
  373. ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes
  374. byteloop:
  375. bitloop:
  376. sbrs shift, 0 ;[8] [-3]
  377. eor x1, x4 ;[9] [-2]
  378. out USBOUT, x1 ;[10] [-1] <-- out
  379. ror shift ;[0]
  380. ror x2 ;[1]
  381. didStuffN:
  382. cpi x2, 0xfc ;[2]
  383. brcc bitstuffN ;[3]
  384. nop ;[4]
  385. subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37
  386. brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value
  387. sbrs shift, 0 ;[7]
  388. eor x1, x4 ;[8]
  389. ror shift ;[9]
  390. didStuff7:
  391. out USBOUT, x1 ;[10] <-- out
  392. ror x2 ;[0]
  393. cpi x2, 0xfc ;[1]
  394. brcc bitstuff7 ;[2]
  395. ld shift, y+ ;[3]
  396. dec cnt ;[5]
  397. brne byteloop ;[6]
  398. ;make SE0:
  399. cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles]
  400. lds x2, usbNewDeviceAddr;[8]
  401. lsl x2 ;[10] we compare with left shifted address
  402. out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
  403. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  404. ;set address only after data packet was sent, not after handshake
  405. subi YL, 2 ;[0] Only assign address on data packets, not ACK/NAK in r0
  406. sbci YH, 0 ;[1]
  407. breq skipAddrAssign ;[2]
  408. sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
  409. skipAddrAssign:
  410. ;end of usbDeviceAddress transfer
  411. ldi x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag
  412. USB_STORE_PENDING(x2) ;[5]
  413. ori x1, USBIDLE ;[6]
  414. in x2, USBDDR ;[7]
  415. cbr x2, USBMASK ;[8] set both pins to input
  416. mov x3, x1 ;[9]
  417. cbr x3, USBMASK ;[10] configure no pullup on both pins
  418. ldi x4, 4 ;[11]
  419. se0Delay:
  420. dec x4 ;[12] [15] [18] [21]
  421. brne se0Delay ;[13] [16] [19] [22]
  422. out USBOUT, x1 ;[23] <-- out J (idle) -- end of SE0 (EOP signal)
  423. out USBDDR, x2 ;[24] <-- release bus now
  424. out USBOUT, x3 ;[25] <-- ensure no pull-up resistors are active
  425. rjmp doReturn