uaa

testing SoftwareSerial.cpp diff

uaa
Jul 23rd, 2020
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.73 KB | None | 0 0
  1. diff --git a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
  2. index 7d3cde6..17a182b 100644
  3. --- a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
  4. +++ b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
  5. @@ -43,23 +43,22 @@ http://arduiniana.org.
  6. #include <Arduino.h>
  7. #include <SoftwareSerial.h>
  8. // #include <util/delay_basic.h>
  9. -// replace modified _delay_loop_2() for LGT8F328P
  10. -/*
  11. - Delay loop using a 16-bit counter \c __count, so up to 65536
  12. - iterations are possible. (The value 65536 would have to be
  13. - passed as 0.) The loop executes four CPU cycles per iteration,
  14. - not including the overhead the compiler requires to setup the
  15. - counter register pair.
  16. -
  17. - Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
  18. - milliseconds can be achieved.
  19. - */
  20. -static void SoftwareSerial::_delay_loop_2(uint16_t __count)
  21. +// copy from <util/delay_basic.h> with two modifications
  22. +// - to reduce CALL/RET overhead, use always_inline
  23. +// - NOP afrer BRNE ensures delay time
  24. +// be careful to differences of instruction execute cycle
  25. +// NOP 1
  26. +// BRNE 1:branch not taken, 2:taken
  27. +// SBIW 2:AVR processor, 1:LGT8x processor
  28. +// CALL 4
  29. +// RET 4:AVR processor, 2:LGT8x processor
  30. +// at CPU speed of 1MHz, up to 262.1ms (AVR) or 196.6ms (LGT8x)
  31. +__attribute__((always_inline)) static inline void SoftwareSerial::_delay_loop_2(uint16_t __count)
  32. {
  33. __asm__ volatile (
  34. "1: sbiw %0,1" "\n\t"
  35. - "nop" "\n\t" // LGT8F328P's SBIW takes 1 clock, adjust
  36. - "brne 1b"
  37. + "brne 1b" "\n\t"
  38. + "nop"
  39. : "=w" (__count)
  40. : "0" (__count)
  41. );
  42. @@ -99,7 +98,7 @@ inline void DebugPulse(uint8_t, uint8_t) {}
  43. //
  44.  
  45. /* static */
  46. -inline void SoftwareSerial::tunedDelay(uint16_t delay) {
  47. +__attribute__((always_inline)) static inline void SoftwareSerial::tunedDelay(uint16_t delay) {
  48. _delay_loop_2(delay);
  49. }
  50.  
  51. @@ -347,23 +346,40 @@ void SoftwareSerial::begin(uint16_t rxcenter, uint16_t rxintra, uint16_t rxsto
  52.  
  53. listen();
  54. }
  55. +// Calculated by gcc-7.3.0
  56. +#if defined(__LGT8F__)
  57. +#define DELAY_CYCLE 3
  58. +#define TXDELAY 14
  59. +#define RXDELAY_BEFORECENTER 44 /*45*/
  60. +#define RXDELAY_CENTER2READ 14
  61. +#define RXDELAY_READLOOP 14
  62. +#define RXDELAY_BEFORESTOP 28 /*25*/
  63. +#define RXDELAY_AFTERSTOP 6
  64. +#else
  65. +#define DELAY_CYCLE 4
  66. +#define TXDELAY 16
  67. +#define RXDELAY_BEFORECENTER 73
  68. +#define RXDELAY_CENTER2READ 20
  69. +#define RXDELAY_READLOOP 15
  70. +#define RXDELAY_BEFORESTOP 33 /*32*/
  71. +#define RXDELAY_AFTERSTOP 11
  72. +#endif
  73. void SoftwareSerial::begin(long speed)
  74. {
  75. _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
  76.  
  77. - // Precalculate the various delays, in number of 4-cycle delays
  78. - uint16_t bit_delay = (F_CPU / speed) / 4;
  79. + // Precalculate the various delays, in number of delay cycles
  80. + uint16_t bit_delay = (F_CPU / speed) / DELAY_CYCLE;
  81.  
  82. // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit,
  83. // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits,
  84. // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit
  85. // These are all close enough to just use 15 cycles, since the inter-bit
  86. // timings are the most critical (deviations stack 8 times)
  87. - _tx_delay = subtract_cap(bit_delay, 15 / 4);
  88. + _tx_delay = subtract_cap(bit_delay, TXDELAY / DELAY_CYCLE);
  89.  
  90. // Only setup rx when we have a valid PCINT for this pin
  91. if (digitalPinToPCICR((int8_t)_receivePin)) {
  92. - #if GCC_VERSION > 40800
  93. // Timings counted from gcc 4.8.2 output. This works up to 115200 on
  94. // 16Mhz and 57600 on 8Mhz.
  95. //
  96. @@ -371,16 +387,20 @@ void SoftwareSerial::begin(long speed)
  97. // interrupt flag is set, 4 cycles before the PC is set to the right
  98. // interrupt vector address and the old PC is pushed on the stack,
  99. // and then 75 cycles of instructions (including the RJMP in the
  100. - // ISR vector table) until the first delay. After the delay, there
  101. - // are 17 more cycles until the pin value is read (excluding the
  102. - // delay in the loop).
  103. + // ISR vector table) until the first delay (RXDELAY_BEFORECENTER).
  104. + // After the delay, there are 17 more cycles until the pin value is read
  105. + // (excluding the delay in the loop, RXDELAY_CENTER2READ).
  106. // We want to have a total delay of 1.5 bit time. Inside the loop,
  107. // we already wait for 1 bit time - 23 cycles, so here we wait for
  108. // 0.5 bit time - (71 + 18 - 22) cycles.
  109. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4);
  110. + _rx_delay_centering = subtract_cap(bit_delay / 2,
  111. + (4 + 4 + RXDELAY_BEFORECENTER +
  112. + RXDELAY_CENTER2READ -
  113. + RXDELAY_READLOOP) / DELAY_CYCLE);
  114.  
  115. // There are 23 cycles in each loop iteration (excluding the delay)
  116. - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4);
  117. + _rx_delay_intrabit = subtract_cap(bit_delay,
  118. + RXDELAY_READLOOP / DELAY_CYCLE);
  119.  
  120. // There are 37 cycles from the last bit read to the start of
  121. // stopbit delay and 11 cycles from the delay until the interrupt
  122. @@ -389,15 +409,9 @@ void SoftwareSerial::begin(long speed)
  123. // delay will be at 1/4th of the stopbit. This allows some extra
  124. // time for ISR cleanup, which makes 115200 baud at 16Mhz work more
  125. // reliably
  126. - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4);
  127. - #else // Timings counted from gcc 4.3.2 output
  128. - // Note that this code is a _lot_ slower, mostly due to bad register
  129. - // allocation choices of gcc. This works up to 57600 on 16Mhz and
  130. - // 38400 on 8Mhz.
  131. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4);
  132. - _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4);
  133. - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4);
  134. - #endif
  135. + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4,
  136. + (RXDELAY_BEFORESTOP + RXDELAY_AFTERSTOP) /
  137. + DELAY_CYCLE);
  138.  
  139.  
  140. // Enable the PCINT for the entire port here, but never disable it
  141. diff --git a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
  142. index 1e17b2d..b2412f9 100644
  143. --- a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
  144. +++ b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
  145. @@ -85,7 +85,7 @@ private:
  146. static uint16_t subtract_cap(uint16_t num, uint16_t sub);
  147.  
  148. // private static method for timing
  149. - static void _delay_loop_2(uint16_t __count);
  150. + static inline void _delay_loop_2(uint16_t __count);
  151. static inline void tunedDelay(uint16_t delay);
  152.  
  153. public:
Add Comment
Please, Sign In to add comment