Keyboard firmwares for Atmel AVR and Cortex-M
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.

usbdrvasm.S 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /* Name: usbdrvasm.S
  2. * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
  3. * Author: Christian Starkjohann
  4. * Creation Date: 2007-06-13
  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: usbdrvasm.S 785 2010-05-30 17:57:07Z cs $
  9. */
  10. /*
  11. General Description:
  12. This module is the assembler part of the USB driver. This file contains
  13. general code (preprocessor acrobatics and CRC computation) and then includes
  14. the file appropriate for the given clock rate.
  15. */
  16. #define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
  17. #include "usbportability.h"
  18. #include "usbdrv.h" /* for common defs */
  19. /* register names */
  20. #define x1 r16
  21. #define x2 r17
  22. #define shift r18
  23. #define cnt r19
  24. #define x3 r20
  25. #define x4 r21
  26. #define x5 r22
  27. #define bitcnt x5
  28. #define phase x4
  29. #define leap x4
  30. /* Some assembler dependent definitions and declarations: */
  31. #ifdef __IAR_SYSTEMS_ASM__
  32. extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
  33. extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
  34. extern usbTxBuf, usbTxStatus1, usbTxStatus3
  35. # if USB_COUNT_SOF
  36. extern usbSofCount
  37. # endif
  38. public usbCrc16
  39. public usbCrc16Append
  40. COMMON INTVEC
  41. # ifndef USB_INTR_VECTOR
  42. ORG INT0_vect
  43. # else /* USB_INTR_VECTOR */
  44. ORG USB_INTR_VECTOR
  45. # undef USB_INTR_VECTOR
  46. # endif /* USB_INTR_VECTOR */
  47. # define USB_INTR_VECTOR usbInterruptHandler
  48. rjmp USB_INTR_VECTOR
  49. RSEG CODE
  50. #else /* __IAR_SYSTEMS_ASM__ */
  51. # ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
  52. # ifdef INT0_vect
  53. # define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
  54. # else
  55. # define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
  56. # endif
  57. # endif
  58. .text
  59. .global USB_INTR_VECTOR
  60. .type USB_INTR_VECTOR, @function
  61. .global usbCrc16
  62. .global usbCrc16Append
  63. #endif /* __IAR_SYSTEMS_ASM__ */
  64. #if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
  65. # define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
  66. # define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
  67. #else /* It's a memory address, use lds and sts */
  68. # define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
  69. # define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
  70. #endif
  71. #define usbTxLen1 usbTxStatus1
  72. #define usbTxBuf1 (usbTxStatus1 + 1)
  73. #define usbTxLen3 usbTxStatus3
  74. #define usbTxBuf3 (usbTxStatus3 + 1)
  75. ;----------------------------------------------------------------------------
  76. ; Utility functions
  77. ;----------------------------------------------------------------------------
  78. #ifdef __IAR_SYSTEMS_ASM__
  79. /* Register assignments for usbCrc16 on IAR cc */
  80. /* Calling conventions on IAR:
  81. * First parameter passed in r16/r17, second in r18/r19 and so on.
  82. * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
  83. * Result is passed in r16/r17
  84. * In case of the "tiny" memory model, pointers are only 8 bit with no
  85. * padding. We therefore pass argument 1 as "16 bit unsigned".
  86. */
  87. RTMODEL "__rt_version", "3"
  88. /* The line above will generate an error if cc calling conventions change.
  89. * The value "3" above is valid for IAR 4.10B/W32
  90. */
  91. # define argLen r18 /* argument 2 */
  92. # define argPtrL r16 /* argument 1 */
  93. # define argPtrH r17 /* argument 1 */
  94. # define resCrcL r16 /* result */
  95. # define resCrcH r17 /* result */
  96. # define ptrL ZL
  97. # define ptrH ZH
  98. # define ptr Z
  99. # define byte r22
  100. # define bitCnt r19
  101. # define polyL r20
  102. # define polyH r21
  103. # define scratch r23
  104. #else /* __IAR_SYSTEMS_ASM__ */
  105. /* Register assignments for usbCrc16 on gcc */
  106. /* Calling conventions on gcc:
  107. * First parameter passed in r24/r25, second in r22/23 and so on.
  108. * Callee must preserve r1-r17, r28/r29
  109. * Result is passed in r24/r25
  110. */
  111. # define argLen r22 /* argument 2 */
  112. # define argPtrL r24 /* argument 1 */
  113. # define argPtrH r25 /* argument 1 */
  114. # define resCrcL r24 /* result */
  115. # define resCrcH r25 /* result */
  116. # define ptrL XL
  117. # define ptrH XH
  118. # define ptr x
  119. # define byte r18
  120. # define bitCnt r19
  121. # define polyL r20
  122. # define polyH r21
  123. # define scratch r23
  124. #endif
  125. #if USB_USE_FAST_CRC
  126. ; This implementation is faster, but has bigger code size
  127. ; Thanks to Slawomir Fras (BoskiDialer) for this code!
  128. ; It implements the following C pseudo-code:
  129. ; unsigned table(unsigned char x)
  130. ; {
  131. ; unsigned value;
  132. ;
  133. ; value = (unsigned)x << 6;
  134. ; value ^= (unsigned)x << 7;
  135. ; if(parity(x))
  136. ; value ^= 0xc001;
  137. ; return value;
  138. ; }
  139. ; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
  140. ; {
  141. ; unsigned crc = 0xffff;
  142. ;
  143. ; while(argLen--)
  144. ; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
  145. ; return ~crc;
  146. ; }
  147. ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
  148. ; argPtr r24+25 / r16+r17
  149. ; argLen r22 / r18
  150. ; temp variables:
  151. ; byte r18 / r22
  152. ; scratch r23
  153. ; resCrc r24+r25 / r16+r17
  154. ; ptr X / Z
  155. usbCrc16:
  156. mov ptrL, argPtrL
  157. mov ptrH, argPtrH
  158. ldi resCrcL, 0xFF
  159. ldi resCrcH, 0xFF
  160. rjmp usbCrc16LoopTest
  161. usbCrc16ByteLoop:
  162. ld byte, ptr+
  163. eor resCrcL, byte ; resCrcL is now 'x' in table()
  164. mov byte, resCrcL ; compute parity of 'x'
  165. swap byte
  166. eor byte, resCrcL
  167. mov scratch, byte
  168. lsr byte
  169. lsr byte
  170. eor byte, scratch
  171. inc byte
  172. lsr byte
  173. andi byte, 1 ; byte is now parity(x)
  174. mov scratch, resCrcL
  175. mov resCrcL, resCrcH
  176. eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
  177. neg byte
  178. andi byte, 0xc0
  179. mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
  180. clr byte
  181. lsr scratch
  182. ror byte
  183. eor resCrcH, scratch
  184. eor resCrcL, byte
  185. lsr scratch
  186. ror byte
  187. eor resCrcH, scratch
  188. eor resCrcL, byte
  189. usbCrc16LoopTest:
  190. subi argLen, 1
  191. brsh usbCrc16ByteLoop
  192. com resCrcL
  193. com resCrcH
  194. ret
  195. #else /* USB_USE_FAST_CRC */
  196. ; This implementation is slower, but has less code size
  197. ;
  198. ; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
  199. ; argPtr r24+25 / r16+r17
  200. ; argLen r22 / r18
  201. ; temp variables:
  202. ; byte r18 / r22
  203. ; bitCnt r19
  204. ; poly r20+r21
  205. ; scratch r23
  206. ; resCrc r24+r25 / r16+r17
  207. ; ptr X / Z
  208. usbCrc16:
  209. mov ptrL, argPtrL
  210. mov ptrH, argPtrH
  211. ldi resCrcL, 0
  212. ldi resCrcH, 0
  213. ldi polyL, lo8(0xa001)
  214. ldi polyH, hi8(0xa001)
  215. com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
  216. ldi bitCnt, 0 ; loop counter with starnd condition = end condition
  217. rjmp usbCrcLoopEntry
  218. usbCrcByteLoop:
  219. ld byte, ptr+
  220. eor resCrcL, byte
  221. usbCrcBitLoop:
  222. ror resCrcH ; carry is always set here (see brcs jumps to here)
  223. ror resCrcL
  224. brcs usbCrcNoXor
  225. eor resCrcL, polyL
  226. eor resCrcH, polyH
  227. usbCrcNoXor:
  228. subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
  229. brcs usbCrcBitLoop
  230. usbCrcLoopEntry:
  231. subi argLen, -1
  232. brcs usbCrcByteLoop
  233. usbCrcReady:
  234. ret
  235. ; Thanks to Reimar Doeffinger for optimizing this CRC routine!
  236. #endif /* USB_USE_FAST_CRC */
  237. ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
  238. usbCrc16Append:
  239. rcall usbCrc16
  240. st ptr+, resCrcL
  241. st ptr+, resCrcH
  242. ret
  243. #undef argLen
  244. #undef argPtrL
  245. #undef argPtrH
  246. #undef resCrcL
  247. #undef resCrcH
  248. #undef ptrL
  249. #undef ptrH
  250. #undef ptr
  251. #undef byte
  252. #undef bitCnt
  253. #undef polyL
  254. #undef polyH
  255. #undef scratch
  256. #if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
  257. #ifdef __IAR_SYSTEMS_ASM__
  258. /* Register assignments for usbMeasureFrameLength on IAR cc */
  259. /* Calling conventions on IAR:
  260. * First parameter passed in r16/r17, second in r18/r19 and so on.
  261. * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
  262. * Result is passed in r16/r17
  263. * In case of the "tiny" memory model, pointers are only 8 bit with no
  264. * padding. We therefore pass argument 1 as "16 bit unsigned".
  265. */
  266. # define resL r16
  267. # define resH r17
  268. # define cnt16L r30
  269. # define cnt16H r31
  270. # define cntH r18
  271. #else /* __IAR_SYSTEMS_ASM__ */
  272. /* Register assignments for usbMeasureFrameLength on gcc */
  273. /* Calling conventions on gcc:
  274. * First parameter passed in r24/r25, second in r22/23 and so on.
  275. * Callee must preserve r1-r17, r28/r29
  276. * Result is passed in r24/r25
  277. */
  278. # define resL r24
  279. # define resH r25
  280. # define cnt16L r24
  281. # define cnt16H r25
  282. # define cntH r26
  283. #endif
  284. # define cnt16 cnt16L
  285. ; extern unsigned usbMeasurePacketLength(void);
  286. ; returns time between two idle strobes in multiples of 7 CPU clocks
  287. .global usbMeasureFrameLength
  288. usbMeasureFrameLength:
  289. ldi cntH, 6 ; wait ~ 10 ms for D- == 0
  290. clr cnt16L
  291. clr cnt16H
  292. usbMFTime16:
  293. dec cntH
  294. breq usbMFTimeout
  295. usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
  296. sbiw cnt16, 1 ;[0] [6]
  297. breq usbMFTime16 ;[2]
  298. sbic USBIN, USBMINUS ;[3]
  299. rjmp usbMFWaitStrobe ;[4]
  300. usbMFWaitIdle: ; then wait until idle again
  301. sbis USBIN, USBMINUS ;1 wait for D- == 1
  302. rjmp usbMFWaitIdle ;2
  303. ldi cnt16L, 1 ;1 represents cycles so far
  304. clr cnt16H ;1
  305. usbMFWaitLoop:
  306. in cntH, USBIN ;[0] [7]
  307. adiw cnt16, 1 ;[1]
  308. breq usbMFTimeout ;[3]
  309. andi cntH, USBMASK ;[4]
  310. brne usbMFWaitLoop ;[5]
  311. usbMFTimeout:
  312. #if resL != cnt16L
  313. mov resL, cnt16L
  314. mov resH, cnt16H
  315. #endif
  316. ret
  317. #undef resL
  318. #undef resH
  319. #undef cnt16
  320. #undef cnt16L
  321. #undef cnt16H
  322. #undef cntH
  323. #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
  324. ;----------------------------------------------------------------------------
  325. ; Now include the clock rate specific code
  326. ;----------------------------------------------------------------------------
  327. #ifndef USB_CFG_CLOCK_KHZ
  328. # ifdef F_CPU
  329. # define USB_CFG_CLOCK_KHZ (F_CPU/1000)
  330. # else
  331. # error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
  332. # endif
  333. #endif
  334. #if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
  335. # if USB_CFG_CLOCK_KHZ == 18000
  336. # include "usbdrvasm18-crc.inc"
  337. # else
  338. # error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
  339. # endif
  340. #else /* USB_CFG_CHECK_CRC */
  341. # if USB_CFG_CLOCK_KHZ == 12000
  342. # include "usbdrvasm12.inc"
  343. # elif USB_CFG_CLOCK_KHZ == 12800
  344. # include "usbdrvasm128.inc"
  345. # elif USB_CFG_CLOCK_KHZ == 15000
  346. # include "usbdrvasm15.inc"
  347. # elif USB_CFG_CLOCK_KHZ == 16000
  348. # include "usbdrvasm16.inc"
  349. # elif USB_CFG_CLOCK_KHZ == 16500
  350. # include "usbdrvasm165.inc"
  351. # elif USB_CFG_CLOCK_KHZ == 20000
  352. # include "usbdrvasm20.inc"
  353. # else
  354. # error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
  355. # endif
  356. #endif /* USB_CFG_CHECK_CRC */