|
15 | 15 |
|
16 | 16 | #include "resource_table.h" |
17 | 17 |
|
18 | | -/* from Linux */ |
19 | | - |
20 | | -#define EV3_PRU_TACHO_RING_BUF_SIZE 1024 /* must be power of 2! */ |
21 | | - |
22 | | -enum ev3_pru_tacho_msg_type { |
23 | | - /* Host >< PRU: request memory map address of ring buffer data */ |
24 | | - EV3_PRU_TACHO_MSG_DATA_ADDR, |
25 | | -}; |
26 | | - |
27 | | -struct ev3_pru_tacho_msg { |
28 | | - uint32_t type; |
29 | | - uint32_t value; |
30 | | -}; |
31 | | - |
32 | | -enum ev3_pru_tacho { |
33 | | - EV3_PRU_TACHO_A, |
34 | | - EV3_PRU_TACHO_B, |
35 | | - EV3_PRU_TACHO_C, |
36 | | - EV3_PRU_TACHO_D, |
37 | | - NUM_EV3_PRU_TACHO |
38 | | -}; |
39 | | - |
40 | | -struct ev3_pru_tacho_remote_data { |
41 | | - uint32_t position[NUM_EV3_PRU_TACHO][EV3_PRU_TACHO_RING_BUF_SIZE]; |
42 | | - uint32_t timestamp[NUM_EV3_PRU_TACHO][EV3_PRU_TACHO_RING_BUF_SIZE]; |
43 | | - uint32_t head[NUM_EV3_PRU_TACHO]; |
44 | | -}; |
45 | | - |
46 | | -/* end Linux */ |
47 | | - |
48 | | -enum direction { |
49 | | - REVERSE = -1, |
50 | | - UNKNOWN = 0, |
51 | | - FORWARD = 1 |
52 | | -}; |
53 | | - |
54 | | -#define REMOTE_DATA_ADDR 0x80002000 |
55 | | -#define REMOTE_DATA (*(struct ev3_pru_tacho_remote_data *)(REMOTE_DATA_ADDR)) |
56 | 18 |
|
57 | 19 | // system events to/from ARM |
58 | 20 |
|
59 | 21 | // PRU0 |
60 | 22 | #define HOST_INT (uint32_t)(1 << 30) // host interrupt 0 |
61 | | -#define EVENT_FROM_ARM 32 |
62 | | -#define EVENT_TO_ARM 33 |
| 23 | +#define EVENT_FROM_ARM 60 |
| 24 | +#define EVENT_TO_ARM 61 |
63 | 25 |
|
64 | 26 | // PRU1 |
65 | 27 | //#define HOST_INT (uint32_t)(1 << 31) // host interrupt 1 |
66 | | -//#define EVENT_FROM_ARM 34 |
67 | | -//#define EVENT_TO_ARM 35 |
| 28 | +//#define EVENT_FROM_ARM 62 |
| 29 | +//#define EVENT_TO_ARM 63 |
68 | 30 |
|
69 | 31 | volatile uint32_t register __R31; |
70 | 32 |
|
71 | | -// This is 512B (RPMSG_BUF_SIZE), so it won't fit in PRU RAM, so put it in shared RAM |
72 | | -#define payload ((void *)(REMOTE_DATA_ADDR + sizeof(struct ev3_pru_tacho_remote_data))) |
73 | | - |
74 | | -#define INTA GPIO.IN_DATA45_bit.GP5P11 // GPIO 5[11] |
75 | | -#define INTB GPIO.IN_DATA45_bit.GP5P8 // GPIO 5[8] |
76 | | -#define INTC GPIO.IN_DATA45_bit.GP5P13 // GPIO 5[13] |
77 | | -#define INTD GPIO.IN_DATA67_bit.GP6P9 // GPIO 6[9] |
78 | | - |
79 | | -#define DIRA GPIO.IN_DATA01_bit.GP0P4 // GPIO 0[4] |
80 | | -#define DIRB GPIO.IN_DATA23_bit.GP2P9 // GPIO 2[9] |
81 | | -#define DIRC GPIO.IN_DATA23_bit.GP3P14 // GPIO 3[14] |
82 | | -#define DIRD GPIO.IN_DATA23_bit.GP2P8 // GPIO 2[8] |
83 | | - |
84 | | -#define TACHO_STATE(x) ((INT##x << 1) | DIR##x) |
85 | | - |
86 | | -static uint8_t tacho_state[NUM_EV3_PRU_TACHO]; |
87 | | -static uint32_t tacho_prev_timestamp[NUM_EV3_PRU_TACHO]; |
88 | | -static uint32_t tacho_counts[NUM_EV3_PRU_TACHO]; |
89 | | - |
90 | | -static void update_tacho_state(enum ev3_pru_tacho idx, uint8_t new_state) |
91 | | -{ |
92 | | - uint8_t current_state = tacho_state[idx] & 0x3; |
93 | | - enum direction new_dir = UNKNOWN; |
94 | | - uint32_t now, elapsed; |
95 | | - |
96 | | - switch (current_state) { |
97 | | - case 0x0: |
98 | | - if (new_state == 0x1) { |
99 | | - new_dir = REVERSE; |
100 | | - } else if (new_state == 0x2) { |
101 | | - new_dir = FORWARD; |
102 | | - } |
103 | | - break; |
104 | | - |
105 | | - case 0x1: |
106 | | - if (new_state == 0x3) { |
107 | | - new_dir = REVERSE; |
108 | | - } else if (new_state == 0x0) { |
109 | | - new_dir = FORWARD; |
110 | | - } |
111 | | - break; |
112 | | - |
113 | | - case 0x3: |
114 | | - if (new_state == 0x2) { |
115 | | - new_dir = REVERSE; |
116 | | - } else if (new_state == 0x1) { |
117 | | - new_dir = FORWARD; |
118 | | - } |
119 | | - break; |
120 | | - |
121 | | - case 0x2: |
122 | | - if (new_state == 0x0) { |
123 | | - new_dir = REVERSE; |
124 | | - } else if (new_state == 0x3) { |
125 | | - new_dir = FORWARD; |
126 | | - } |
127 | | - break; |
128 | | - } |
129 | | - |
130 | | - tacho_state[idx] = new_state; |
131 | | - tacho_counts[idx] += new_dir; |
| 33 | +// only have 512B for stack/data, so this won't fit |
| 34 | +//uint8_t payload[RPMSG_BUF_SIZE]; |
| 35 | +// using 128K shared RAM for now |
| 36 | +#define payload ((uint8_t *)(0x8001F200)) |
132 | 37 |
|
133 | | - now = TIMER64P0.TIM34; |
134 | | - elapsed = now - tacho_prev_timestamp[idx]; |
135 | | - |
136 | | - // if there was a change in count or if count hasn't changed for 50ms |
137 | | - if (new_dir || elapsed > (50 * 1000000 * 3 / 125)) { |
138 | | - uint32_t new_head = (REMOTE_DATA.head[idx] + 1) & (EV3_PRU_TACHO_RING_BUF_SIZE - 1); |
139 | | - |
140 | | - tacho_prev_timestamp[idx] = now; |
141 | | - |
142 | | - REMOTE_DATA.position[idx][new_head] = tacho_counts[idx]; |
143 | | - REMOTE_DATA.timestamp[idx][new_head] = now; |
144 | | - REMOTE_DATA.head[idx] = new_head; |
145 | | - } |
146 | | -} |
| 38 | +#define LED (GPIO.OUT_DATA67_bit.GP6P7) |
147 | 39 |
|
148 | 40 | int main(void) { |
149 | 41 | volatile uint8_t *status; |
150 | 42 | struct pru_rpmsg_transport transport; |
151 | 43 | uint16_t src, dst, len; |
152 | 44 |
|
153 | 45 | // Clear the status of the PRU-system event that the ARM will use to 'kick' us |
154 | | - PRU_INTC.STATIDXCLR = EVENT_FROM_ARM; |
| 46 | + PRU_INTC.STATIDXCLR_bit.INDEX = EVENT_FROM_ARM; |
155 | 47 |
|
156 | 48 | // Wait until Linux gives us the OK that the driver is loaded |
157 | 49 | status = &resource_table.rpmsg_vdev.status; |
158 | 50 | while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK)); |
159 | 51 |
|
160 | | - pru_virtqueue_init(&transport.virtqueue0, &resource_table.vring0, EVENT_TO_ARM, EVENT_FROM_ARM); |
161 | | - pru_virtqueue_init(&transport.virtqueue1, &resource_table.vring1, EVENT_TO_ARM, EVENT_FROM_ARM); |
| 52 | + pru_rpmsg_init(&transport, &resource_table.vring0, &resource_table.vring1, EVENT_TO_ARM, EVENT_FROM_ARM); |
162 | 53 |
|
163 | | - while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, "ev3-tacho-rpmsg", 0) != PRU_RPMSG_SUCCESS); |
| 54 | + while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, "rpmsg-client-sample", 0) != PRU_RPMSG_SUCCESS); |
164 | 55 |
|
165 | 56 | while (true) { |
166 | | - // wait for the ARM to kick us |
167 | | - while (!(__R31 & HOST_INT)) { |
168 | | - update_tacho_state(EV3_PRU_TACHO_A, TACHO_STATE(A)); |
169 | | - update_tacho_state(EV3_PRU_TACHO_B, TACHO_STATE(B)); |
170 | | - update_tacho_state(EV3_PRU_TACHO_C, TACHO_STATE(C)); |
171 | | - update_tacho_state(EV3_PRU_TACHO_D, TACHO_STATE(D)); |
172 | | - } |
173 | | - |
174 | | - // clear the interrupt |
175 | | - PRU_INTC.STATIDXCLR = EVENT_FROM_ARM; |
176 | | - |
177 | | - // Receive all available messages, multiple messages can be sent per kick |
178 | | - while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) { |
179 | | - struct ev3_pru_tacho_msg *msg = payload; |
180 | | - |
181 | | - switch (msg->type) { |
182 | | - case EV3_PRU_TACHO_MSG_DATA_ADDR: |
183 | | - msg->value = REMOTE_DATA_ADDR; |
184 | | - pru_rpmsg_send(&transport, dst, src, msg, sizeof(*msg)); |
185 | | - break; |
| 57 | + // Check bit 30 of register R31 to see if the ARM has kicked us |
| 58 | + if (__R31 & HOST_INT) { |
| 59 | + // clear the interrupt |
| 60 | + PRU_INTC.STATIDXCLR_bit.INDEX = EVENT_FROM_ARM; |
| 61 | + |
| 62 | + // Receive all available messages, multiple messages can be sent per kick |
| 63 | + while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) { |
| 64 | + // Echo the message back |
| 65 | + pru_rpmsg_send(&transport, dst, src, payload, len); |
186 | 66 | } |
187 | 67 | } |
188 | 68 | } |
|
0 commit comments