Skip to content

Commit 5e5dc05

Browse files
committed
pbio/drv/i2c/i2c_ev3.c: Add interrupt handlers
The PRU uses these events to inform the ARM of completion (both success and failure).
1 parent 635fcf5 commit 5e5dc05

File tree

1 file changed

+79
-1
lines changed

1 file changed

+79
-1
lines changed

lib/pbio/drv/i2c/i2c_ev3.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@
1010
#include <stdbool.h>
1111
#include <stdint.h>
1212
#include <stdio.h>
13+
#include <string.h>
1314

14-
#include <pbdrv/gpio.h>
15+
#include <tiam1808/armv5/am1808/interrupt.h>
16+
#include <tiam1808/hw/hw_types.h>
17+
#include <tiam1808/pruss.h>
18+
19+
#include <pbio/busy_count.h>
1520
#include <pbio/error.h>
21+
#include <pbio/os.h>
1622
#include <pbio/util.h>
1723

1824
#include <pbdrv/i2c.h>
1925

26+
#include "../drv/rproc/rproc.h"
2027
#include "../rproc/rproc_ev3.h"
2128

2229
#define DEBUG 1
@@ -32,12 +39,20 @@
3239
#endif
3340

3441
struct _pbdrv_i2c_dev_t {
42+
volatile bool is_busy;
3543
bool is_initialized;
3644
uint8_t pru_i2c_idx;
3745
};
3846

3947
static pbdrv_i2c_dev_t i2c_devs[PBDRV_RPROC_EV3_PRU1_NUM_I2C_BUSES];
4048

49+
enum {
50+
PRU_I2C_PORT1_EVT = 42,
51+
PRU_I2C_PORT2_EVT = 44,
52+
PRU_I2C_PORT3_EVT = 46,
53+
PRU_I2C_PORT4_EVT = 48,
54+
};
55+
4156
pbio_error_t pbdrv_i2c_get_instance(uint8_t id, pbdrv_i2c_dev_t **i2c_dev) {
4257
if (id >= PBDRV_RPROC_EV3_PRU1_NUM_I2C_BUSES) {
4358
return PBIO_ERROR_INVALID_ARG;
@@ -51,17 +66,80 @@ pbio_error_t pbdrv_i2c_get_instance(uint8_t id, pbdrv_i2c_dev_t **i2c_dev) {
5166
return PBIO_SUCCESS;
5267
}
5368

69+
static void pbdrv_i2c_irq_0(void) {
70+
IntSystemStatusClear(SYS_INT_EVTOUT4);
71+
HWREG(INTC_PHYS_BASE + PRU_INTC_SICR_REG) = PRU_I2C_PORT1_EVT;
72+
i2c_devs[0].is_busy = false;
73+
pbio_os_request_poll();
74+
}
75+
static void pbdrv_i2c_irq_1(void) {
76+
IntSystemStatusClear(SYS_INT_EVTOUT5);
77+
HWREG(INTC_PHYS_BASE + PRU_INTC_SICR_REG) = PRU_I2C_PORT2_EVT;
78+
i2c_devs[1].is_busy = false;
79+
pbio_os_request_poll();
80+
}
81+
static void pbdrv_i2c_irq_2(void) {
82+
IntSystemStatusClear(SYS_INT_EVTOUT6);
83+
HWREG(INTC_PHYS_BASE + PRU_INTC_SICR_REG) = PRU_I2C_PORT3_EVT;
84+
i2c_devs[2].is_busy = false;
85+
pbio_os_request_poll();
86+
}
87+
static void pbdrv_i2c_irq_3(void) {
88+
IntSystemStatusClear(SYS_INT_EVTOUT7);
89+
HWREG(INTC_PHYS_BASE + PRU_INTC_SICR_REG) = PRU_I2C_PORT4_EVT;
90+
i2c_devs[3].is_busy = false;
91+
pbio_os_request_poll();
92+
}
93+
5494
pbio_error_t pbdrv_i2c_placeholder_operation(pbdrv_i2c_dev_t *i2c_dev, const char *operation) {
5595
debug_pr("I2C placeholder operation %s\n", operation);
5696
return PBIO_SUCCESS;
5797
}
5898

99+
static pbio_os_process_t ev3_i2c_init_process;
100+
101+
pbio_error_t ev3_i2c_init_process_thread(pbio_os_state_t *state, void *context) {
102+
PBIO_OS_ASYNC_BEGIN(state);
103+
104+
// Need rproc to be initialized, because it sets up the PRU INTC
105+
PBIO_OS_AWAIT_UNTIL(state, pbdrv_rproc_is_ready());
106+
107+
// REVISIT: These event numbers get set up by the SUART library.
108+
// We should separate them cleanly in the future.
109+
IntRegister(SYS_INT_EVTOUT4, pbdrv_i2c_irq_0);
110+
IntChannelSet(SYS_INT_EVTOUT4, 2);
111+
IntSystemEnable(SYS_INT_EVTOUT4);
112+
HWREG(INTC_PHYS_BASE + PRU_INTC_EISR_REG) = PRU_I2C_PORT1_EVT;
113+
114+
IntRegister(SYS_INT_EVTOUT5, pbdrv_i2c_irq_1);
115+
IntChannelSet(SYS_INT_EVTOUT5, 2);
116+
IntSystemEnable(SYS_INT_EVTOUT5);
117+
HWREG(INTC_PHYS_BASE + PRU_INTC_EISR_REG) = PRU_I2C_PORT2_EVT;
118+
119+
IntRegister(SYS_INT_EVTOUT6, pbdrv_i2c_irq_2);
120+
IntChannelSet(SYS_INT_EVTOUT6, 2);
121+
IntSystemEnable(SYS_INT_EVTOUT6);
122+
HWREG(INTC_PHYS_BASE + PRU_INTC_EISR_REG) = PRU_I2C_PORT3_EVT;
123+
124+
IntRegister(SYS_INT_EVTOUT7, pbdrv_i2c_irq_3);
125+
IntChannelSet(SYS_INT_EVTOUT7, 2);
126+
IntSystemEnable(SYS_INT_EVTOUT7);
127+
HWREG(INTC_PHYS_BASE + PRU_INTC_EISR_REG) = PRU_I2C_PORT4_EVT;
128+
129+
pbio_busy_count_down();
130+
131+
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
132+
}
133+
59134
void pbdrv_i2c_init(void) {
60135
for (int i = 0; i < PBDRV_RPROC_EV3_PRU1_NUM_I2C_BUSES; i++) {
61136
pbdrv_i2c_dev_t *i2c = &i2c_devs[i];
62137
i2c->pru_i2c_idx = i;
63138
i2c->is_initialized = true;
64139
}
140+
141+
pbio_busy_count_up();
142+
pbio_os_process_start(&ev3_i2c_init_process, ev3_i2c_init_process_thread, NULL);
65143
}
66144

67145
#endif // PBDRV_CONFIG_I2C_EV3

0 commit comments

Comments
 (0)