Advertisement
Guest User

Untitled

a guest
Jun 24th, 2021
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.95 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stddef.h>
  3. #include "pru_uart.h"
  4. #include "pru_ecap.h"
  5.  
  6. struct Message {
  7. uint32_t id;
  8. uint32_t timestamp;
  9. uint32_t position;
  10. int32_t force;
  11. };
  12.  
  13. // encoder position in other PRU core's memory
  14. #define position_var ((uint32_t const volatile *)0x00002000)
  15.  
  16. // layout of shared ddr3 memory (filled in by loader)
  17. struct DDRLayout {
  18. Message volatile *msgbuf;
  19. uint16_t num_msgs;
  20. uint16_t msg_size;
  21. };
  22.  
  23. struct SharedVars {
  24. // set by pru before halting
  25. char const *abort_file;
  26. int abort_line;
  27. // read-pointer updated by python
  28. uint16_t ridx;
  29. };
  30.  
  31. far struct DDRLayout ddr __attribute__((location(0x10000))) = {};
  32. far struct SharedVars volatile shmem __attribute__((location(0x10100))) = {};
  33.  
  34. static inline uint32_t timestamp_cycles()
  35. {
  36. return CT_ECAP.TSCTR;
  37. }
  38.  
  39. uint32_t timestamp()
  40. {
  41. static uint32_t now = 0;
  42. return now += (uint16_t)( ( timestamp_cycles() >> 16 ) - now );
  43. }
  44.  
  45.  
  46. // for easier debugging, record where in the source code we halted
  47. __attribute__((noreturn))
  48. void abort_at( char const *file, int line )
  49. {
  50. shmem.abort_file = file;
  51. shmem.abort_line = line;
  52. for(;;) __halt();
  53. }
  54.  
  55. static inline void assert_at( bool cond, char const *file, int line )
  56. {
  57. if( ! cond )
  58. abort_at( file, line );
  59. }
  60.  
  61. #define abort() abort_at( __FILE__, __LINE__ )
  62. #define assert(cond) assert_at( (cond), __FILE__, __LINE__ )
  63.  
  64. // local copy of write-pointer
  65. static uint16_t widx = 0;
  66.  
  67. // global var for write-pointer is located right after message ringbuffer
  68. #define ddr_msgbuf_end ( ddr.msgbuf + ddr.num_msgs )
  69. #define ddr_widx ( *(uint16_t volatile *)ddr_msgbuf_end )
  70.  
  71. // receive byte from uart
  72. static inline char uart_recv_byte()
  73. {
  74. for(;;) {
  75. uint8_t lsr = CT_UART.LSR;
  76. if( lsr & 0x1e )
  77. abort(); // receive-error occurred
  78. if( lsr & 0x01 )
  79. return (char) CT_UART.RBR;
  80. }
  81. }
  82.  
  83.  
  84. // receive CR-terminated line from uart
  85. static inline uint8_t uart_recv_line( char volatile msg[], uint8_t maxlen )
  86. {
  87. uint8_t len = 0;
  88.  
  89. for(;;) {
  90. char c = uart_recv_byte();
  91. if( c == '\r' )
  92. break; // found end of line
  93. if( len == maxlen )
  94. abort(); // line does not fit in buffer
  95. msg[ len++ ] = c;
  96. }
  97.  
  98. return len;
  99. }
  100.  
  101. int32_t receive_measurement()
  102. {
  103. // allocate buffer at fixed address for debugging convenience
  104. static char volatile msg[8] __attribute__((location(0x1f00)));
  105.  
  106. // receive line from uart
  107. uint8_t len = uart_recv_line( msg, sizeof msg );
  108.  
  109. // verify length and prefix
  110. if( len != 8 || msg[0] != 'N' || (msg[1] != '+' && msg[1] != '-'))
  111. abort();
  112.  
  113. // parse the remainder as integer
  114. int32_t value = 0;
  115. uint8_t i;
  116. for( i = 2; i < len; i++ ) {
  117. if( msg[i] < '0' || msg[i] > '9' )
  118. abort();
  119. value = value * 10 + ( msg[i] - '0' );
  120. }
  121. if (msg[1] == '-')
  122. value *= -1;
  123.  
  124. return value;
  125. }
  126.  
  127.  
  128. void initialize()
  129. {
  130. // perform sanity-checking
  131. assert( 0x80000000 <= (uint32_t)ddr.msgbuf );
  132. assert( ddr.msgbuf < ddr_msgbuf_end );
  133. assert( ddr.msg_size == sizeof(Message) );
  134.  
  135. assert( ddr_widx == widx );
  136. assert( shmem.ridx == widx );
  137. }
  138.  
  139.  
  140. static inline uint16_t next_idx( uint16_t idx )
  141. {
  142. if( ++idx == ddr.num_msgs )
  143. idx = 0;
  144. return idx;
  145. }
  146.  
  147.  
  148. void send_message( uint32_t id)
  149. {
  150. uint16_t next_widx = next_idx( widx );
  151.  
  152. if( next_widx == shmem.ridx ) {
  153. // can't send message, ringbuffer is full
  154. abort();
  155. }
  156.  
  157. Message volatile *msg = &ddr.msgbuf[ widx ];
  158.  
  159. // fill in contents of message
  160. msg->id = id;
  161. msg->position = *position_var;
  162. msg->force = receive_measurement();
  163. msg->timestamp = timestamp();
  164. // update write-pointer
  165. ddr_widx = widx = next_widx;
  166. }
  167.  
  168. void main() {
  169. initialize();
  170.  
  171. CT_UART.THR = 'S';
  172. CT_UART.THR = 'N';
  173. CT_UART.THR = '\r';
  174.  
  175. uint32_t id = 0;
  176. for(;;) {
  177. send_message( ++id );
  178. __delay_cycles( 10000 );
  179. }
  180. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement