From 372d338d3fd9810a1b87e019d56f9b693f38b215 Mon Sep 17 00:00:00 2001 From: Francisco Gil Martinez Date: Fri, 1 Sep 2017 11:57:06 +0200 Subject: [PATCH] pwm_apix_sample: add an example for the pwm digi apix https://jira.digi.com/browse/DEL-4881 Signed-off-by: Francisco Gil Martinez --- apix-pwm-example/Makefile | 43 ++++++++ apix-pwm-example/README.md | 105 ++++++++++++++++++++ apix-pwm-example/main.c | 197 +++++++++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 apix-pwm-example/Makefile create mode 100644 apix-pwm-example/README.md create mode 100644 apix-pwm-example/main.c diff --git a/apix-pwm-example/Makefile b/apix-pwm-example/Makefile new file mode 100644 index 0000000..8be9bfd --- /dev/null +++ b/apix-pwm-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 = pwm-digiapix-sample + +SRC = . + +CFLAGS += -Wall + +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-pwm-example/README.md b/apix-pwm-example/README.md new file mode 100644 index 0000000..5630927 --- /dev/null +++ b/apix-pwm-example/README.md @@ -0,0 +1,105 @@ +Digi APIX PWM Sample Application +=================================== + +Sample application to access and manage PWM lines using the Digi APIX library. + +The application enables one PWM line of the board using a frequency of +1000Hz. Then, progressively modifies the duty cycle in a loop from 10% to +90% and vice-versa. + +The PWM lines used in the sample are mapped as follows in the Digi Boards: + - **CCIMX6 SBC**: PWM1 - Pin **10** of the parallel video (LCD) connector. + - **CCIMX6UL SBC Express**: PWM1 - Pin **27** of the expansion connector. + - **CCIMX6UL SBC Pro**: PWM4 - Pin **11** of the GPIO connector. + +The following device tree modifications are required for the sample to work: + - **CCIMX6 SBC**: +``` +/* PWM1 */ +&pwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; + status = "okay"; +}; + +/* Pin mux configuration */ +&iomuxc { + imx6q-ccimx6sbc { + pinctrl_pwm1: pwm1grp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x110b0 + >; + }; + }; +}; +``` + - **CCIMX6UL SBC Express**: + _No device tree modifications are required._ + - **CCIMX6UL SBC Pro**: +``` +/* PWM4 */ +&pwm4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm4>; + clocks = <&clks IMX6UL_CLK_PWM4>, + <&clks IMX6UL_CLK_PWM4>; + status = "okay"; +}; + +/* Pin mux configuration */ +&iomuxc { + imx6ul-ccimx6ul { + pinctrl_pwm4: pwm4grp { + fsl,pins = < + MX6UL_PAD_GPIO1_IO05__PWM4_OUT 0x110b0 + >; + }; + }; +}; +``` + +Running the application +----------------------- +Once the binary is in the target, launch the application: +``` +#> pwm-digiapix-sample +``` + +The sample applicaion is ready to work with all Digi platforms using the corresponding +PWM chip (0 by default) and a frequency of 1000Hz. If a different PWM chip or frequency +is required, the application allows 2 additional parameters in order to customize +these values: +``` +#> pwm-digiapix-sample [pwm-chip pwm-freq] +``` +Where: + - 'pwm-chip' is an optional PWM chip number. + - 'pwm-freq' is an optional frequency to use (Hz). + +Compiling the application +------------------------- +This demo 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-pwm-example/main.c b/apix-pwm-example/main.c new file mode 100644 index 0000000..c2fde5e --- /dev/null +++ b/apix-pwm-example/main.c @@ -0,0 +1,197 @@ +/* + * 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. + * ======================================================================= + */ +#include +#include +#include +#include +#include + +#include + +/*------------------------------------------------------------------------------ + D E F I N I T I O N S +------------------------------------------------------------------------------*/ + +#define DEFAULT_PWM_CHANNEL 0 +#define DEFAULT_FREQUENCY 1000 /* In Hz */ +#define DEFAULT_PWM_ALIAS "DEFAULT_PWM" + + +#define BUFF_SIZE 256 +#define USAGE \ + "Usage:\n" \ + "%s [pwm-chip pwm-freq]\n\n" \ + "Where:\n" \ + " 'pwm-chip' is an optional PWM chip number\n" \ + " 'pwm-freq' is an optional frequency to use (Hz)\n\n" \ + +/*------------------------------------------------------------------------------ + F U N C T I O N D E C L A R A T I O N S +------------------------------------------------------------------------------*/ +static void cleanup(); +static void add_sigkill_signal(void); +static void graceful_shutdown(void); +static void sigint_handler(int signum); +static void usage(char const * const name); + +/** + * sigint_handler() - Manage signal received. + * + * @signum: Received signal. + */ +static void sigint_handler(int signum) +{ + exit(EXIT_SUCCESS); +} + +/** + * usage() - Print usage information + * + * @name: Name of the application. + */ +static void usage(char const * const name) +{ + printf(USAGE, name); +} + +/*------------------------------------------------------------------------------ + G L O B A L V A R I A B L E S +------------------------------------------------------------------------------*/ +static pwm_t *pwm_line; +static int running = 1; + +int main(int argc, char **argv) +{ + unsigned int pwm_freq = DEFAULT_FREQUENCY; + int ret, duty_cycle = 10, ascending = 1; + char *name = basename(argv[0]); + + /* Check if the PWM values are passed in the command line. */ + if (argc == 3) { + unsigned int pwm_chip = atoi(argv[1]); + pwm_freq = atoi(argv[2]); + pwm_line = pwm_request(pwm_chip, DEFAULT_PWM_CHANNEL, REQUEST_SHARED); + } else if (argc == 1) { + /* Initialize the PWM. */ + pwm_line = pwm_request_by_alias(DEFAULT_PWM_ALIAS, REQUEST_SHARED); + } else if (argc <= 2 || argc > 3) { + usage(name); + return EXIT_FAILURE; + } + + /* Check PWM. */ + if (!pwm_line) { + printf("Failed to initialize PWM\n"); + return EXIT_FAILURE; + } + + add_sigkill_signal(); + + printf("Setting PWM frequency to %dHz...", pwm_freq); + /* Set a duty cycle of 0 to avoid errors configuring the frequency */ + pwm_set_duty_cycle(pwm_line, 0); + ret = pwm_set_freq(pwm_line, pwm_freq); + if (ret != PWM_CONFIG_ERROR_NONE) { + printf("Failed\n"); + return EXIT_FAILURE; + } + + /* Check the frequency. */ + ret = pwm_get_freq(pwm_line); + printf("%s\n", ret >= 0 ? "Done" : "Failed"); + if (ret == -1) { + return EXIT_FAILURE; + } + + printf("Enabling PWM %d:%d...", pwm_line->chip, pwm_line->channel); + ret = pwm_enable(pwm_line, PWM_ENABLED); + if (ret != EXIT_SUCCESS) { + printf("Failed\n"); + return EXIT_FAILURE; + } + + ret = pwm_is_enabled(pwm_line); + printf("%s\n", ret == PWM_ENABLED ? "Done" : "Failed"); + if (ret != PWM_ENABLED) { + return EXIT_FAILURE; + } + + /* Main application loop.*/ + while (running) { + /* Set the duty cycle. */ + ret = pwm_set_duty_cycle_percentage(pwm_line, duty_cycle); + if (ret != PWM_CONFIG_ERROR_NONE) { + printf("Failed to set the duty cycle\n"); + return EXIT_FAILURE; + } + if (ascending) { + duty_cycle += 10; + if (duty_cycle == 100) { + duty_cycle = 80; + ascending = 0; + } + } else { + duty_cycle -= 10; + if (duty_cycle == 0) { + duty_cycle = 20; + ascending = 1; + } + } + sleep(1); + } + + return EXIT_SUCCESS; +} + +/** + * cleanup() - Frees and leaves PWM into a known state before exit + */ +static void cleanup() +{ + if (pwm_line) { + pwm_enable(pwm_line, PWM_DISABLED); + pwm_free(pwm_line); + } +} + +/** + * add_sigkill_signal() - Add the kill signal to the process + */ +static void add_sigkill_signal(void) +{ + struct sigaction new_action; + struct sigaction old_action; + + /* Setup signal hander. */ + atexit(graceful_shutdown); + new_action.sa_handler = sigint_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + sigaction(SIGINT, NULL, &old_action); + + if (old_action.sa_handler != SIG_IGN) + sigaction(SIGINT, &new_action, NULL); +} + +/** + * graceful_shutdown() - Stop main loop + */ +void graceful_shutdown(void) +{ + running = 0; + cleanup(); +}