Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bricks/_common/arm_none_eabi.mk
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ OBJ += $(addprefix $(BUILD)/, $(TI_AM1808_USB_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(EV3_SRC_S:.S=.o))
$(addprefix $(BUILD)/, $(EV3_SRC_S:.S=.o)): CFLAGS += -D__ASSEMBLY__
OBJ += $(BUILD)/pru_suart.bin.o
OBJ += $(BUILD)/pru_ledpwm.bin.o
endif

# List of sources for qstr extraction
Expand Down Expand Up @@ -637,6 +638,11 @@ $(BUILD)/u-boot.bin:
$(Q)mkdir -p $(dir $@)
$(Q)curl -sL -o $@ https://github.com/pybricks/u-boot/releases/download/pybricks/v2.0.1/u-boot.bin
$(Q)echo "86ddad84f64d8aea85b4315fc1414bdec0bb0d46c92dbd3db45ed599e3a994cb $@" | sha256sum -c --strict
$(BUILD)/pru_ledpwm.bin:
$(ECHO) "Downloading pru_ledpwm.bin"
$(Q)mkdir -p $(dir $@)
$(Q)curl -sL -o $@ https://github.com/pybricks/pybricks-pru/releases/download/v0.0.1/pru_ledpwm.bin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would already call it v1.0.0. (I no longer believe in https://0ver.org/) 😆

$(Q)echo "c0138addb8ebb3d0f531499b6f45ccc71f524afbb6ce55ca3ab462a001ec28d2 $@" | sha256sum -c --strict

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

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

# firmware in DFU format
$(BUILD)/%.dfu: $(BUILD)/%-base.bin
Expand Down
2 changes: 2 additions & 0 deletions lib/pbio/drv/led/led_pwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ typedef struct {
uint8_t scale_factor;
} pbdrv_led_pwm_platform_data_t;

#define PBDRV_LED_PWM_CHANNEL_INVALID 0xff

// defined in platform/*/platform.c
extern const pbdrv_led_pwm_platform_data_t pbdrv_led_pwm_platform_data[PBDRV_CONFIG_LED_PWM_NUM_DEV];

Expand Down
62 changes: 47 additions & 15 deletions lib/pbio/drv/pwm/pwm_ev3.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,75 @@
#if PBDRV_CONFIG_PWM_TIAM1808

#include <stdio.h>
#include <string.h>

#include <pbdrv/pwm.h>
#include <pbdrv/gpio.h>
#include <pbio/error.h>

#include <tiam1808/hw/hw_syscfg0_AM1808.h>
#include <tiam1808/hw/hw_types.h>
#include <tiam1808/hw/soc_AM1808.h>
#include <tiam1808/pruss.h>
#include <tiam1808/psc.h>
#include <tiam1808/timer.h>

#include "../drv/pwm/pwm.h"
#include "../../drv/led/led_pwm.h"
#include "../../drv/pwm/pwm_ev3.h"
#include "../../drv/gpio/gpio_ev3.h"

// This needs to match the interface expected by the PRU firmware
typedef struct shared_ram {
uint8_t pwms[PBDRV_PWM_EV3_NUM_CHANNELS];
} shared_ram;
static volatile shared_ram pru1_shared_ram __attribute__((section(".shared1")));

static pbio_error_t pbdrv_pwm_tiam1808_set_duty(pbdrv_pwm_dev_t *dev, uint32_t ch, uint32_t value) {
// Blue not available.
if (ch == 2) {
if (ch == PBDRV_LED_PWM_CHANNEL_INVALID) {
return PBIO_SUCCESS;
}
pbdrv_pwm_tiam1808_platform_data_t *priv = dev->priv;

// TODO: implement PWM. Just use GPIO for now.
pbdrv_gpio_t *gpio = (ch == 0) ? &priv->gpio_red : &priv->gpio_green;
if (value) {
pbdrv_gpio_out_high(gpio);
} else {
pbdrv_gpio_out_low(gpio);
}

pru1_shared_ram.pwms[ch] = value;
return PBIO_SUCCESS;
}

static const pbdrv_pwm_driver_funcs_t pbdrv_pwm_tiam1808_funcs = {
.set_duty = pbdrv_pwm_tiam1808_set_duty,
};

extern char _pru1_start;
extern char _pru1_end;

#define PINMUX_ALT_PRU1 4

void pbdrv_pwm_tiam1808_init(pbdrv_pwm_dev_t *devs) {
for (int i = 0; i < PBDRV_CONFIG_PWM_TIAM1808_NUM_DEV; i++) {
devs[i].funcs = &pbdrv_pwm_tiam1808_funcs;
devs[i].priv = (pbdrv_pwm_tiam1808_platform_data_t *)&pbdrv_pwm_tiam1808_platform_data[i];
// Enable Timer0 "34" half to count up to 256 * 256
// This is used by the PRU to time the PWM
TimerPreScalarCount34Set(SOC_TMR_0_REGS, 0);
TimerPeriodSet(SOC_TMR_0_REGS, TMR_TIMER34, 256 * 256 - 1);
TimerEnable(SOC_TMR_0_REGS, TMR_TIMER34, TMR_ENABLE_CONT);

// Clear shared command memory
memset((void *)&pru1_shared_ram, 0, sizeof(shared_ram));

// Enable PRU1 and load its firmware
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_PRU, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
PRUSSDRVPruDisable(1);
PRUSSDRVPruReset(1);
unsigned int *fw_start = (unsigned int *)&_pru1_start;
uint32_t fw_sz = &_pru1_end - &_pru1_start;
PRUSSDRVPruWriteMemory(PRUSS0_PRU1_IRAM, 0, fw_start, fw_sz);
// Set constant table C30 to point to shared memory
PRUSSDRVPruSetCTable(1, 30, (((uint32_t)&pru1_shared_ram) >> 8) & 0xffff);
PRUSSDRVPruEnable(1);

devs[0].funcs = &pbdrv_pwm_tiam1808_funcs;

pbdrv_gpio_out_low(&pbdrv_pwm_tiam1808_platform_data[i].gpio_red);
pbdrv_gpio_out_low(&pbdrv_pwm_tiam1808_platform_data[i].gpio_green);
// Set GPIO alt modes for the PRU
for (int j = 0; j < PBDRV_PWM_EV3_NUM_CHANNELS; j++) {
pbdrv_gpio_alt(&pbdrv_pwm_tiam1808_platform_data.gpios[j], PINMUX_ALT_PRU1);
}
}

Expand Down
8 changes: 4 additions & 4 deletions lib/pbio/drv/pwm/pwm_ev3.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
#include <pbdrv/pwm.h>
#include <pbdrv/gpio.h>

#define PBDRV_PWM_EV3_NUM_CHANNELS 4

/** Platform-specific device information. */
typedef struct {
uint8_t id;
pbdrv_gpio_t gpio_red;
pbdrv_gpio_t gpio_green;
pbdrv_gpio_t gpios[PBDRV_PWM_EV3_NUM_CHANNELS];
} pbdrv_pwm_tiam1808_platform_data_t;

// Defined in platform.c
extern const pbdrv_pwm_tiam1808_platform_data_t
pbdrv_pwm_tiam1808_platform_data[PBDRV_CONFIG_PWM_TIAM1808_NUM_DEV];
extern const pbdrv_pwm_tiam1808_platform_data_t pbdrv_pwm_tiam1808_platform_data;

void pbdrv_pwm_tiam1808_init(pbdrv_pwm_dev_t *devs);

Expand Down
1 change: 0 additions & 1 deletion lib/pbio/platform/ev3/pbdrvconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
#define PBDRV_CONFIG_PWM (1)
#define PBDRV_CONFIG_PWM_NUM_DEV (2)
#define PBDRV_CONFIG_PWM_TIAM1808 (1)
#define PBDRV_CONFIG_PWM_TIAM1808_NUM_DEV (2)

#define PBDRV_CONFIG_RESET (1)
#define PBDRV_CONFIG_RESET_EV3 (1)
Expand Down
44 changes: 20 additions & 24 deletions lib/pbio/platform/ev3/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ enum {
};

enum {
PWM_DEV_0_TODO,
PWM_DEV_1_TODO,
PWM_DEV_0,
};

// LED
Expand All @@ -87,7 +86,7 @@ const pbdrv_led_dual_platform_data_t pbdrv_led_dual_platform_data[PBDRV_CONFIG_L
};

static const pbdrv_led_pwm_platform_color_t pbdrv_led_pwm_color = {
// TODO: PWM not yet implemented, so these values not used.
// TODO: Calibrate these numbers, as well as .scale_factor
.r_factor = 1000,
.g_factor = 170,
.b_factor = 200,
Expand All @@ -100,42 +99,39 @@ const pbdrv_led_pwm_platform_data_t pbdrv_led_pwm_platform_data[PBDRV_CONFIG_LED
{
.color = &pbdrv_led_pwm_color,
.id = LED_DEV_1_STATUS_LEFT,
.r_id = PWM_DEV_0_TODO,
.r_id = PWM_DEV_0,
.r_ch = 0,
.g_id = PWM_DEV_0_TODO,
.g_id = PWM_DEV_0,
.g_ch = 1,
// Blue not available.
.b_id = PWM_DEV_0_TODO,
.b_ch = 2,
.b_id = PWM_DEV_0,
.b_ch = PBDRV_LED_PWM_CHANNEL_INVALID,
// TODO: PWM not yet implemented, so these values not used.
.scale_factor = 35,
},
{
.color = &pbdrv_led_pwm_color,
.id = LED_DEV_2_STATUS_RIGHT,
.r_id = PWM_DEV_1_TODO,
.r_ch = 0,
.g_id = PWM_DEV_1_TODO,
.g_ch = 1,
.r_id = PWM_DEV_0,
.r_ch = 2,
.g_id = PWM_DEV_0,
.g_ch = 3,
// Blue not available.
.b_id = PWM_DEV_1_TODO,
.b_ch = 2,
.b_id = PWM_DEV_0,
.b_ch = PBDRV_LED_PWM_CHANNEL_INVALID,
// TODO: PWM not yet implemented, so these values not used.
.scale_factor = 35,
},
};

const pbdrv_pwm_tiam1808_platform_data_t
pbdrv_pwm_tiam1808_platform_data[PBDRV_CONFIG_PWM_TIAM1808_NUM_DEV] = {
{
.id = PWM_DEV_0_TODO,
.gpio_red = PBDRV_GPIO_EV3_PIN(13, 11, 8, 6, 13),
.gpio_green = PBDRV_GPIO_EV3_PIN(14, 3, 0, 6, 7),
},
{
.id = PWM_DEV_1_TODO,
.gpio_red = PBDRV_GPIO_EV3_PIN(13, 15, 12, 6, 12),
.gpio_green = PBDRV_GPIO_EV3_PIN(13, 7, 4, 6, 14),
const pbdrv_pwm_tiam1808_platform_data_t pbdrv_pwm_tiam1808_platform_data =
{
.id = PWM_DEV_0,
.gpios = {
PBDRV_GPIO_EV3_PIN(13, 11, 8, 6, 13),
PBDRV_GPIO_EV3_PIN(14, 3, 0, 6, 7),
PBDRV_GPIO_EV3_PIN(13, 15, 12, 6, 12),
PBDRV_GPIO_EV3_PIN(13, 7, 4, 6, 14),
},
};

Expand Down
17 changes: 16 additions & 1 deletion lib/pbio/platform/ev3/platform.ld
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ ENTRY(Entry)

MEMORY
{
SRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 128K
SRAM_PRU0 (rw) : ORIGIN = 0x80000000, LENGTH = 64K
SRAM_PRU1 (rw) : ORIGIN = 0x80010000, LENGTH = 64K
DDR_unused (rwx) : ORIGIN = 0xC0000000, LENGTH = 0x8000
DDR (rwx) : ORIGIN = 0xC0008000, LENGTH = (64M - 0x8000)
ARM_LRAM (rwx) : ORIGIN = 0xFFFF0000, LENGTH = 8K
Expand Down Expand Up @@ -38,6 +39,10 @@ SECTIONS
KEEP(*(.pru0));
. = ALIGN(4);
_pru0_end = .;
_pru1_start = .;
KEEP(*(.pru1));
. = ALIGN(4);
_pru1_end = .;
} >DDR

.data :
Expand Down Expand Up @@ -79,4 +84,14 @@ SECTIONS
. = . + _minimal_stack_size; /* will cause linker error if there is not enough space for stack. */
. = ALIGN(4);
} > DDR

/* Shared on-chip SRAM */
.shared0 (NOLOAD) :
{
*(.shared0)
} > SRAM_PRU0
.shared1 (NOLOAD) :
{
*(.shared1)
} > SRAM_PRU1
}
47 changes: 47 additions & 0 deletions lib/tiam1808/drivers/pruss.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,53 @@ void PRUSSDRVIntcSetHmr(unsigned short channel,
| (((host) & 0xF) << (((channel) & 0x3) << 3));
}

/**
* \brief Set PRU constant table entries
*
* \param pruNum PRU instance number[0 or 1].
* \param ctable_idx Index into constants table
* \param value Value to set
*
* \return 0 in case of success, -1 otherwise.
*/
int PRUSSDRVPruSetCTable(unsigned int pruNum,
unsigned int ctable_idx,
unsigned int value)
{
unsigned int regAddr;

if(pruNum == 0)
regAddr = PRU0CONTROL_PHYS_BASE;
else if(pruNum == 1)
regAddr = PRU1CONTROL_PHYS_BASE;
else
return -1;

switch (ctable_idx) {
case 24:
HWREG(regAddr + PRU_CONTABBLKIDX0) = (HWREG(regAddr + PRU_CONTABBLKIDX0) & ~0xf) | (value & 0xf);
break;
case 25:
HWREG(regAddr + PRU_CONTABBLKIDX0) = (HWREG(regAddr + PRU_CONTABBLKIDX0) & ~0xf0000) | ((value & 0xf) << 16);
break;
case 28:
HWREG(regAddr + PRU_CONTABPROPTR0) = (HWREG(regAddr + PRU_CONTABPROPTR0) & ~0xffff) | (value & 0xffff);
break;
case 29:
HWREG(regAddr + PRU_CONTABPROPTR0) = (HWREG(regAddr + PRU_CONTABPROPTR0) & ~0xffff0000) | ((value & 0xffff) << 16);
break;
case 30:
HWREG(regAddr + PRU_CONTABPROPTR1) = (HWREG(regAddr + PRU_CONTABPROPTR1) & ~0xffff) | (value & 0xffff);
break;
case 31:
HWREG(regAddr + PRU_CONTABPROPTR1) = (HWREG(regAddr + PRU_CONTABPROPTR1) & ~0xffff0000) | ((value & 0xffff) << 16);
break;
default:
return -1;
}
return 0;
}

void ICSS_Init(void)
{
/* ICSS PRCM Enable */
Expand Down
11 changes: 11 additions & 0 deletions lib/tiam1808/tiam1808/pruss.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ extern "C" {
#define PRU1IRAM_PHYS_BASE 0x01C3C000
#endif

/*
* PRUSS control and status registers offsets
*/
#define PRU_CONTABBLKIDX0 0x20
#define PRU_CONTABPROPTR0 0x28
#define PRU_CONTABPROPTR1 0x2C

#define PRU_EVTOUT_0 0
#define PRU_EVTOUT_1 1
#define PRU_EVTOUT_2 2
Expand Down Expand Up @@ -258,6 +265,10 @@ void PRUSSDRVIntcSetCmr(unsigned short sysevt,
void PRUSSDRVIntcSetHmr(unsigned short channel,
unsigned short host);

int PRUSSDRVPruSetCTable(unsigned int pruNum,
unsigned int ctable_idx,
unsigned int value);

void ICSS_Init(void);

// #ifdef AM33XX
Expand Down