Skip to content

Commit 710e9fb

Browse files
committed
pbio/drv/rproc: Introduce remote coprocessor subsystem
This is currently going to be used to manage the EV3 PRUs, which involve a number of implicit dependencies between unrelated modules. This begins by moving the EV3 PWM logic to depend on the new subsystem.
1 parent b77115b commit 710e9fb

File tree

8 files changed

+106
-44
lines changed

8 files changed

+106
-44
lines changed

bricks/_common/sources.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
175175
drv/reset/reset_nxt.c \
176176
drv/reset/reset_stm32.c \
177177
drv/resistor_ladder/resistor_ladder.c \
178+
drv/rproc/rproc_ev3.c \
178179
drv/sound/beep_sampled.c \
179180
drv/sound/sound_ev3.c \
180181
drv/sound/sound_nxt.c \

lib/pbio/drv/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "pwm/pwm.h"
2626
#include "random/random.h"
2727
#include "reset/reset.h"
28+
#include "rproc/rproc.h"
2829
#include "sound/sound.h"
2930
#include "uart/uart.h"
3031
#include "uart/uart_debug_first_port.h"
@@ -38,6 +39,9 @@ void pbdrv_init(void) {
3839
pbdrv_clock_init();
3940
process_init();
4041
process_start(&etimer_process);
42+
// because a variety of modules can all implicitly depend on coprocessors,
43+
// initialize them next before everything else starts
44+
pbdrv_rproc_init();
4145

4246
// the rest of the drivers should be implemented so that init order doesn't matter
4347
pbdrv_adc_init();

lib/pbio/drv/pwm/pwm_ev3.c

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,75 +5,36 @@
55

66
#if PBDRV_CONFIG_PWM_TIAM1808
77

8-
#include <stdio.h>
9-
#include <string.h>
10-
118
#include <pbdrv/pwm.h>
129
#include <pbdrv/gpio.h>
1310
#include <pbio/error.h>
1411

15-
#include <tiam1808/hw/hw_syscfg0_AM1808.h>
16-
#include <tiam1808/hw/hw_types.h>
17-
#include <tiam1808/hw/soc_AM1808.h>
18-
#include <tiam1808/pruss.h>
19-
#include <tiam1808/psc.h>
20-
#include <tiam1808/timer.h>
21-
2212
#include "../drv/pwm/pwm.h"
2313
#include "../../drv/led/led_pwm.h"
2414
#include "../../drv/pwm/pwm_ev3.h"
2515
#include "../../drv/gpio/gpio_ev3.h"
2616

27-
// This needs to match the interface expected by the PRU firmware
28-
typedef struct shared_ram {
29-
uint8_t pwms[PBDRV_PWM_EV3_NUM_CHANNELS];
30-
} shared_ram;
31-
static volatile shared_ram pru1_shared_ram __attribute__((section(".shared1")));
32-
3317
static pbio_error_t pbdrv_pwm_tiam1808_set_duty(pbdrv_pwm_dev_t *dev, uint32_t ch, uint32_t value) {
3418
// Blue not available.
3519
if (ch == PBDRV_LED_PWM_CHANNEL_INVALID) {
3620
return PBIO_SUCCESS;
3721
}
3822

39-
pru1_shared_ram.pwms[ch] = value;
23+
pbdrv_ev3_pru1_shared_ram.pwms[ch] = value;
4024
return PBIO_SUCCESS;
4125
}
4226

4327
static const pbdrv_pwm_driver_funcs_t pbdrv_pwm_tiam1808_funcs = {
4428
.set_duty = pbdrv_pwm_tiam1808_set_duty,
4529
};
4630

47-
extern char _pru1_start;
48-
extern char _pru1_end;
49-
5031
#define PINMUX_ALT_PRU1 4
5132

5233
void pbdrv_pwm_tiam1808_init(pbdrv_pwm_dev_t *devs) {
53-
// Enable Timer0 "34" half to count up to 256 * 256
54-
// This is used by the PRU to time the PWM
55-
TimerPreScalarCount34Set(SOC_TMR_0_REGS, 0);
56-
TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 256 * 256 - 1);
57-
TimerEnable(SOC_TMR_0_REGS, TMR_TIMER34, TMR_ENABLE_CONT);
58-
59-
// Clear shared command memory
60-
memset((void *)&pru1_shared_ram, 0, sizeof(shared_ram));
61-
62-
// Enable PRU1 and load its firmware
63-
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_PRU, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
64-
PRUSSDRVPruDisable(1);
65-
PRUSSDRVPruReset(1);
66-
unsigned int *fw_start = (unsigned int *)&_pru1_start;
67-
uint32_t fw_sz = &_pru1_end - &_pru1_start;
68-
PRUSSDRVPruWriteMemory(PRUSS0_PRU1_IRAM, 0, fw_start, fw_sz);
69-
// Set constant table C30 to point to shared memory
70-
PRUSSDRVPruSetCTable(1, 30, (((uint32_t)&pru1_shared_ram) >> 8) & 0xffff);
71-
PRUSSDRVPruEnable(1);
72-
7334
devs[0].funcs = &pbdrv_pwm_tiam1808_funcs;
7435

7536
// Set GPIO alt modes for the PRU
76-
for (int j = 0; j < PBDRV_PWM_EV3_NUM_CHANNELS; j++) {
37+
for (int j = 0; j < PBDRV_EV3_PRU1_NUM_PWM_CHANNELS; j++) {
7738
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data.gpios[j], PINMUX_ALT_PRU1);
7839
}
7940
}

lib/pbio/drv/pwm/pwm_ev3.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212

1313
#include <pbdrv/pwm.h>
1414
#include <pbdrv/gpio.h>
15-
16-
#define PBDRV_PWM_EV3_NUM_CHANNELS 4
15+
#include "../rproc/rproc_ev3.h"
1716

1817
/** Platform-specific device information. */
1918
typedef struct {
2019
uint8_t id;
21-
pbdrv_gpio_t gpios[PBDRV_PWM_EV3_NUM_CHANNELS];
20+
pbdrv_gpio_t gpios[PBDRV_EV3_PRU1_NUM_PWM_CHANNELS];
2221
} pbdrv_pwm_tiam1808_platform_data_t;
2322

2423
// Defined in platform.c

lib/pbio/drv/rproc/rproc.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025 The Pybricks Authors
3+
4+
#ifndef _INTERNAL_PBDRV_RPROC_H_
5+
#define _INTERNAL_PBDRV_RPROC_H_
6+
7+
#include <pbdrv/config.h>
8+
9+
#if PBDRV_CONFIG_RPROC
10+
11+
/**
12+
* Initializes "remote" coprocessors early during the startup sequence
13+
*/
14+
void pbdrv_rproc_init(void);
15+
16+
#else // PBDRV_CONFIG_RPROC
17+
18+
#define pbdrv_rproc_init()
19+
20+
#endif // PBDRV_CONFIG_RPROC
21+
22+
#endif // _INTERNAL_PBDRV_RPROC_H_

lib/pbio/drv/rproc/rproc_ev3.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025 The Pybricks Authors
3+
4+
// Manages EV3 PRU coprocessor initialization
5+
6+
#include <pbdrv/config.h>
7+
8+
#if PBDRV_CONFIG_RPROC_EV3
9+
10+
#include <string.h>
11+
12+
#include <tiam1808/hw/hw_syscfg0_AM1808.h>
13+
#include <tiam1808/hw/soc_AM1808.h>
14+
#include <tiam1808/pruss.h>
15+
#include <tiam1808/psc.h>
16+
#include <tiam1808/timer.h>
17+
18+
#include "rproc_ev3.h"
19+
20+
volatile pbdrv_ev3_pru1_shared_ram_t pbdrv_ev3_pru1_shared_ram __attribute__((section(".shared1")));
21+
22+
extern char _pru1_start;
23+
extern char _pru1_end;
24+
25+
void pbdrv_rproc_init(void) {
26+
// Enable PRU subsystem
27+
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_PRU, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
28+
29+
// PRU1 initialization
30+
31+
// Enable Timer0 "34" half to count up to 256 * 256
32+
// This is used by the PRU to time the PWM
33+
TimerPreScalarCount34Set(SOC_TMR_0_REGS, 0);
34+
TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 256 * 256 - 1);
35+
TimerEnable(SOC_TMR_0_REGS, TMR_TIMER34, TMR_ENABLE_CONT);
36+
37+
// Clear shared command memory
38+
memset((void *)&pbdrv_ev3_pru1_shared_ram, 0, sizeof(pbdrv_ev3_pru1_shared_ram));
39+
40+
// Enable PRU1 and load its firmware
41+
PRUSSDRVPruDisable(1);
42+
PRUSSDRVPruReset(1);
43+
unsigned int *fw_start = (unsigned int *)&_pru1_start;
44+
uint32_t fw_sz = &_pru1_end - &_pru1_start;
45+
PRUSSDRVPruWriteMemory(PRUSS0_PRU1_IRAM, 0, fw_start, fw_sz);
46+
// Set constant table C30 to point to shared memory
47+
PRUSSDRVPruSetCTable(1, 30, (((uint32_t)&pbdrv_ev3_pru1_shared_ram) >> 8) & 0xffff);
48+
PRUSSDRVPruEnable(1);
49+
}
50+
51+
#endif // PBDRV_CONFIG_RPROC_EV3

lib/pbio/drv/rproc/rproc_ev3.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: MIT
2+
// Copyright (c) 2025 The Pybricks Authors
3+
4+
#ifndef _INTERNAL_PBDRV_RPROC_EV3_H_
5+
#define _INTERNAL_PBDRV_RPROC_EV3_H_
6+
7+
#include <stdint.h>
8+
9+
// EV3 PRU interfaces and ABI
10+
// These need to match the interface expected by the PRU firmware
11+
12+
// PRU1 interface
13+
14+
#define PBDRV_EV3_PRU1_NUM_PWM_CHANNELS 4
15+
typedef struct pbdrv_ev3_pru1_shared_ram_t {
16+
uint8_t pwms[PBDRV_EV3_PRU1_NUM_PWM_CHANNELS];
17+
} pbdrv_ev3_pru1_shared_ram_t;
18+
19+
extern volatile pbdrv_ev3_pru1_shared_ram_t pbdrv_ev3_pru1_shared_ram;
20+
21+
#endif // _INTERNAL_PBDRV_RPROC_EV3_H_

lib/pbio/platform/ev3/pbdrvconfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070
#define PBDRV_CONFIG_RESET (1)
7171
#define PBDRV_CONFIG_RESET_EV3 (1)
7272

73+
#define PBDRV_CONFIG_RPROC (1)
74+
#define PBDRV_CONFIG_RPROC_EV3 (1)
75+
7376
#define PBDRV_CONFIG_SOUND (1)
7477
#define PBDRV_CONFIG_SOUND_EV3 (1)
7578
#define PBDRV_CONFIG_SOUND_DEFAULT_VOLUME 75

0 commit comments

Comments
 (0)