delays.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * Copyright (C) 2018 bzt (bztsrc@github)
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. *
  24. */
  25. #include "gpio.h"
  26. #define SYSTMR_LO ((volatile unsigned int*)(MMIO_BASE+0x00003004))
  27. #define SYSTMR_HI ((volatile unsigned int*)(MMIO_BASE+0x00003008))
  28. /**
  29. * Wait N CPU cycles (ARM CPU only)
  30. */
  31. void wait_cycles(unsigned int n)
  32. {
  33. if(n) while(n--) { asm volatile("nop"); }
  34. }
  35. /**
  36. * Wait N microsec (ARM CPU only)
  37. */
  38. void wait_msec(unsigned int n)
  39. {
  40. register unsigned long f, t, r;
  41. // get the current counter frequency
  42. asm volatile ("mrs %0, cntfrq_el0" : "=r"(f));
  43. // read the current counter
  44. asm volatile ("mrs %0, cntpct_el0" : "=r"(t));
  45. // calculate required count increase
  46. unsigned long i=((f/1000)*n)/1000;
  47. // loop while counter increase is less than i
  48. do{asm volatile ("mrs %0, cntpct_el0" : "=r"(r));}while(r-t<i);
  49. }
  50. /**
  51. * Get System Timer's counter
  52. */
  53. unsigned long get_system_timer()
  54. {
  55. unsigned int h=-1, l;
  56. // we must read MMIO area as two separate 32 bit reads
  57. h=*SYSTMR_HI;
  58. l=*SYSTMR_LO;
  59. // we have to repeat it if high word changed during read
  60. if(h!=*SYSTMR_HI) {
  61. h=*SYSTMR_HI;
  62. l=*SYSTMR_LO;
  63. }
  64. // compose long int value
  65. return ((unsigned long) h << 32) | l;
  66. }
  67. /**
  68. * Wait N microsec (with BCM System Timer)
  69. */
  70. void wait_msec_st(unsigned int n)
  71. {
  72. unsigned long t=get_system_timer();
  73. // we must check if it's non-zero, because qemu does not emulate
  74. // system timer, and returning constant zero would mean infinite loop
  75. if(t) while(get_system_timer()-t < n);
  76. }