From 36562fe4115efa0f75432549a598c50e0b8f378d Mon Sep 17 00:00:00 2001 From: Heinz Junkes Date: Wed, 3 Sep 2025 15:46:59 +0200 Subject: [PATCH] add gpio handling and adc section to BBB --- bsps/arm/beagle/adc/bbb-adc.c | 154 ++++++++ bsps/arm/beagle/gpio/bbb-gpio.c | 330 ++++++++++++++---- bsps/arm/beagle/include/bsp/bbb-adc.h | 33 ++ bsps/arm/beagle/include/bsp/beagleboneblack.h | 66 +++- bsps/arm/include/libcpu/am335x.h | 40 +++ bsps/include/bsp/gpio.h | 19 + bsps/shared/dev/gpio/gpio-support.c | 7 +- spec/build/bsps/arm/beagle/obj.yml | 2 + 8 files changed, 570 insertions(+), 81 deletions(-) create mode 100644 bsps/arm/beagle/adc/bbb-adc.c create mode 100644 bsps/arm/beagle/include/bsp/bbb-adc.h diff --git a/bsps/arm/beagle/adc/bbb-adc.c b/bsps/arm/beagle/adc/bbb-adc.c new file mode 100644 index 0000000000..74449baa7b --- /dev/null +++ b/bsps/arm/beagle/adc/bbb-adc.c @@ -0,0 +1,154 @@ +/** + * @file + * + * @ingroup arm_beagle + * + * @brief ADC definitions. + */ + +/** + * Copyright (c) 2015 Ketul Shah + + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_adc_bsp_lock, "rtems_adc_bsp_lock" ); + +/* Waits a number of CPU cycles. */ +static void arm_delay(uint8_t cycles) +{ + uint8_t i; + + for ( i = 0; i < cycles; ++i ) { + asm volatile("nop"); + } +} + +static void inline reg_update(uint32_t reg, uint32_t val) +{ + mmio_write(reg, val); +} + +static void inline reg_update_or(uint32_t reg, uint32_t val) +{ + uint32_t reg_val=mmio_read(reg); + reg_val |= val; + mmio_write(reg, reg_val); +} + +/* Configure STEPCONFIG register with average of 16 */ +static void inline stepc_update_16(uint32_t reg, uint32_t val) +{ + mmio_write(reg,(val | AM335X_ADC_AVG16)); +} + +/* Configure STEPDELAY register */ +static void inline stepd_update(uint32_t reg) +{ + mmio_write(reg,(0x0F)<<24); +} + +static uint32_t inline get_val(uint32_t reg, uint32_t val) +{ + return (mmio_read(reg) & val); +} + +void rtems_adc_init(void) +{ + + rtems_interrupt_lock_context lock_context; + + rtems_interrupt_lock_acquire(&rtems_adc_bsp_lock, &lock_context); + /* Enable the CM_WKUP_ADC_CLKCTRL with CM_WKUP_MODUELEMODE_ENABLE */ + reg_update_or(AM335X_CM_WKUP_ADC_CLKCTRL, AM335X_CM_WKUP_MODULEMODE_ENABLE); /* 0x02 */ + + while(!( get_val(AM335X_CM_WKUP_ADC_CLKCTRL,AM335X_CM_WKUP_MODULEMODE_ENABLE))){ + /* Here waiting period for intialization of adc clock module */ + } + + /* Make sure STEPCONFIG write protect is off */ + reg_update_or(AM335X_ADC_CTRL, AM335X_ADC_STEPCONFIG_WRITE_PROTECT_OFF); + + /* ADC_STEPCONFIG for each AIN pin */ + stepc_update_16(AM335X_ADC_STEPCONFIG1,0x00<<19); + stepd_update(AM335X_ADC_STEPDELAY1); + stepc_update_16(AM335X_ADC_STEPCONFIG2,0x01<<19); + stepd_update(AM335X_ADC_STEPDELAY2); + stepc_update_16(AM335X_ADC_STEPCONFIG3,0x02<<19); + stepd_update(AM335X_ADC_STEPDELAY3); + stepc_update_16(AM335X_ADC_STEPCONFIG4,0x03<<19); + stepd_update(AM335X_ADC_STEPDELAY4); + stepc_update_16(AM335X_ADC_STEPCONFIG5,0x04<<19); + stepd_update(AM335X_ADC_STEPDELAY5); + stepc_update_16(AM335X_ADC_STEPCONFIG6,0x05<<19); + stepd_update(AM335X_ADC_STEPDELAY6); + stepc_update_16(AM335X_ADC_STEPCONFIG7,0x06<<19); + stepd_update(AM335X_ADC_STEPDELAY7); + stepc_update_16(AM335X_ADC_STEPCONFIG8,0x07<<19); + stepd_update(AM335X_ADC_STEPDELAY8); + + /* ADC_CTRL is enabled + store the Step ID-number with the captured ADC data in the Fifo */ + reg_update_or(AM335X_ADC_CTRL,0x03); + + rtems_interrupt_lock_release(&rtems_gpio_bsp_lock, &lock_context); +} + +int rtems_adc_read(unsigned int pin_number) +{ + rtems_interrupt_lock_context lock_context; + + /* The clock module is not enabled */ + if(get_val(AM335X_CM_WKUP_ADC_CLKCTRL,AM335X_CM_WKUP_IDLEST_DISABLED)) + rtems_adc_init(); + + rtems_interrupt_lock_acquire(&rtems_adc_bsp_lock, &lock_context); + /* Enable the step sequencer for the given pin */ + reg_update(AM335X_ADC_STEPENABLE,(0x01<<(pin_number+1))); + + rtems_interrupt_lock_release(&rtems_gpio_bsp_lock, &lock_context); + /* Return the value of data register FIFO0 */ + return (get_val(AM335X_ADC_FIFO0DATA,AM335X_ADC_FIFO_MASK)); +} + +unsigned int rtems_adc_read_multiple(unsigned int len, unsigned int wait, unsigned int mask, unsigned int data[]) +{ + rtems_interrupt_lock_context lock_context; + + /* The clock module is not enabled */ + if(get_val(AM335X_CM_WKUP_ADC_CLKCTRL,AM335X_CM_WKUP_IDLEST_DISABLED)) + rtems_adc_init(); + + rtems_interrupt_lock_acquire(&rtems_adc_bsp_lock, &lock_context); + /* Enable the step sequencer for the given pins/mask */ + reg_update(AM335X_ADC_STEPENABLE, mask); + int timeOut = len * wait; + int fifo; + do { + fifo = get_val(AM335X_ADC_FIFO0COUNT, 0x7F); + timeOut-=1; + arm_delay(5); + } while( (len != fifo) && timeOut); + + unsigned int d; + for(unsigned int i = 0; i < fifo; i++) { + d = get_val(AM335X_ADC_FIFO0DATA, 0x000F0FFF); + if (d>>16 < len) // chid in head of data + data[d>>16] = d & 0xfff; + } + rtems_interrupt_lock_release(&rtems_gpio_bsp_lock, &lock_context); + return (fifo); +} + diff --git a/bsps/arm/beagle/gpio/bbb-gpio.c b/bsps/arm/beagle/gpio/bbb-gpio.c index bd081fae5a..8e8adce660 100644 --- a/bsps/arm/beagle/gpio/bbb-gpio.c +++ b/bsps/arm/beagle/gpio/bbb-gpio.c @@ -28,18 +28,23 @@ #include #include +#include /* Currently these definitions are for BeagleBone Black board only + * with modifications from ketul93 + * (https://gist.github.com/ketul93/d717555951174a74c8b4) * Later on Beagle-xM board support can be added in this code. * After support gets added if condition should be removed + * HPJ: set almost all I/O to Mode7 to use all for own application + * This is not yet well structured and good ideas are still needed */ #if IS_AM335X -static const uint32_t gpio_bank_addrs[] = +static const uint32_t gpio_bank_addrs[] = { AM335X_GPIO0_BASE, - AM335X_GPIO1_BASE, - AM335X_GPIO2_BASE, - AM335X_GPIO3_BASE }; + AM335X_GPIO1_BASE, + AM335X_GPIO2_BASE, + AM335X_GPIO3_BASE }; static const rtems_vector_number gpio_bank_vector[] = { AM335X_INT_GPIOINT0A, @@ -47,10 +52,161 @@ static const rtems_vector_number gpio_bank_vector[] = AM335X_INT_GPIOINT2A, AM335X_INT_GPIOINT3A }; +/* Macro for the gpio pin not having control module offset mapping */ +#define CONF_NOT_DEFINED 0x00 + +/* Mapping of gpio pin number to the Control module mapped register offset */ +// FHI: allmost all, but mmc, used in MUXMODE7 from our applications +// Macro? +static const uint32_t gpio_pad_conf [GPIO_BANK_COUNT][BSP_GPIO_PINS_PER_BANK] = +{ + /* GPIO Module 0 */ + { CONF_NOT_DEFINED, /* GPIO0[0] */ + CONF_NOT_DEFINED, /* GPIO0[1] */ + AM335X_CONF_SPI0_SCLK, /* GPIO0[2] */ + AM335X_CONF_SPI0_D0, /* GPIO0[3] */ + AM335X_CONF_SPI0_D1, /* GPIO0[4] */ + AM335X_CONF_SPI0_CS0, /* GPIO0[5] */ + CONF_NOT_DEFINED, /* GPIO0[6] */ + AM335X_CONF_ECAP0_IN_PWM0_OUT,/* GPIO0[7] */ + AM335X_CONF_LCD_DATA12, /* GPIO0[8] */ + AM335X_CONF_LCD_DATA13, /* GPIO0[9] */ + AM335X_CONF_LCD_DATA14, /* GPIO0[10] */ + AM335X_CONF_LCD_DATA15, /* GPIO0[11] */ + AM335X_CONF_UART1_CTSN, /* GPIO0[12] */ + AM335X_CONF_UART1_RTSN, /* GPIO0[13] */ + AM335X_CONF_UART1_RXD, /* GPIO0[14] */ + AM335X_CONF_UART1_TXD, /* GPIO0[15] */ + CONF_NOT_DEFINED, /* GPIO0[16] */ + CONF_NOT_DEFINED, /* GPIO0[17] */ + CONF_NOT_DEFINED, /* GPIO0[18] */ + CONF_NOT_DEFINED, /* GPIO0[19] */ + AM335X_CONF_XDMA_EVENT_INTR1, /* GPIO0[20] */ + CONF_NOT_DEFINED, /* GPIO0[21] */ + AM335X_CONF_GPMC_AD8, /* GPIO0[22] */ + AM335X_CONF_GPMC_AD9, /* GPIO0[23] */ + CONF_NOT_DEFINED, /* GPIO0[24] */ + CONF_NOT_DEFINED, /* GPIO0[25] */ + AM335X_CONF_GPMC_AD10, /* GPIO0[26] */ + AM335X_CONF_GPMC_AD11, /* GPIO0[27] */ + CONF_NOT_DEFINED, /* GPIO0[28] */ + CONF_NOT_DEFINED, /* GPIO0[29] */ + AM335X_CONF_GPMC_WAIT0, /* GPIO0[30] */ + AM335X_CONF_GPMC_WPN /* GPIO0[31] */ }, + + /* GPIO Module 1 */ + { AM335X_CONF_GPMC_AD0, /* GPIO1[0] */ + AM335X_CONF_GPMC_AD1, /* GPIO1[1] */ + AM335X_CONF_GPMC_AD2, /* GPIO1[2] */ + AM335X_CONF_GPMC_AD3, /* GPIO1[3] */ + AM335X_CONF_GPMC_AD4, /* GPIO1[4] */ + AM335X_CONF_GPMC_AD5, /* GPIO1[5] */ + AM335X_CONF_GPMC_AD6, /* GPIO1[6] */ + AM335X_CONF_GPMC_AD7, /* GPIO1[7] */ + CONF_NOT_DEFINED, /* GPIO1[8] */ + CONF_NOT_DEFINED, /* GPIO1[9] */ + CONF_NOT_DEFINED, /* GPIO1[10] */ + CONF_NOT_DEFINED, /* GPIO1[11] */ + AM335X_CONF_GPMC_AD12, /* GPIO1[12] */ + AM335X_CONF_GPMC_AD13, /* GPIO1[13] */ + AM335X_CONF_GPMC_AD14, /* GPIO1[14] */ + AM335X_CONF_GPMC_AD15, /* GPIO1[15] */ + AM335X_CONF_GPMC_A0, /* GPIO1[16] */ + AM335X_CONF_GPMC_A1, /* GPIO1[17] */ + AM335X_CONF_GPMC_A2, /* GPIO1[18] */ + AM335X_CONF_GPMC_A3, /* GPIO1[19] */ + CONF_NOT_DEFINED, /* GPIO1[20] */ + AM335X_CONF_GPMC_A5, /* GPIO1[21] */ + AM335X_CONF_GPMC_A6, /* GPIO1[22] */ + AM335X_CONF_GPMC_A7, /* GPIO1[23] */ + AM335X_CONF_GPMC_A8, /* GPIO1[24] */ + CONF_NOT_DEFINED, /* GPIO1[25] */ + CONF_NOT_DEFINED, /* GPIO1[26] */ + CONF_NOT_DEFINED, /* GPIO1[27] */ + AM335X_CONF_GPMC_BEN1, /* GPIO1[28] */ + AM335X_CONF_GPMC_CSN0, /* GPIO1[29] */ + AM335X_CONF_GPMC_CSN1, /* GPIO1[30] */ + AM335X_CONF_GPMC_CSN2 /* GPIO1[31] */ }, + + /* GPIO Module 2 */ + { CONF_NOT_DEFINED, /* GPIO2[0] */ + AM335X_CONF_GPMC_CLK, /* GPIO2[1] */ + AM335X_CONF_GPMC_ADVN_ALE, /* GPIO2[2] */ + AM335X_CONF_GPMC_OEN_REN, /* GPIO2[3] */ + AM335X_CONF_GPMC_WEN, /* GPIO2[4] */ + AM335X_CONF_GPMC_BEN0_CLE, /* GPIO2[5] */ + AM335X_CONF_LCD_DATA0, /* GPIO2[6] */ + AM335X_CONF_LCD_DATA1, /* GPIO2[7] */ + AM335X_CONF_LCD_DATA2, /* GPIO2[8] */ + AM335X_CONF_LCD_DATA3, /* GPIO2[9] */ + AM335X_CONF_LCD_DATA4, /* GPIO2[10] */ + AM335X_CONF_LCD_DATA5, /* GPIO2[11] */ + AM335X_CONF_LCD_DATA6, /* GPIO2[12] */ + AM335X_CONF_LCD_DATA7, /* GPIO2[13] */ + AM335X_CONF_LCD_DATA8, /* GPIO2[14] */ + AM335X_CONF_LCD_DATA9, /* GPIO2[15] */ + AM335X_CONF_LCD_DATA10, /* GPIO2[16] */ + AM335X_CONF_LCD_DATA11, /* GPIO2[17] */ + CONF_NOT_DEFINED, /* GPIO2[18] */ + CONF_NOT_DEFINED, /* GPIO2[19] */ + CONF_NOT_DEFINED, /* GPIO2[20] */ + CONF_NOT_DEFINED, /* GPIO2[21] */ + AM335X_CONF_LCD_VSYNC, /* GPIO2[22] */ + AM335X_CONF_LCD_HSYNC, /* GPIO2[23] */ + AM335X_CONF_LCD_PCLK, /* GPIO2[24] */ + AM335X_CONF_LCD_AC_BIAS_EN /* GPIO2[25] */ }, + + /* GPIO Module 3 */ + { CONF_NOT_DEFINED, /* GPIO3[0] */ + CONF_NOT_DEFINED, /* GPIO3[1] */ + CONF_NOT_DEFINED, /* GPIO3[2] */ + CONF_NOT_DEFINED, /* GPIO3[3] */ + CONF_NOT_DEFINED, /* GPIO3[4] */ + CONF_NOT_DEFINED, /* GPIO3[5] */ + CONF_NOT_DEFINED, /* GPIO3[6] */ + CONF_NOT_DEFINED, /* GPIO3[7] */ + CONF_NOT_DEFINED, /* GPIO3[8] */ + CONF_NOT_DEFINED, /* GPIO3[9] */ + CONF_NOT_DEFINED, /* GPIO3[10] */ + CONF_NOT_DEFINED, /* GPIO3[11] */ + CONF_NOT_DEFINED, /* GPIO3[12] */ + CONF_NOT_DEFINED, /* GPIO3[13] */ + AM335X_CONF_MCASP0_ACLKX, /* GPIO3[14] */ + AM335X_CONF_MCASP0_FSX, /* GPIO3[15] */ + AM335X_CONF_MCASP0_AXR0, /* GPIO3[16] */ + AM335X_CONF_MCASP0_AHCLKR, /* GPIO3[17] */ + CONF_NOT_DEFINED, /* GPIO3[18] */ + AM335X_CONF_MCASP0_FSR, /* GPIO3[19] */ + AM335X_CONF_MCASP0_AXR1, /* GPIO3[20] */ + AM335X_CONF_MCASP0_AHCLKX /* GPIO3[21] */ } +}; + +/* Get the address of Base Register + Offset for pad config */ +uint32_t static inline bbb_conf_reg(uint32_t bank, uint32_t pin) +{ + /* Asserts if invalid pin is supplied */ + assert(gpio_pad_conf[bank][pin] != CONF_NOT_DEFINED); + + /* + How to Deal with MUXMODE 7 ? + */ + return (AM335X_PADCONF_BASE + gpio_pad_conf[bank][pin]); +} + /* Get the value of Base Register + Offset */ uint32_t static inline bbb_reg(uint32_t bank, uint32_t reg) { - return (gpio_bank_addrs[bank] + reg); + return REG(gpio_bank_addrs[bank] + reg); +} + +/* Waits a number of CPU cycles. */ +static void arm_delay(uint8_t cycles) +{ + uint8_t i; + + for ( i = 0; i < cycles; ++i ) { + asm volatile("nop"); + } } static rtems_status_code bbb_select_pin_function( @@ -60,50 +216,47 @@ static rtems_status_code bbb_select_pin_function( ) { if ( type == BBB_DIGITAL_IN ) { - mmio_set(bbb_reg(bank, AM335X_GPIO_OE), BIT(pin)); - } else { - mmio_clear(bbb_reg(bank, AM335X_GPIO_OE), BIT(pin)); + mmio_set((gpio_bank_addrs[bank] + AM335X_GPIO_OE), BIT(pin)); + } + else { + mmio_clear((gpio_bank_addrs[bank] + AM335X_GPIO_OE), BIT(pin)); } - return RTEMS_SUCCESSFUL; + } rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask) { - mmio_set(bbb_reg(bank, AM335X_GPIO_SETDATAOUT), bitmask); - + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_SETDATAOUT), bitmask); return RTEMS_SUCCESSFUL; } rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask) { - mmio_set(bbb_reg(bank, AM335X_GPIO_CLEARDATAOUT), bitmask); - + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_CLEARDATAOUT), bitmask); return RTEMS_SUCCESSFUL; } uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask) { - return (bbb_reg(bank, AM335X_GPIO_DATAIN) & bitmask); + return (mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_DATAIN) & bitmask); } rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin) { - mmio_set(bbb_reg(bank, AM335X_GPIO_SETDATAOUT), BIT(pin)); - + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_SETDATAOUT), BIT(pin)); return RTEMS_SUCCESSFUL; } rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin) { - mmio_set(bbb_reg(bank, AM335X_GPIO_CLEARDATAOUT), BIT(pin)); - + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_CLEARDATAOUT), BIT(pin)); return RTEMS_SUCCESSFUL; } uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin) { - return (mmio_read(bbb_reg(bank, AM335X_GPIO_DATAIN)) & BIT(pin)); + return (mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_DATAIN) & BIT(pin) ? 1:0); } rtems_status_code rtems_gpio_bsp_select_input( @@ -131,13 +284,42 @@ rtems_status_code rtems_gpio_bsp_select_specific_io( return RTEMS_NOT_DEFINED; } +rtems_status_code rtems_bsp_select_specific_io( + uint32_t bank, + uint32_t pin, + uint32_t function, + void *pin_data +) { + return RTEMS_NOT_DEFINED; +} + rtems_status_code rtems_gpio_bsp_set_resistor_mode( uint32_t bank, uint32_t pin, rtems_gpio_pull_mode mode ) { - /* TODO: Add support for setting up resistor mode */ - return RTEMS_NOT_DEFINED; + + uint32_t register_content; + + register_content = BBB_MUXMODE(7); + + /* Set control signal. */ + switch ( mode ) { + case PULL_UP: + register_content = register_content | BBB_PU_EN | BBB_RXACTIVE; // assume input + break; + case PULL_DOWN: + break; + case NO_PULL_RESISTOR: + register_content = register_content | BBB_PUDDIS; + break; + default: + return RTEMS_UNSATISFIED; + } + + mmio_write(bbb_conf_reg(bank,pin), register_content); + + return RTEMS_SUCCESSFUL; } rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank) @@ -157,12 +339,11 @@ uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector) } /* Retrieve the interrupt event status. */ - event_status = mmio_read(bbb_reg(bank_nr, AM335X_GPIO_IRQSTATUS_0)); + event_status = bbb_reg(bank_nr, AM335X_GPIO_IRQSTATUS_0); /* Clear the interrupt line. */ - mmio_write( - (bbb_reg(bank_nr, AM335X_GPIO_IRQSTATUS_0)), event_status); - + mmio_write(gpio_bank_addrs[bank_nr] + AM335X_GPIO_IRQSTATUS_0, event_status); + return event_status; } @@ -171,135 +352,135 @@ rtems_status_code rtems_gpio_bsp_enable_interrupt( uint32_t pin, rtems_gpio_interrupt interrupt ) { - - /* Enable IRQ generation for the specific pin */ - mmio_set(bbb_reg(bank, AM335X_GPIO_IRQSTATUS_SET_0), BIT(pin)); - + return rtems_bsp_enable_interrupt(bank, pin, interrupt); +} + +rtems_status_code rtems_bsp_enable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +) { switch ( interrupt ) { case FALLING_EDGE: /* Enables asynchronous falling edge detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_FALLINGDETECT, BIT(pin)); break; case RISING_EDGE: /* Enables asynchronous rising edge detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_RISINGDETECT, BIT(pin)); break; case BOTH_EDGES: /* Enables asynchronous falling edge detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin)); - + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_FALLINGDETECT, BIT(pin)); /* Enables asynchronous rising edge detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_RISINGDETECT, BIT(pin)); break; case LOW_LEVEL: /* Enables pin low level detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT0, BIT(pin)); break; case HIGH_LEVEL: - /* Enables pin high level detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin)); + /* Enables pin high level detection. */ + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT1, BIT(pin)); break; case BOTH_LEVELS: /* Enables pin low level detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT0, BIT(pin)); /* Enables pin high level detection. */ - mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin)); + mmio_set(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT1, BIT(pin)); break; case NONE: default: return RTEMS_UNSATISFIED; } +/* + printf(" Register for interrupt detection are : \n"); + printf("\t FALLING : 0x%x\n", mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_FALLINGDETECT)); + printf("\t RISING : 0x%x\n", mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_RISINGDETECT)); + printf("\t Low Level : 0x%x\n", mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT0)); + printf("\t High Level : 0x%x\n", mmio_read(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT1)); +*/ + + mmio_write(gpio_bank_addrs[bank] + AM335X_GPIO_IRQSTATUS_SET_0, BIT(pin)); + mmio_write(gpio_bank_addrs[bank] + AM335X_GPIO_IRQSTATUS_SET_1, BIT(pin)); /* The detection starts after 5 clock cycles as per AM335X TRM * This period is required to clean the synchronization edge/ * level detection pipeline */ - asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); - asm volatile("nop"); asm volatile("nop"); - + arm_delay(5); return RTEMS_SUCCESSFUL; } + rtems_status_code rtems_gpio_bsp_disable_interrupt( uint32_t bank, uint32_t pin, rtems_gpio_interrupt interrupt ) { - /* Clear IRQ generation for the specific pin */ - mmio_write(bbb_reg(bank, AM335X_GPIO_IRQSTATUS_CLR_0), BIT(pin)); + return rtems_bsp_disable_interrupt(bank, pin, interrupt); +} +rtems_status_code rtems_bsp_disable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +) { switch ( interrupt ) { case FALLING_EDGE: /* Disables asynchronous falling edge detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_FALLINGDETECT, BIT(pin)); break; case RISING_EDGE: /* Disables asynchronous rising edge detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_RISINGDETECT, BIT(pin)); break; case BOTH_EDGES: /* Disables asynchronous falling edge detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_FALLINGDETECT, BIT(pin)); /* Disables asynchronous rising edge detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_RISINGDETECT, BIT(pin)); break; case LOW_LEVEL: /* Disables pin low level detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT0, BIT(pin)); break; case HIGH_LEVEL: /* Disables pin high level detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT1, BIT(pin)); break; case BOTH_LEVELS: /* Disables pin low level detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT0, BIT(pin)); /* Disables pin high level detection. */ - mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin)); + mmio_clear(gpio_bank_addrs[bank] + AM335X_GPIO_LEVELDETECT1, BIT(pin)); break; case NONE: default: return RTEMS_UNSATISFIED; } - /* The detection starts after 5 clock cycles as per AM335X TRM - * This period is required to clean the synchronization edge/ - * level detection pipeline - */ - asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); - asm volatile("nop"); asm volatile("nop"); + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_IRQSTATUS_CLR_0), BIT(pin)); + mmio_write((gpio_bank_addrs[bank] + AM335X_GPIO_IRQSTATUS_CLR_1), BIT(pin)); return RTEMS_SUCCESSFUL; } +/* I have unfortunately lost the overview a little .... +*/ rtems_status_code rtems_gpio_bsp_multi_select( rtems_gpio_multiple_pin_select *pins, uint32_t pin_count, uint32_t select_bank ) { - uint32_t register_address; - uint32_t select_register; uint8_t i; - register_address = gpio_bank_addrs[select_bank] + AM335X_GPIO_OE; - - select_register = REG(register_address); - for ( i = 0; i < pin_count; ++i ) { - if ( pins[i].function == DIGITAL_INPUT ) { - select_register |= BIT(pins[i].pin_number); - } else if ( pins[i].function == DIGITAL_OUTPUT ) { - select_register &= ~BIT(pins[i].pin_number); - } else { /* BSP_SPECIFIC function. */ - return RTEMS_NOT_DEFINED; - } + bbb_select_pin_function((pins[i].pin_number)/32, (pins[i].pin_number)%32, pins[i].function); } - - REG(register_address) = select_register; - return RTEMS_SUCCESSFUL; } @@ -311,7 +492,6 @@ rtems_status_code rtems_gpio_bsp_specific_group_operation( ) { return RTEMS_NOT_DEFINED; } - #endif /* IS_AM335X */ /* For support of BeagleboardxM */ diff --git a/bsps/arm/beagle/include/bsp/bbb-adc.h b/bsps/arm/beagle/include/bsp/bbb-adc.h new file mode 100644 index 0000000000..22eb854174 --- /dev/null +++ b/bsps/arm/beagle/include/bsp/bbb-adc.h @@ -0,0 +1,33 @@ +/** + * @file + * + * @ingroup arm_beagle + * + * @brief BeagleBone Black BSP definitions. + */ + +/** + * Copyright (c) 2015 Ketul Shah + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef LIBBSP_ARM_BEAGLE_ADC_H +#define LIBBSP_ARM_BEAGLE_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief ADC intialization. + */ +extern void rtems_adc_init(void); +/** + * @brief Reads the ADC value for input from pin. + */ +extern int rtems_adc_read(unsigned int); +extern unsigned int rtems_adc_read_multiple(unsigned int len, unsigned int wait, unsigned int mask, unsigned int data[]); +#endif diff --git a/bsps/arm/beagle/include/bsp/beagleboneblack.h b/bsps/arm/beagle/include/bsp/beagleboneblack.h index c62f4aa92d..cf3d85c6e8 100644 --- a/bsps/arm/beagle/include/bsp/beagleboneblack.h +++ b/bsps/arm/beagle/include/bsp/beagleboneblack.h @@ -37,6 +37,10 @@ #define BBB_LED_USR3 56 /* USR LED3 */ /* Header P8 of BeagleBone Black */ +#define BBB_P8_3 38 /* GPIO1_6 */ +#define BBB_P8_4 39 /* GPIO1_7 */ +#define BBB_P8_5 34 /* GPIO1_2 */ +#define BBB_P8_6 35 /* GPIO1_3 */ #define BBB_P8_7 66 /* GPIO2_2 */ #define BBB_P8_8 67 /* GPIO2_3 */ #define BBB_P8_9 69 /* GPIO2_5 */ @@ -50,7 +54,33 @@ #define BBB_P8_17 27 /* GPIO0_27 */ #define BBB_P8_18 65 /* GPIO2_1 */ #define BBB_P8_19 22 /* GPIO0_22 */ +#define BBB_P8_20 63 /* GPIO1_31 */ +#define BBB_P8_21 62 /* GPIO1_30 */ +#define BBB_P8_22 37 /* GPIO1_5 */ +#define BBB_P8_23 36 /* GPIO1_4 */ +#define BBB_P8_24 33 /* GPIO1_1 */ +#define BBB_P8_25 32 /* GPIO1_0 */ #define BBB_P8_26 61 /* GPIO1_29 */ +#define BBB_P8_27 86 /* GPIO2_22 */ +#define BBB_P8_28 88 /* GPIO2_24 */ +#define BBB_P8_29 87 /* GPIO2_23 */ +#define BBB_P8_30 89 /* GPIO2_25 */ +#define BBB_P8_31 10 /* GPIO0_10 */ +#define BBB_P8_32 11 /* GPIO0_11 */ +#define BBB_P8_33 9 /* GPIO0_9 */ +#define BBB_P8_34 81 /* GPIO2_17 */ +#define BBB_P8_35 8 /* GPIO0_8 */ +#define BBB_P8_36 80 /* GPIO2_16 */ +#define BBB_P8_37 78 /* GPIO2_14 */ +#define BBB_P8_38 79 /* GPIO2_15 */ +#define BBB_P8_39 76 /* GPIO2_12 */ +#define BBB_P8_40 77 /* GPIO2_13 */ +#define BBB_P8_41 74 /* GPIO2_10 */ +#define BBB_P8_42 75 /* GPIO2_11 */ +#define BBB_P8_43 72 /* GPIO2_8 */ +#define BBB_P8_44 73 /* GPIO2_9 */ +#define BBB_P8_45 70 /* GPIO2_6 */ +#define BBB_P8_46 71 /* GPIO2_7 */ /* Header P9 of BeagleBone Black */ #define BBB_P9_11 30 /* GPIO0_30 */ @@ -61,12 +91,40 @@ #define BBB_P9_16 51 /* GPIO1_19 */ #define BBB_P9_17 5 /* GPIO0_5 */ #define BBB_P9_18 4 /* GPIO0_4 */ + +#define BBB_P9_19 13 /* GPIO0_13 */ +#define BBB_P9_20 12 /* GPIO0_12 */ +#define BBB_P9_21 3 /* GPIO0_3 */ +#define BBB_P9_22 2 /* GPIO0_2 */ + #define BBB_P9_23 49 /* GPIO1_17 */ #define BBB_P9_24 15 /* GPIO0_15 */ + +#define BBB_P9_25 117 /* GPIO3_21 */ + #define BBB_P9_26 14 /* GPIO1_14 */ -#define BBB_P9_27 115/* GPIO3_19 */ -#define BBB_P9_30 112/* GPIO3_16 */ -#define BBB_P9_41 20 /* GPIO0_20 */ +#define BBB_P9_27 115 /* GPIO3_19 */ + +#define BBB_P9_28 113 /* GPIO3_17 */ +#define BBB_P9_29 111 /* GPIO3_15 */ + +#define BBB_P9_30 112 /* GPIO3_16 */ + +#define BBB_P9_31 110 /* GPIO3_14 */ + +#define BBB_P9_41A 20 /* GPIO0_20 */ +#define BBB_P9_41B 116 /* GPIO3_20 */ #define BBB_P9_42 7 /* GPIO0_7 */ -#endif /* LIBBSP_ARM_BEAGLE_GPIO_H */ \ No newline at end of file +/* ADC pins on the BeagleBone Black */ +#define BBB_P9_33 4 /* AIN_4 */ +#define BBB_P9_34 7 /* AIN_7 */ +#define BBB_P9_35 6 /* AIN_6 */ +#define BBB_P9_36 5 /* AIN_5 */ +#define BBB_P9_37 2 /* AIN_2 */ +#define BBB_P9_38 3 /* AIN_3 */ +#define BBB_P9_39 0 /* AIN_0 */ +#define BBB_P9_40 1 /* AIN_1 */ + +#endif /* LIBBSP_ARM_BEAGLE_GPIO_H */ + diff --git a/bsps/arm/include/libcpu/am335x.h b/bsps/arm/include/libcpu/am335x.h index b69c822d62..3117218857 100644 --- a/bsps/arm/include/libcpu/am335x.h +++ b/bsps/arm/include/libcpu/am335x.h @@ -345,6 +345,46 @@ #define AM335X_GPIO_CLEARDATAOUT 0x190 #define AM335X_GPIO_SETDATAOUT 0x194 +/* ADC registers */ +#define AM335X_ADC (0x44E0D000) +#define AM335X_CM_WKUP (0x44E00400) +#define AM335X_CM_WKUP_ADC_CLKCTRL (AM335X_CM_WKUP+0xBC) +#define AM335X_CM_WKUP_MODULEMODE_ENABLE (0x02) +#define AM335X_CM_WKUP_IDLEST_DISABLED (0x03<<16) + +#define AM335X_ADC_CTRL (AM335X_ADC+0x40) +#define AM335X_ADC_STAT (AM335X_ADC+0x44) +#define AM335X_ADC_STEPENABLE (AM335X_ADC+0x54) +#define AM335X_ADC_STEPCONFIG_WRITE_PROTECT_OFF (0x01<<2) + +#define AM335X_ADC_STEPCONFIG1 (AM335X_ADC+0x64) +#define AM335X_ADC_STEPDELAY1 (AM335X_ADC+0x68) +#define AM335X_ADC_STEPCONFIG2 (AM335X_ADC+0x6C) +#define AM335X_ADC_STEPDELAY2 (AM335X_ADC+0x70) +#define AM335X_ADC_STEPCONFIG3 (AM335X_ADC+0x74) +#define AM335X_ADC_STEPDELAY3 (AM335X_ADC+0x78) +#define AM335X_ADC_STEPCONFIG4 (AM335X_ADC+0x7C) +#define AM335X_ADC_STEPDELAY4 (AM335X_ADC+0x80) +#define AM335X_ADC_STEPCONFIG5 (AM335X_ADC+0x84) +#define AM335X_ADC_STEPDELAY5 (AM335X_ADC+0x88) +#define AM335X_ADC_STEPCONFIG6 (AM335X_ADC+0x8C) +#define AM335X_ADC_STEPDELAY6 (AM335X_ADC+0x90) +#define AM335X_ADC_STEPCONFIG7 (AM335X_ADC+0x94) +#define AM335X_ADC_STEPDELAY7 (AM335X_ADC+0x98) +#define AM335X_ADC_STEPCONFIG8 (AM335X_ADC+0x9C) +#define AM335X_ADC_STEPDELAY8 (AM335X_ADC+0xA0) + +#define AM335X_ADC_AVG0 (0x000) +#define AM335X_ADC_AVG2 (0x001) +#define AM335X_ADC_AVG4 (0x010) +#define AM335X_ADC_AVG8 (0x011) +#define AM335X_ADC_AVG16 (0x100) + +#define AM335X_ADC_FIFO0COUNT (AM335X_ADC+0xE4) +#define AM335X_ADC_FIFO0DATA (AM335X_ADC+0x100) +#define AM335X_ADC_FIFO_MASK (0xFFF) + + /* AM335X Pad Configuration Register Base */ #define AM335X_PADCONF_BASE 0x44E10000 diff --git a/bsps/include/bsp/gpio.h b/bsps/include/bsp/gpio.h index 23eb729169..5d7c5780b3 100644 --- a/bsps/include/bsp/gpio.h +++ b/bsps/include/bsp/gpio.h @@ -335,6 +335,13 @@ extern rtems_status_code rtems_gpio_group_bsp_specific_operation( void *arg ); +extern rtems_status_code rtems_bsp_select_specific_io( + uint32_t bank, + uint32_t pin, + uint32_t function, + void *pin_data +); + /** * @brief Requests a GPIO pin configuration. * @@ -929,6 +936,12 @@ extern rtems_status_code rtems_gpio_bsp_enable_interrupt( rtems_gpio_interrupt interrupt ); +extern rtems_status_code rtems_bsp_enable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +); + /** * @brief Stops interrupts from being generated on a given GPIO pin. * This must be implemented by each BSP. @@ -946,6 +959,12 @@ extern rtems_status_code rtems_gpio_bsp_disable_interrupt( rtems_gpio_interrupt interrupt ); +extern rtems_status_code rtems_bsp_disable_interrupt( + uint32_t bank, + uint32_t pin, + rtems_gpio_interrupt interrupt +); + /** @} */ #ifdef __cplusplus diff --git a/bsps/shared/dev/gpio/gpio-support.c b/bsps/shared/dev/gpio/gpio-support.c index 9c053dc151..917e53a7a1 100644 --- a/bsps/shared/dev/gpio/gpio-support.c +++ b/bsps/shared/dev/gpio/gpio-support.c @@ -621,16 +621,16 @@ static rtems_status_code gpio_multi_select( return RTEMS_RESOURCE_IN_USE; } - } - for ( i = 0; i < pin_count; ++i ) { sc = rtems_gpio_request_configuration(&pins[i]); if ( sc != RTEMS_SUCCESSFUL ) { + RELEASE_LOCK(gpio_bank_state[bank].lock); return sc; } gpio_pin_state[pins[i].pin_number].on_group = on_group; + RELEASE_LOCK(gpio_bank_state[bank].lock); } return RTEMS_SUCCESSFUL; @@ -1309,6 +1309,9 @@ rtems_status_code rtems_gpio_request_pin( uint32_t bank; uint32_t pin; +#if defined(DEBUG) + printk("rtems_gpio_request_pin : pinNr: %d, function = %d, bsp_specific = %p\n", pin_number, function, bsp_specific); +#endif if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) { return RTEMS_INVALID_ID; } diff --git a/spec/build/bsps/arm/beagle/obj.yml b/spec/build/bsps/arm/beagle/obj.yml index 513c7414e4..4ee2a4dd6e 100644 --- a/spec/build/bsps/arm/beagle/obj.yml +++ b/spec/build/bsps/arm/beagle/obj.yml @@ -21,6 +21,7 @@ install: - bsps/arm/beagle/include/bsp/pwmss.h - bsps/arm/beagle/include/bsp/qep.h - bsps/arm/beagle/include/bsp/spi.h + - bsps/arm/beagle/include/bsp/bbb-adc.h - destination: ${BSP_INCLUDEDIR}/libcpu source: - bsps/arm/include/libcpu/am335x.h @@ -34,6 +35,7 @@ source: - bsps/arm/beagle/clock/clock.c - bsps/arm/beagle/console/console-config.c - bsps/arm/beagle/gpio/bbb-gpio.c +- bsps/arm/beagle/adc/bbb-adc.c - bsps/arm/beagle/i2c/bbb-i2c.c - bsps/arm/beagle/irq/irq.c - bsps/arm/beagle/pwm/pwm.c