Skip to content

Commit 5572df1

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 6bfbae8 commit 5572df1

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,13 +39,21 @@
3239
#endif
3340

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

3947
static pbdrv_i2c_dev_t i2c_devs[PBDRV_CONFIG_I2C_EV3_NUM_DEV];
4048
_Static_assert(PBDRV_CONFIG_I2C_EV3_NUM_DEV <= PBDRV_RPROC_EV3_PRU1_NUM_I2C_CHANNELS);
4149

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

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

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

68146
#endif // PBDRV_CONFIG_I2C_EV3

0 commit comments

Comments
 (0)