From e683a4e74ef4acf738706fbf6cb15948754849bf Mon Sep 17 00:00:00 2001 From: Dan O'Donovan Date: Fri, 18 Nov 2016 12:12:08 +0000 Subject: [PATCH 1/2] update UP board hardware details and enable ADC Some details regarding the UP board are not in-sync with the final production version of the board. This update adds an ADC, removes a UART, and some corrections in the docs for UP. Signed-off-by: Dan O'Donovan --- docs/up.md | 29 ++++++++++++++++------------- src/x86/up.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/docs/up.md b/docs/up.md index 066a25d68..4c3c764ef 100644 --- a/docs/up.md +++ b/docs/up.md @@ -1,11 +1,11 @@ UP Board {#up} ============ -UP Board is based on the Intel(R) Atom(TM) x5-Z83xx SoC (formerly Cherry Trail). -It includes 2GB RAM, 16/32GB eMMC flash, 6 USB2.0 ports, 1 USB 3.0 OTG port, -1 Gigabit Ethernet, HDMI and DSI Graphics ports, RTC and a 40-pin I/O header. -The form-factor for the board is based on the Raspberry Pi 2, and can be used -with many of the add-on HAT boards designed for the Raspberry Pi 2. +UP Board is based on the Intel(R) Atom(TM) x5-Z8350 SoC (formerly Cherry Trail). +It includes 1/2/4GB RAM, 16/32/64GB eMMC flash, 6 USB2.0 ports, 1 USB 3.0 OTG +port, 1 Gigabit Ethernet, HDMI and DSI/eDP Graphics ports, RTC and a 40-pin I/O +header. The form-factor for the board is based on the Raspberry Pi 2, and can be +used with many of the add-on HAT boards designed for the Raspberry Pi. Interface notes --------------- @@ -25,12 +25,15 @@ granular at higher speeds. E.g. Available speeds include: 25MHz, 12.5MHz, 8.33MHz, 6.25MHz, 5MHz, 4.167MHz, 3.571MHz, 3.125MHz, etc. Please be aware that speeds in between those steps will be rounded UP to the next nearest available speed, and capped at 25MHz. -At the time of writing, only a single native chip-select is available (SPI CS0). +2 chip-selects are available, one natively (SPI CS0) and one by GPIO (SPI CS1). -**UART** 2 high-speed UARTs are available, supporting baud rates up to -support baud rates between 300 and 3686400. Hardware flow-control signals are -not exposed, so software flow-control may be needed for rates above 115200. -A console UART is also available but is not fully supported at this time. +**UART** 1 high-speed UART is available, supporting baud rates between 300 and +3686400. Hardware flow-control signals are available on pins 11/36 (RTS/CTS). + +**ADC** 1 8-bit single-channel ADC (TI ADC081C021) is available on pin 7. + +Please note that a kernel with UP board support is required to enable the I/O +interfaces above. Refer to https://up-community.org for more information. Pin Mapping ----------- @@ -48,13 +51,13 @@ Note that there is an enum to use wiringPi style numbers. | 4 | P1-04 | 5V VCC | | | | 5 | P1-05 | I2C SCL1 | 3 | I2C1 (/dev/i2c-1) | | 6 | P1-06 | GND | | | -| 7 | P1-07 | GPIO(4) | 4 | | +| 7 | P1-07 | GPIO(4) | 4 | ADC0 (iio:device0) | | 8 | P1-08 | UART TX1 | 14 | UART1 (/dev/ttyS1) | | 9 | P1-09 | GND | | | | 10 | P1-10 | UART RX1 | 15 | UART1 (/dev/ttyS1) | | 11 | P1-11 | GPIO(17) | 17 | | | 12 | P1-12 | I2S CLK | 18 | I2S0 (PCM Audio) | -| 13 | P1-13 | UART RX2 | 27 | UART2 (/dev/ttyS2) | +| 13 | P1-13 | GPIO(27) | 27 | | | 14 | P1-14 | GND | | | | 15 | P1-15 | GPIO(22) | 22 | | | 16 | P1-16 | GPIO(23) | 23 | | @@ -63,7 +66,7 @@ Note that there is an enum to use wiringPi style numbers. | 19 | P1-19 | SPI MOSI | 10 | SPI2 (/dev/spidev2.x)| | 20 | P1-20 | GND | | | | 21 | P1-21 | SPI MISO | 9 | SPI2 (/dev/spidev2.x)| -| 22 | P1-22 | UART TX2 | 25 | UART2 (/dev/ttyS2) | +| 22 | P1-22 | GPIO(25) | 25 | | | 23 | P1-23 | SPI SCL | 11 | SPI2 (/dev/spidev2.x)| | 24 | P1-24 | SPI CS0 | 8 | SPI2 (/dev/spidev2.0)| | 25 | P1-25 | GND | | | diff --git a/src/x86/up.c b/src/x86/up.c index 9dd8fd833..335a112c3 100644 --- a/src/x86/up.c +++ b/src/x86/up.c @@ -62,6 +62,13 @@ set_pininfo(mraa_board_t* board, int mraa_index, char* name, mraa_pincapabilitie if (caps.spi) { pin_info->spi.mux_total = 0; } + if (caps.aio) { + pin_info->aio.mux_total = 0; + pin_info->aio.pinmap = 0; + } + if (caps.uart) { + pin_info->uart.mux_total = 0; + } return MRAA_SUCCESS; } return MRAA_ERROR_INVALID_RESOURCE; @@ -80,6 +87,28 @@ get_pin_index(mraa_board_t* board, char* name, int* pin_index) return MRAA_ERROR_INVALID_RESOURCE; } +static mraa_result_t +aio_get_valid_fp(mraa_aio_context dev) +{ + char file_path[64] = ""; + + /* + * Open file Analog device input channel raw voltage file for reading. + * + * The UP ADC has only 1 channel, so the channel number is not included + * in the filename + */ + snprintf(file_path, 64, "/sys/bus/iio/devices/iio:device0/in_voltage_raw"); + + dev->adc_in_fp = open(file_path, O_RDONLY); + if (dev->adc_in_fp == -1) { + syslog(LOG_ERR, "aio: Failed to open input raw file %s for reading!", file_path); + return MRAA_ERROR_INVALID_RESOURCE; + } + + return MRAA_SUCCESS; +} + mraa_board_t* mraa_up_board() { @@ -107,6 +136,8 @@ mraa_up_board() goto error; } + b->adv_func->aio_get_valid_fp = &aio_get_valid_fp; + if (uname(&running_uname) != 0) { free(b->pins); free(b->adv_func); @@ -122,13 +153,13 @@ mraa_up_board() set_pininfo(b, 4, "5v", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); set_pininfo(b, 5, "I2C1_SCL", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }, 3); set_pininfo(b, 6, "GND", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); - set_pininfo(b, 7, "GPIO4", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 4); + set_pininfo(b, 7, "ADC0", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 }, 4); set_pininfo(b, 8, "UART1_TX", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 1 }, 14); set_pininfo(b, 9, "GND", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); set_pininfo(b, 10, "UART1_RX", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 1 }, 15); set_pininfo(b, 11, "GPIO17", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 17); set_pininfo(b, 12, "I2S_CLK", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 18); - set_pininfo(b, 13, "UART2_RX", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 1 }, 27); + set_pininfo(b, 13, "GPIO27", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 27); set_pininfo(b, 14, "GND", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); set_pininfo(b, 15, "GPIO22", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 1, 0, 0 }, 22); set_pininfo(b, 16, "GPIO23", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 23); @@ -137,7 +168,7 @@ mraa_up_board() set_pininfo(b, 19, "SPI_MOSI", (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }, 10); set_pininfo(b, 20, "GND", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); set_pininfo(b, 21, "SPI_MISO", (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }, 9); - set_pininfo(b, 22, "UART2_TX", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 1 }, 25); + set_pininfo(b, 22, "GPIO25", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 25); set_pininfo(b, 23, "SPI_CLK", (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }, 11); set_pininfo(b, 24, "SPI_CS0", (mraa_pincapabilities_t){ 1, 1, 0, 0, 1, 0, 0, 0 }, 8); set_pininfo(b, 25, "GND", (mraa_pincapabilities_t){ 0, 0, 0, 0, 0, 0, 0, 0 }, -1); @@ -196,15 +227,16 @@ mraa_up_board() get_pin_index(b, "SPI_CLK", (int*) &(b->spi_bus[1].sclk)); // Configure UART #1 (default) - b->uart_dev_count = 2; + b->uart_dev_count = 1; get_pin_index(b, "UART1_RX", &(b->uart_dev[0].rx)); get_pin_index(b, "UART1_TX", &(b->uart_dev[0].tx)); b->uart_dev[0].device_path = "/dev/ttyS1"; b->def_uart_dev = 0; - // Configure UART #2 - get_pin_index(b, "UART2_RX", &(b->uart_dev[1].rx)); - get_pin_index(b, "UART2_TX", &(b->uart_dev[1].tx)); - b->uart_dev[1].device_path = "/dev/ttyS2"; + + // Configure ADC #0 + b->aio_count = 1; + b->adc_raw = 8; + b->adc_supported = 8; return b; error: From db4911381d1918ab31d9350c0e10ee20af99b68b Mon Sep 17 00:00:00 2001 From: Dan O'Donovan Date: Fri, 18 Nov 2016 16:18:01 +0000 Subject: [PATCH 2/2] make AIO pin look-up more flexible The current approach used to look up the pin for an AIO channel assumes that the AIO pins are positioned sequentially in the pins array immediately after the GPIO pins. This works for Arduino-style boards, but doesn't port well to other boards where ADC pins may be scattered around the pin array and providing GPIO functionality as well. This commit introduces a different approach by instead searching the pin array for ADC-capable pins, and infers their AIO channel numbers from the order in which they appear in the pin array. This should still work for boards such as Galileo and Edison, and while also supporting boards such as the UP board where the ADC pin appears at an arbitrary position in the pin array. Signed-off-by: Dan O'Donovan --- src/aio/aio.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/aio/aio.c b/src/aio/aio.c index de92d762b..6e36106a1 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -87,7 +87,8 @@ mraa_aio_context mraa_aio_init(unsigned int aio) { mraa_board_t* board = plat; - int pin; + int pin, adc_pin_index = -1; + if (board == NULL) { syslog(LOG_ERR, "aio: Platform not initialised"); return NULL; @@ -102,21 +103,23 @@ mraa_aio_init(unsigned int aio) aio = mraa_get_sub_platform_index(aio); } - // aio are always past the gpio_count in the pin array - pin = aio + board->gpio_count; - - if (pin < 0 || pin >= board->phy_pin_count) { - syslog(LOG_ERR, "aio: pin %i beyond platform definition", pin); - return NULL; - } if (aio >= board->aio_count) { syslog(LOG_ERR, "aio: requested channel out of range"); return NULL; } - if (board->pins[pin].capabilities.aio != 1) { - syslog(LOG_ERR, "aio: pin %i not capable of aio", pin); + + for (pin = 0; pin < board->phy_pin_count; pin++) { + // Assumes that AIO channels numbers match their order of appearance in the pin list + if (board->pins[pin].capabilities.aio == 1) + if (aio == ++adc_pin_index) + break; + } + + if (adc_pin_index != aio) { + syslog(LOG_ERR, "aio: unable to find pin for aio channel %i", aio); return NULL; } + if (board->pins[pin].aio.mux_total > 0) { if (mraa_setup_mux_mapped(board->pins[pin].aio) != MRAA_SUCCESS) { syslog(LOG_ERR, "aio: unable to setup multiplexers for pin");