Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
65 changes: 31 additions & 34 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,55 +86,53 @@ 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.
.r_factor = 1000,
.g_factor = 170,
.b_factor = 200,
.r_brightness = 174,
.g_brightness = 1590,
.b_brightness = 327,
// The red LED is much stronger than the green one, so leave green at 1000
// and adjust red until yellow looks good.
.r_factor = 150,
.g_factor = 1000,
.b_factor = 0,
// 1250 allows max brightness for an 8-bit PWM size (with scale_factor = 1).
// Increase to limit max brightness. Going lower will cause overflow.
.r_brightness = 1250,
.g_brightness = 1250,
.b_brightness = 0,
};

const pbdrv_led_pwm_platform_data_t pbdrv_led_pwm_platform_data[PBDRV_CONFIG_LED_PWM_NUM_DEV] = {
{
.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,
// TODO: PWM not yet implemented, so these values not used.
.scale_factor = 35,
.b_id = PWM_DEV_0,
.b_ch = PBDRV_LED_PWM_CHANNEL_INVALID,
.scale_factor = 1,
},
{
.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,
// TODO: PWM not yet implemented, so these values not used.
.scale_factor = 35,
.b_id = PWM_DEV_0,
.b_ch = PBDRV_LED_PWM_CHANNEL_INVALID,
.scale_factor = 1,
},
};

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