Guest User

Untitled

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