From 5bc334c32055e8d3cdf61a430f3d325adfef015d Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Wed, 20 Sep 2017 18:15:02 +0200 Subject: [PATCH] dey-examples: add libdigiapix I2C example Signed-off-by: Mike Engel https://jira.digi.com/browse/DEL-4873 --- apix-i2c-example/.gitignore | 6 + apix-i2c-example/Makefile | 43 ++++++ apix-i2c-example/README.md | 71 +++++++++ apix-i2c-example/main.c | 293 ++++++++++++++++++++++++++++++++++++ 4 files changed, 413 insertions(+) create mode 100644 apix-i2c-example/.gitignore create mode 100644 apix-i2c-example/Makefile create mode 100644 apix-i2c-example/README.md create mode 100644 apix-i2c-example/main.c diff --git a/apix-i2c-example/.gitignore b/apix-i2c-example/.gitignore new file mode 100644 index 0000000..eebd856 --- /dev/null +++ b/apix-i2c-example/.gitignore @@ -0,0 +1,6 @@ +apix-i2c-example +*.o +.cproject +.project +.settings/ +*~ \ No newline at end of file diff --git a/apix-i2c-example/Makefile b/apix-i2c-example/Makefile new file mode 100644 index 0000000..6dd2ddf --- /dev/null +++ b/apix-i2c-example/Makefile @@ -0,0 +1,43 @@ +# +# Copyright (c) 2017 Digi International Inc. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +# + +EXECUTABLE = apix-i2c-example + +SRC = . + +CFLAGS += -Wall -O2 + +CFLAGS += $(shell pkg-config --cflags libdigiapix) +LDLIBS += $(shell pkg-config --libs libdigiapix) + +SRCS = $(wildcard $(SRC)/*.c) +OBJS = $(SRCS:.c=.o) + +.PHONY: all +all: $(EXECUTABLE) + +$(EXECUTABLE): $(OBJS) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +.PHONY: install +install: $(EXECUTABLE) + install -d $(DESTDIR)/usr/bin + install -m 0755 $(EXECUTABLE) $(DESTDIR)/usr/bin/ + +.PHONY: clean +clean: + -rm -f $(EXECUTABLE) $(OBJS) diff --git a/apix-i2c-example/README.md b/apix-i2c-example/README.md new file mode 100644 index 0000000..c4cd489 --- /dev/null +++ b/apix-i2c-example/README.md @@ -0,0 +1,71 @@ +Digi APIX I2C Sample Application +================================= + +Sample application to access and manage I2C slaves using the Digi APIX library. + +The application writes a page of an external EEPROM memory with random +data and then reads the data back to validate it (tested with 24FC1026). + +The I2C connections for the sample depend on the running platform: + - **CCIMX6 SBC**: I2C connector of the board. + - VCC: Pin 3 + - GND: Pin 6 + - I2C-3 SDA: Pin 2 + - I2C-3 SCL: Pin 1 + - **CCIMX6UL SBC Express**: Expansion connector of the board. + - VCC: Pin 1 + - GND: Pin 6 + - I2C-1 SDA: Pin 3 + - I2C-1 SCL: Pin 5 + - **CCIMX6UL SBC Pro**: I2C connector of the board. + - VCC: Pin 3 + - GND: Pin 6 + - I2C-2 SDA: Pin 2 + - I2C-2 SCL: Pin 1 + +Running the application +----------------------- +Once the binary is in the target, launch the application: + +``` +#> apix-i2c-example +Example application using libdigiapix I2C support + +Usage: %s + + I2C bus index to use + Address of the I2C EEPROM memory + Number of EEPROM memory address bytes + EEPROM memory page size in bytes + EEPROM memory page index to use + +Aliases for SPI can be configured in the library config file +``` + +Compiling the application +------------------------- +This example can be compiled using a Digi Embedded Yocto based toolchain. Make +sure to source the corresponding toolchain of the platform you are using, e.g: + +``` +$> . /environment-setup-cortexa7hf-vfp-neon-dey-linux-gnueabi +$> make +``` + +More information about [Digi Embedded Yocto](https://github.com/digi-embedded/meta-digi). + +License +------- +Copyright 2017, Digi International Inc. + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. \ No newline at end of file diff --git a/apix-i2c-example/main.c b/apix-i2c-example/main.c new file mode 100644 index 0000000..faa346b --- /dev/null +++ b/apix-i2c-example/main.c @@ -0,0 +1,293 @@ +/* + * Copyright 2017, Digi International Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define I2C_TIMEOUT 1 + +static i2c_t *i2c_bus; +static unsigned int i2c_address; +static int eeprom_page_size, eeprom_addr_size; +static uint8_t *tx_buf; +static uint8_t *rx_buf; + +/* + * usage_and_exit() - Show usage information and exit with 'exitval' return + * value + */ +static void usage_and_exit(char *name, int exitval) +{ + fprintf(stdout, + "Example application using libdigiapix I2C support\n" + "\n" + "Usage: %s \n\n" + " I2C bus index to use\n" + " Address of the I2C EEPROM memory\n" + " Number of EEPROM memory address bytes\n" + " EEPROM memory page size in bytes\n" + " EEPROM memory page index to use\n" + "\n" + "Aliases for I2C can be configured in the library config file\n" + "\n", name); + + exit(exitval); +} + +/* + * cleanup() - Frees all the allocated memory before exiting + */ +static void cleanup(void) +{ + /* Free i2c */ + i2c_free(i2c_bus); + + /* Free buffers */ + free(rx_buf); + free(tx_buf); +} + +/** + * sigaction_handler() - Handler to execute after receiving a signal. + * + * @signum: Received signal. + */ +static void sigaction_handler(int signum) +{ + /* 'atexit' executes the cleanup function */ + exit(EXIT_SUCCESS); +} + +/* + * register_signals() - Registers program signals + */ +static void register_signals(void) +{ + struct sigaction action; + + action.sa_handler = sigaction_handler; + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + + sigaction(SIGHUP, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); +} + +static int write_page(int page_index, uint8_t *data) +{ + unsigned int page_address = eeprom_page_size * page_index; + int i, ret; + uint8_t *write_data; + + /* Create write buffer */ + write_data = (uint8_t*)calloc(eeprom_page_size + eeprom_addr_size, sizeof(uint8_t)); + if (write_data == NULL) { + printf("Error: allocating page memory\n"); + return EXIT_FAILURE; + } + + printf("Writing %d bytes to page %d at address 0x%x...\n", eeprom_page_size, + page_index, page_address); + + for (i = 0; i < eeprom_addr_size; i++) { + write_data[i] = (page_address >> (8 * (eeprom_addr_size - i -1))); + } + + /* Fill the data array. */ + for (i = 0; i < eeprom_page_size; i++) { + write_data[(i + eeprom_addr_size)] = data[i]; + } + + if (i2c_write(i2c_bus, i2c_address, write_data, (uint16_t)(eeprom_page_size + eeprom_addr_size)) != EXIT_SUCCESS) { + printf("Error: Data written failed.\n"); + free(write_data); + return EXIT_FAILURE; + } + + /* Wait for the operation to complete. (try to set I2C address offset until + we get a success result). */ + do { + printf("Write in progress...\n"); + ret = i2c_write(i2c_bus, i2c_address, write_data, (uint16_t)eeprom_addr_size); + usleep(1); + } while (ret == EXIT_FAILURE); + printf("Write finished!\n"); + + free(write_data); + + return EXIT_SUCCESS; +} + +static int read_page(int page_index, uint8_t *data) +{ + unsigned int page_address = eeprom_page_size * page_index; + uint8_t *write_data; + int i; + + /* Create write buffer */ + write_data = (uint8_t*)calloc(eeprom_addr_size, sizeof(uint8_t)); + if (write_data == NULL) { + printf("Error: allocating page memory\n"); + return EXIT_FAILURE; + } + + printf("Reading %d bytes from page %d at address 0x%x...\n", eeprom_page_size, + page_index, page_address); + + for (i = 0; i < eeprom_addr_size; i++) { + write_data[i] = (page_address >> (8 * (eeprom_addr_size - i -1))); + } + + if (i2c_transfer(i2c_bus, i2c_address, write_data, (uint16_t)eeprom_addr_size, + data, (uint16_t)eeprom_page_size) != EXIT_SUCCESS) { + printf("Failed to read data\n"); + free(write_data); + return EXIT_FAILURE; + } + + free(write_data); + + return EXIT_SUCCESS; +} + +int main(int argc, char **argv) +{ + char *name = basename(argv[0]); + int page_index; + int i2c_bus_nb; + int i; + + /* Check input parameters */ + if (argc != 6) { + usage_and_exit(name, EXIT_FAILURE); + return EXIT_FAILURE; + } + + i2c_bus_nb = atoi(argv[1]); + i2c_address = (unsigned int)strtol(argv[2],NULL,16); + eeprom_addr_size = atoi(argv[3]); + eeprom_page_size = atoi(argv[4]); + page_index = atoi(argv[5]); + + if (eeprom_addr_size <= 0) { + printf("Address size must be greater than 0\n"); + return EXIT_FAILURE; + } + + if (page_index < 0) { + printf("Page index must be 0 or greater\n"); + return EXIT_FAILURE; + } + + if (eeprom_page_size <= 0) { + printf("Page size must be greater than 0\n"); + return EXIT_FAILURE; + } + + if (i2c_bus_nb < 0) { + printf("I2C bus index must be 0 or greater\n"); + return EXIT_FAILURE; + } + + /* Register signals and exit cleanup function */ + atexit(cleanup); + register_signals(); + + /* Request I2C */ + i2c_bus = i2c_request((unsigned int)i2c_bus_nb); + if (!i2c_bus) { + printf("Failed to initialize I2C\n"); + return EXIT_FAILURE; + } + + /* Set the timeout for the I2C slave. */ + if (i2c_set_timeout(i2c_bus, I2C_TIMEOUT) != EXIT_SUCCESS) { + printf("Failed to set I2C timeout\n"); + return EXIT_FAILURE; + } + + printf("Preparing I2C data to write...\n"); + + /* Create write buffer */ + tx_buf = (uint8_t*)calloc(eeprom_page_size + eeprom_addr_size, sizeof(uint8_t)); + if (tx_buf == NULL) { + printf("Error: allocating page memory\n"); + return EXIT_FAILURE; + } + + /* Erase the EEPROM page. */ + for (i = 0; i < eeprom_page_size; i++) { + tx_buf[i] = 0xFF; + } + + if (write_page(page_index, tx_buf) != EXIT_SUCCESS) { + printf("Failed to erase EEPROM\n"); + return EXIT_FAILURE; + } + + /* Create some random data that will be written to the EEPROM */ + srand(time(NULL)); + + for (i = 0; i < eeprom_page_size; i++) { + tx_buf[i] = rand() % 255; + } + + /* Write new data */ + if (write_page(page_index, tx_buf) != EXIT_SUCCESS) { + printf("Failed to write EEPROM\n"); + return EXIT_FAILURE; + } + + /* Create read buffer */ + rx_buf = (uint8_t*)calloc(eeprom_page_size, sizeof(uint8_t)); + if (rx_buf == NULL) { + printf("Error: allocating page memory\n"); + return EXIT_FAILURE; + } + + /* Read the data back */ + if (read_page(page_index, rx_buf) != EXIT_SUCCESS) { + printf("Failed to read EEPROM\n"); + return EXIT_FAILURE; + } + + /* Verify the written data */ + printf("Validating read data...\n"); + + for (i = 0; i < eeprom_page_size; i++) { + printf("written_data[%d] = 0x%02x : read_data[%d] = 0x%02x\n", i, + tx_buf[i], i, rx_buf[i]); + if (rx_buf[i] != tx_buf[i]) { + printf("Failed while comparing written EEPROM data.\n \ + Expected 0x%x but got 0x%x\n", tx_buf[i], rx_buf[i]); + return EXIT_FAILURE; + } + } + + printf("Data has been written and verified correctly\n"); + + return EXIT_SUCCESS; +}