usbdrvasm16.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /* Name: usbdrvasm16.inc
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-06-15
  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: usbdrvasm16.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 MHz version of the asssembler part of the USB driver. It
  16. requires a 16 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: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte
  25. ; Numbers in brackets are clocks counted from center of last sync bit
  26. ; when instruction starts
  27. USB_INTR_VECTOR:
  28. ;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt
  29. push YL ;[-25] push only what is necessary to sync with edge ASAP
  30. in YL, SREG ;[-23]
  31. push YL ;[-22]
  32. push YH ;[-20]
  33. ;----------------------------------------------------------------------------
  34. ; Synchronize with sync pattern:
  35. ;----------------------------------------------------------------------------
  36. ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
  37. ;sync up with J to K edge during sync pattern -- use fastest possible loops
  38. ;The first part waits at most 1 bit long since we must be in sync pattern.
  39. ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
  40. ;waitForJ, ensure that this prerequisite is met.
  41. waitForJ:
  42. inc YL
  43. sbis USBIN, USBMINUS
  44. brne waitForJ ; just make sure we have ANY timeout
  45. waitForK:
  46. ;The following code results in a sampling window of < 1/4 bit which meets the spec.
  47. sbis USBIN, USBMINUS ;[-15]
  48. rjmp foundK ;[-14]
  49. sbis USBIN, USBMINUS
  50. rjmp foundK
  51. sbis USBIN, USBMINUS
  52. rjmp foundK
  53. sbis USBIN, USBMINUS
  54. rjmp foundK
  55. sbis USBIN, USBMINUS
  56. rjmp foundK
  57. sbis USBIN, USBMINUS
  58. rjmp foundK
  59. #if USB_COUNT_SOF
  60. lds YL, usbSofCount
  61. inc YL
  62. sts usbSofCount, YL
  63. #endif /* USB_COUNT_SOF */
  64. #ifdef USB_SOF_HOOK
  65. USB_SOF_HOOK
  66. #endif
  67. rjmp sofError
  68. foundK: ;[-12]
  69. ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
  70. ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
  71. ;are cycles from center of first sync (double K) bit after the instruction
  72. push bitcnt ;[-12]
  73. ; [---] ;[-11]
  74. lds YL, usbInputBufOffset;[-10]
  75. ; [---] ;[-9]
  76. clr YH ;[-8]
  77. subi YL, lo8(-(usbRxBuf));[-7] [rx loop init]
  78. sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init]
  79. push shift ;[-5]
  80. ; [---] ;[-4]
  81. ldi bitcnt, 0x55 ;[-3] [rx loop init]
  82. sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
  83. rjmp haveTwoBitsK ;[-1]
  84. pop shift ;[0] undo the push from before
  85. pop bitcnt ;[2] undo the push from before
  86. rjmp waitForK ;[4] this was not the end of sync, retry
  87. ; The entire loop from waitForK until rjmp waitForK above must not exceed two
  88. ; bit times (= 21 cycles).
  89. ;----------------------------------------------------------------------------
  90. ; push more registers and initialize values while we sample the first bits:
  91. ;----------------------------------------------------------------------------
  92. haveTwoBitsK:
  93. push x1 ;[1]
  94. push x2 ;[3]
  95. push x3 ;[5]
  96. ldi shift, 0 ;[7]
  97. ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that
  98. push x4 ;[9] == leap
  99. in x1, USBIN ;[11] <-- sample bit 0
  100. andi x1, USBMASK ;[12]
  101. bst x1, USBMINUS ;[13]
  102. bld shift, 7 ;[14]
  103. push cnt ;[15]
  104. ldi leap, 0 ;[17] [rx loop init]
  105. ldi cnt, USB_BUFSIZE;[18] [rx loop init]
  106. rjmp rxbit1 ;[19] arrives at [21]
  107. ;----------------------------------------------------------------------------
  108. ; Receiver loop (numbers in brackets are cycles within byte after instr)
  109. ;----------------------------------------------------------------------------
  110. unstuff6:
  111. andi x2, USBMASK ;[03]
  112. ori x3, 1<<6 ;[04] will not be shifted any more
  113. andi shift, ~0x80;[05]
  114. mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6
  115. subi leap, 3 ;[07] since this is a short (10 cycle) bit, enforce leap bit
  116. rjmp didUnstuff6 ;[08]
  117. unstuff7:
  118. ori x3, 1<<7 ;[09] will not be shifted any more
  119. in x2, USBIN ;[00] [10] re-sample bit 7
  120. andi x2, USBMASK ;[01]
  121. andi shift, ~0x80;[02]
  122. subi leap, 3 ;[03] since this is a short (10 cycle) bit, enforce leap bit
  123. rjmp didUnstuff7 ;[04]
  124. unstuffEven:
  125. ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0
  126. in x1, USBIN ;[00] [10]
  127. andi shift, ~0x80;[01]
  128. andi x1, USBMASK ;[02]
  129. breq se0 ;[03]
  130. subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
  131. nop ;[05]
  132. rjmp didUnstuffE ;[06]
  133. unstuffOdd:
  134. ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1
  135. in x2, USBIN ;[00] [10]
  136. andi shift, ~0x80;[01]
  137. andi x2, USBMASK ;[02]
  138. breq se0 ;[03]
  139. subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
  140. nop ;[05]
  141. rjmp didUnstuffO ;[06]
  142. rxByteLoop:
  143. andi x1, USBMASK ;[03]
  144. eor x2, x1 ;[04]
  145. subi leap, 1 ;[05]
  146. brpl skipLeap ;[06]
  147. subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte
  148. nop ;1
  149. skipLeap:
  150. subi x2, 1 ;[08]
  151. ror shift ;[09]
  152. didUnstuff6:
  153. cpi shift, 0xfc ;[10]
  154. in x2, USBIN ;[00] [11] <-- sample bit 7
  155. brcc unstuff6 ;[01]
  156. andi x2, USBMASK ;[02]
  157. eor x1, x2 ;[03]
  158. subi x1, 1 ;[04]
  159. ror shift ;[05]
  160. didUnstuff7:
  161. cpi shift, 0xfc ;[06]
  162. brcc unstuff7 ;[07]
  163. eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others
  164. st y+, x3 ;[09] store data
  165. rxBitLoop:
  166. in x1, USBIN ;[00] [11] <-- sample bit 0/2/4
  167. andi x1, USBMASK ;[01]
  168. eor x2, x1 ;[02]
  169. andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7
  170. subi x2, 1 ;[04]
  171. ror shift ;[05]
  172. cpi shift, 0xfc ;[06]
  173. brcc unstuffEven ;[07]
  174. didUnstuffE:
  175. lsr x3 ;[08]
  176. lsr x3 ;[09]
  177. rxbit1:
  178. in x2, USBIN ;[00] [10] <-- sample bit 1/3/5
  179. andi x2, USBMASK ;[01]
  180. breq se0 ;[02]
  181. eor x1, x2 ;[03]
  182. subi x1, 1 ;[04]
  183. ror shift ;[05]
  184. cpi shift, 0xfc ;[06]
  185. brcc unstuffOdd ;[07]
  186. didUnstuffO:
  187. subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3
  188. brcs rxBitLoop ;[09]
  189. subi cnt, 1 ;[10]
  190. in x1, USBIN ;[00] [11] <-- sample bit 6
  191. brcc rxByteLoop ;[01]
  192. rjmp overflow
  193. macro POP_STANDARD ; 14 cycles
  194. pop cnt
  195. pop x4
  196. pop x3
  197. pop x2
  198. pop x1
  199. pop shift
  200. pop bitcnt
  201. endm
  202. macro POP_RETI ; 7 cycles
  203. pop YH
  204. pop YL
  205. out SREG, YL
  206. pop YL
  207. endm
  208. #include "asmcommon.inc"
  209. ; USB spec says:
  210. ; idle = J
  211. ; J = (D+ = 0), (D- = 1)
  212. ; K = (D+ = 1), (D- = 0)
  213. ; Spec allows 7.5 bit times from EOP to SOP for replies
  214. bitstuffN:
  215. eor x1, x4 ;[5]
  216. ldi x2, 0 ;[6]
  217. nop2 ;[7]
  218. nop ;[9]
  219. out USBOUT, x1 ;[10] <-- out
  220. rjmp didStuffN ;[0]
  221. bitstuff6:
  222. eor x1, x4 ;[5]
  223. ldi x2, 0 ;[6] Carry is zero due to brcc
  224. rol shift ;[7] compensate for ror shift at branch destination
  225. rjmp didStuff6 ;[8]
  226. bitstuff7:
  227. ldi x2, 0 ;[2] Carry is zero due to brcc
  228. rjmp didStuff7 ;[3]
  229. sendNakAndReti:
  230. ldi x3, USBPID_NAK ;[-18]
  231. rjmp sendX3AndReti ;[-17]
  232. sendAckAndReti:
  233. ldi cnt, USBPID_ACK ;[-17]
  234. sendCntAndReti:
  235. mov x3, cnt ;[-16]
  236. sendX3AndReti:
  237. ldi YL, 20 ;[-15] x3==r20 address is 20
  238. ldi YH, 0 ;[-14]
  239. ldi cnt, 2 ;[-13]
  240. ; rjmp usbSendAndReti fallthrough
  241. ;usbSend:
  242. ;pointer to data in 'Y'
  243. ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
  244. ;uses: x1...x4, btcnt, shift, cnt, Y
  245. ;Numbers in brackets are time since first bit of sync pattern is sent
  246. ;We don't match the transfer rate exactly (don't insert leap cycles every third
  247. ;byte) because the spec demands only 1.5% precision anyway.
  248. usbSendAndReti: ; 12 cycles until SOP
  249. in x2, USBDDR ;[-12]
  250. ori x2, USBMASK ;[-11]
  251. sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
  252. in x1, USBOUT ;[-8] port mirror for tx loop
  253. out USBDDR, x2 ;[-7] <- acquire bus
  254. ; need not init x2 (bitstuff history) because sync starts with 0
  255. ldi x4, USBMASK ;[-6] exor mask
  256. ldi shift, 0x80 ;[-5] sync byte is first byte sent
  257. txByteLoop:
  258. ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101
  259. txBitLoop:
  260. sbrs shift, 0 ;[-3] [7]
  261. eor x1, x4 ;[-2] [8]
  262. out USBOUT, x1 ;[-1] [9] <-- out N
  263. ror shift ;[0] [10]
  264. ror x2 ;[1]
  265. didStuffN:
  266. cpi x2, 0xfc ;[2]
  267. brcc bitstuffN ;[3]
  268. lsr bitcnt ;[4]
  269. brcc txBitLoop ;[5]
  270. brne txBitLoop ;[6]
  271. sbrs shift, 0 ;[7]
  272. eor x1, x4 ;[8]
  273. didStuff6:
  274. out USBOUT, x1 ;[-1] [9] <-- out 6
  275. ror shift ;[0] [10]
  276. ror x2 ;[1]
  277. cpi x2, 0xfc ;[2]
  278. brcc bitstuff6 ;[3]
  279. ror shift ;[4]
  280. didStuff7:
  281. ror x2 ;[5]
  282. sbrs x2, 7 ;[6]
  283. eor x1, x4 ;[7]
  284. nop ;[8]
  285. cpi x2, 0xfc ;[9]
  286. out USBOUT, x1 ;[-1][10] <-- out 7
  287. brcc bitstuff7 ;[0] [11]
  288. ld shift, y+ ;[1]
  289. dec cnt ;[3]
  290. brne txByteLoop ;[4]
  291. ;make SE0:
  292. cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles]
  293. lds x2, usbNewDeviceAddr;[6]
  294. lsl x2 ;[8] we compare with left shifted address
  295. subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3
  296. sbci YH, 0 ;[10]
  297. out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
  298. ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
  299. ;set address only after data packet was sent, not after handshake
  300. breq skipAddrAssign ;[0]
  301. sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
  302. skipAddrAssign:
  303. ;end of usbDeviceAddress transfer
  304. ldi x2, 1<<USB_INTR_PENDING_BIT;[2] int0 occurred during TX -- clear pending flag
  305. USB_STORE_PENDING(x2) ;[3]
  306. ori x1, USBIDLE ;[4]
  307. in x2, USBDDR ;[5]
  308. cbr x2, USBMASK ;[6] set both pins to input
  309. mov x3, x1 ;[7]
  310. cbr x3, USBMASK ;[8] configure no pullup on both pins
  311. ldi x4, 4 ;[9]
  312. se0Delay:
  313. dec x4 ;[10] [13] [16] [19]
  314. brne se0Delay ;[11] [14] [17] [20]
  315. out USBOUT, x1 ;[21] <-- out J (idle) -- end of SE0 (EOP signal)
  316. out USBDDR, x2 ;[22] <-- release bus now
  317. out USBOUT, x3 ;[23] <-- ensure no pull-up resistors are active
  318. rjmp doReturn