Skip to content

Commit 73fc991

Browse files
committed
pbio/drv/pwm/pwm_ev3: Load PRU firmware which implements LED PWM
1 parent 49f716f commit 73fc991

File tree

3 files changed

+62
-16
lines changed

3 files changed

+62
-16
lines changed

bricks/_common/arm_none_eabi.mk

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ OBJ += $(addprefix $(BUILD)/, $(TI_AM1808_USB_SRC_C:.c=.o))
564564
OBJ += $(addprefix $(BUILD)/, $(EV3_SRC_S:.S=.o))
565565
$(addprefix $(BUILD)/, $(EV3_SRC_S:.S=.o)): CFLAGS += -D__ASSEMBLY__
566566
OBJ += $(BUILD)/pru_suart.bin.o
567+
OBJ += $(BUILD)/pru_ledpwm.bin.o
567568
endif
568569

569570
# List of sources for qstr extraction
@@ -637,6 +638,11 @@ $(BUILD)/u-boot.bin:
637638
$(Q)mkdir -p $(dir $@)
638639
$(Q)curl -sL -o $@ https://github.com/pybricks/u-boot/releases/download/pybricks/v2.0.1/u-boot.bin
639640
$(Q)echo "86ddad84f64d8aea85b4315fc1414bdec0bb0d46c92dbd3db45ed599e3a994cb $@" | sha256sum -c --strict
641+
$(BUILD)/pru_ledpwm.bin:
642+
$(ECHO) "Downloading pru_ledpwm.bin"
643+
$(Q)mkdir -p $(dir $@)
644+
$(Q)curl -sL -o $@ https://github.com/pybricks/pybricks-pru/releases/download/v0.0.1/pru_ledpwm.bin
645+
$(Q)echo "c0138addb8ebb3d0f531499b6f45ccc71f524afbb6ce55ca3ab462a001ec28d2 $@" | sha256sum -c --strict
640646

641647
MAKE_BOOTABLE_IMAGE = $(PBTOP)/bricks/ev3/make_bootable_image.py
642648

@@ -668,6 +674,9 @@ $(BUILD)/firmware.zip: $(ZIP_FILES)
668674
$(BUILD)/pru_suart.bin.o: $(PBTOP)/lib/pbio/drv/uart/uart_ev3_pru_lib/pru_suart.bin
669675
$(Q)$(OBJCOPY) -I binary -O elf32-littlearm -B arm \
670676
--rename-section .data=.pru0,alloc,load,readonly,data,contents $^ $@
677+
$(BUILD)/pru_ledpwm.bin.o: $(BUILD)/pru_ledpwm.bin
678+
$(Q)$(OBJCOPY) -I binary -O elf32-littlearm -B arm \
679+
--rename-section .data=.pru1,alloc,load,readonly,data,contents $^ $@
671680

672681
# firmware in DFU format
673682
$(BUILD)/%.dfu: $(BUILD)/%-base.bin

lib/pbio/drv/pwm/pwm_ev3.c

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,71 @@
1111
#include <pbdrv/gpio.h>
1212
#include <pbio/error.h>
1313

14+
#include <tiam1808/hw/hw_syscfg0_AM1808.h>
15+
#include <tiam1808/hw/hw_types.h>
16+
#include <tiam1808/hw/soc_AM1808.h>
17+
#include <tiam1808/pruss.h>
18+
#include <tiam1808/psc.h>
19+
#include <tiam1808/timer.h>
20+
1421
#include "../drv/pwm/pwm.h"
1522
#include "../../drv/pwm/pwm_ev3.h"
1623
#include "../../drv/gpio/gpio_ev3.h"
1724

25+
// This is the second 64K of the on-chip RAM
26+
#define PRU1_SHARED_RAM_ADDR 0x80010000
27+
28+
// This needs to match the interface expected by the PRU firmware
29+
typedef struct shared_ram {
30+
uint8_t pwms[4];
31+
} shared_ram;
32+
static volatile shared_ram *const pru1_shared_ram = (volatile shared_ram *)PRU1_SHARED_RAM_ADDR;
33+
1834
static pbio_error_t pbdrv_pwm_tiam1808_set_duty(pbdrv_pwm_dev_t *dev, uint32_t ch, uint32_t value) {
19-
// Blue not available.
20-
if (ch == 2) {
21-
return PBIO_SUCCESS;
22-
}
23-
pbdrv_pwm_tiam1808_platform_data_t *priv = dev->priv;
24-
25-
// TODO: implement PWM. Just use GPIO for now.
26-
pbdrv_gpio_t *gpio = (ch == 0) ? &priv->gpio_red : &priv->gpio_green;
27-
if (value) {
28-
pbdrv_gpio_out_high(gpio);
29-
} else {
30-
pbdrv_gpio_out_low(gpio);
31-
}
35+
// TODO: Reimplement this function to use the PRU
3236
return PBIO_SUCCESS;
3337
}
3438

3539
static const pbdrv_pwm_driver_funcs_t pbdrv_pwm_tiam1808_funcs = {
3640
.set_duty = pbdrv_pwm_tiam1808_set_duty,
3741
};
3842

43+
extern char _pru1_start;
44+
extern char _pru1_end;
45+
3946
void pbdrv_pwm_tiam1808_init(pbdrv_pwm_dev_t *devs) {
47+
// Enable Timer0 "34" half to count up to 256 * 256
48+
// This is used by the PRU to time the PWM
49+
TimerPreScalarCount34Set(SOC_TMR_0_REGS, 0);
50+
TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 256 * 256 - 1);
51+
TimerEnable(SOC_TMR_0_REGS, TMR_TIMER34, TMR_ENABLE_CONT);
52+
53+
// Set GPIO alt modes for the PRU
54+
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data[0].gpio_red, SYSCFG_PINMUX13_PINMUX13_11_8_PRU1_R30_12);
55+
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data[0].gpio_green, SYSCFG_PINMUX14_PINMUX14_3_0_PRU1_R30_10);
56+
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data[1].gpio_red, SYSCFG_PINMUX13_PINMUX13_15_12_PRU1_R30_11);
57+
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data[1].gpio_green, SYSCFG_PINMUX13_PINMUX13_7_4_PRU1_R30_13);
58+
59+
// TODO: Remove this test code
60+
pru1_shared_ram->pwms[0] = 0x20; // R
61+
pru1_shared_ram->pwms[1] = 0xc0; // G
62+
pru1_shared_ram->pwms[2] = 0x10; // R
63+
pru1_shared_ram->pwms[3] = 0xf0; // G
64+
65+
// Enable PRU1 and load its firmware
66+
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_PRU, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
67+
PRUSSDRVPruDisable(1);
68+
PRUSSDRVPruReset(1);
69+
unsigned int *fw_start = (unsigned int *)&_pru1_start;
70+
uint32_t fw_sz = &_pru1_end - &_pru1_start;
71+
PRUSSDRVPruWriteMemory(PRUSS0_PRU1_IRAM, 0, fw_start, fw_sz);
72+
// Set constant table C30 to point to 0x80010000
73+
HWREG(PRU1CONTROL_PHYS_BASE + 0x2c) = (PRU1_SHARED_RAM_ADDR >> 8) & 0xffff;
74+
PRUSSDRVPruEnable(1);
75+
4076
for (int i = 0; i < PBDRV_CONFIG_PWM_TIAM1808_NUM_DEV; i++) {
4177
devs[i].funcs = &pbdrv_pwm_tiam1808_funcs;
4278
devs[i].priv = (pbdrv_pwm_tiam1808_platform_data_t *)&pbdrv_pwm_tiam1808_platform_data[i];
43-
44-
pbdrv_gpio_out_low(&pbdrv_pwm_tiam1808_platform_data[i].gpio_red);
45-
pbdrv_gpio_out_low(&pbdrv_pwm_tiam1808_platform_data[i].gpio_green);
4679
}
4780
}
4881

lib/pbio/platform/ev3/platform.ld

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ SECTIONS
3838
KEEP(*(.pru0));
3939
. = ALIGN(4);
4040
_pru0_end = .;
41+
_pru1_start = .;
42+
KEEP(*(.pru1));
43+
. = ALIGN(4);
44+
_pru1_end = .;
4145
} >DDR
4246

4347
.data :

0 commit comments

Comments
 (0)