Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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