From b1bfc1ec682aa6bb8daa6826e2830f32f1de9e0e Mon Sep 17 00:00:00 2001 From: Artem Shyshko Date: Tue, 8 Mar 2022 18:18:26 +0200 Subject: [PATCH] TASK08: Implemented IRQ handling task Following files were added: procfs_module.c - a Linux kernel module for OrangePi Zero board which switches red led light using selected interrupt. Makefile contains target for the module's build process. --- 08_irq_handling/Makefile | 12 +++ 08_irq_handling/irq_module.c | 65 ++++++++++++++ 08_irq_handling/irq_module.ko | Bin 0 -> 4676 bytes 08_irq_handling/led_mod.c | 154 ---------------------------------- 4 files changed, 77 insertions(+), 154 deletions(-) create mode 100644 08_irq_handling/Makefile create mode 100644 08_irq_handling/irq_module.c create mode 100644 08_irq_handling/irq_module.ko delete mode 100644 08_irq_handling/led_mod.c diff --git a/08_irq_handling/Makefile b/08_irq_handling/Makefile new file mode 100644 index 0000000..cd18352 --- /dev/null +++ b/08_irq_handling/Makefile @@ -0,0 +1,12 @@ +ORANGEKERN ?= ~/Orange/buildroot-2021.11.1/output/build/linux-5.12.2/ #relative path +LOCALKERN ?= /lib/modules/$(shell uname -r)/build + +obj-m := irq_module.o + +all: clean build + +build: + $(MAKE) -C $(ORANGEKERN) M=$(PWD) modules + +clean: + $(MAKE) -C $(ORANGEKERN) M=$(PWD) clean diff --git a/08_irq_handling/irq_module.c b/08_irq_handling/irq_module.c new file mode 100644 index 0000000..8c761b4 --- /dev/null +++ b/08_irq_handling/irq_module.c @@ -0,0 +1,65 @@ +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME +#define MOD_AUTHOR "Artem Shyshko" +#define MOD_LICENSE "GPL" + +#include +#include +#include +#include + +#define GPIO_NUMBER(port, bit) (32 * (port) + (bit)) +#define LED_RED GPIO_NUMBER(0, 17) + +static int irq, dev_id = 1; +static int ledr_gpio = -1; +static bool irq_count = false; + +module_param(irq, int, S_IRUGO); + +static irqreturn_t timer_interrupt(int irq, void* dev_id) +{ + irq_count = !irq_count; + gpio_set_value(ledr_gpio, irq_count); + return IRQ_NONE; +} + +static int led_gpio_init(int gpio, int *led_gpio) +{ + int res; + + res = gpio_direction_output(gpio, 0); + if (res != 0) + return res; + + *led_gpio = gpio; + return 0; +} + +static int proc_init(void) +{ + int res = 0; + if (request_irq(irq, timer_interrupt, IRQF_SHARED, "interrupt", &dev_id)) { + res = -1; + pr_info("Error while loading\n"); + } else { + pr_info("Module loaded, %d\n", irq); + res = led_gpio_init(LED_RED, &ledr_gpio); + if (res != 0) + pr_err("Can't set GPIO%d for output\n", LED_RED); + } + return res; +} + +static void proc_exit(void) +{ + synchronize_irq(irq); + free_irq(irq, &dev_id); + gpio_set_value(ledr_gpio, 0); + pr_info("Module exited\n"); +} + +module_init(proc_init); +module_exit(proc_exit); + +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_LICENSE(MOD_LICENSE); diff --git a/08_irq_handling/irq_module.ko b/08_irq_handling/irq_module.ko new file mode 100644 index 0000000000000000000000000000000000000000..f824966fe05c0ea94db5eebaac22790ddd2ba8d7 GIT binary patch literal 4676 zcmeHKQEVJ%5uUv}rx&LVwn<3}ZnZ5=G1y++U7R`%G2G#VB;X{bQBZ^`HtX9>yvp6} zc5lyd5DFH`1E5B#sl_g%H3Q8o9=z}AKTJgj~B~YIbYHdtIkx&arydaM6+ui@X zd!kaG5hLx*d^7XU{QvB~|3CMg6ANF~G))v~G9f!iwdo^Y zL4PTZ*XK8a`7qXinjd10l-Bc7x;gOIZZ{Kqg!z;B?{>TIMQd0@-o@(9{N=@Dyq^bTuim?lIlRYu-o1Ng?FjiR+STM^~PcEK5 zchJ@^BaGJx{Z80F-dS}+CmxIZ(s1ietL@C4TwD;V6E1tfTrCKlrhb0;dVBe*C%zRl z!|T2?2k)bpz1WWLwCwhrw5(>NRclyrf~IxFtV9SAh|Y8@9&gLrdDbF|K8&~(#&ULHO{+_>{=_KYL;UyxuQJ*abR}3Cc6e7s1>!{xxw6MZlCs$wm*MBdszEq z?$O-iAGRyw+UGN;GSA*z=B4DL(|AXfmw_DsDK9*ccPKA72~(7p-6=%>=+p1%^0KEV zQ^?CuAC4~yrOe}yO;cV*(h%cE`|!v6FmIS0%F9EU3KZmnZZ^VRc!*T+a3vb%KL!4I zJe&z}75uAsCKH?;pOcHwlMdj~P~S@g2{B(&fr#hDPcYBl99FcJ;Fyid4>EYDZ^gU% za8Yh&{EPBK;0JrUqPz^5bBn1cKY}o$Al~O4$crib6Udy~8+bUsUx4#Yh^Z(W5O`;B z4DH!^?3Q20j?uZPp{iN?ki3<#56RoW><##6*dJN{QF#}75_h@=>n|bf_>am5ku_d3 z-&YZKuAlFf_)*};Aaf@XXXEdY!?2UMb2RMNtUdOxL>~MZlv?6X#69vAh4E>P$X>aq zaANm>RlP=0uN!^#7l2j0X@9xT{%Rk7y$}DP4{!J3zxCnNg=OFpH0m;Li)mgsd-`h^ zPMD{Uo5?j=F3)7tyj08OLm8dASj**#m@O}K%-M8!gtjDfn@(WvbQi`#?d<%ib5EB< zNo7d$g!7S9p>&8pGvWtc9b?^)@Nf*-Ctw!1{;j6j4iTH(f@25f72oyH1+18^9ZjR| z;cU)KIB6;>l_ME-++S2Gvl%VovcITQp6sP#s>^}nL^(|}Tz1>4$uQ06*hW)v&28Cc z-S8EHtcC^epVwc$6AbE(}HqwY1E4t8HW zFZ}{Bn4o;PgJPNi!)xwQA(0I5wBJSG13j;}{)E_~ z+#0=($A`Q?MM5ebUj=)GYNFpji?a;BPXP0E(~s}+I35mH^V>+pf;zI1pO0n#y96Nm zaeiv+sJ!Q(OXnR&E2TrnyzJ6c-fu!?Ds^Z54&eL1is(l>`x0_Bze^BQE~tBQr_axZ z-wGWPVhj@JpN{u?`0a}<@sEmq12Dag#9h_yA4I!FB$+} zMb$)j9z31bMqYl4tRK5jmG@_md+`_tEithoCBF)V^3&j_eTd&{@Z-GIItuXnZ|k_1 z#4CZ5==b$ljDDGm5Bn=M2O7QszceY^TTmh=w{b-DD=Pr5{K!+~lIP%8LNWG3kK-?@ f3+u$%sWm{94JuLtRXp}tX}=J4{u2izr2PH^SxAUe literal 0 HcmV?d00001 diff --git a/08_irq_handling/led_mod.c b/08_irq_handling/led_mod.c deleted file mode 100644 index 5444623..0000000 --- a/08_irq_handling/led_mod.c +++ /dev/null @@ -1,154 +0,0 @@ -#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ - -#include -#include -#include -#include - -#define GPIO_NUMBER(port, bit) (32 * (port) + (bit)) - -/* https://linux-sunxi.org/Xunlong_Orange_Pi_PC#LEDs - * Board config for OPI-PC: - * LED GREEN (PL10): GPIO_11_10 - * LED RED (PA15): GPIO_0_15 - * BUTTON (PG7) : GPIO_6_7 - * - * https://linux-sunxi.org/Xunlong_Orange_Pi_Zero#LEDs - * Board config for OPI-Zero: - * LED GREEN (PL10): GPIO_11_10 - * LED RED (PA17): GPIO_0_17 - * BUTTON (PG7) : GPIO_6_7 - * - */ - -#define LED_GREEN GPIO_NUMBER(11, 10) -#define LED_RED GPIO_NUMBER(0, 15) -#define BUTTON GPIO_NUMBER(6, 7) - -//#define TIMER_ENABLE 1 - -static int ledg_gpio = -1; -static int ledr_gpio = -1; -static int button_gpio = -1; -static int button_state = -1; -static int button_cnt = -1; - -#ifdef TIMER_ENABLE -static ktime_t timer_period; -struct hrtimer button_timer; - -static enum hrtimer_restart timer_callback(struct hrtimer *timer) -{ - int cur_button_state; - - cur_button_state = gpio_get_value(button_gpio); - button_cnt = (cur_button_state == button_state) ? (button_cnt + 1) : 0; - button_state = cur_button_state; - gpio_set_value(ledr_gpio, ((button_cnt == 20) ? 1 : 0)); - if (button_cnt >= 20) - gpio_set_value(ledg_gpio, !button_state); - hrtimer_forward(timer, timer->base->get_time(), timer_period); - return HRTIMER_RESTART; //restart timer -} -#endif - -static int led_gpio_init(int gpio, int *led_gpio) -{ - int res; - - res = gpio_direction_output(gpio, 0); - if (res != 0) - return res; - - *led_gpio = gpio; - return 0; -} - -static int button_gpio_init(int gpio) -{ - int res; - - res = gpio_request(gpio, "Onboard user button"); - if (res != 0) - return res; - - res = gpio_direction_input(gpio); - if (res != 0) - goto err_input; - - button_gpio = gpio; - pr_info("Init GPIO%d OK\n", button_gpio); - button_state = gpio_get_value(button_gpio); - button_cnt = 0; - - return 0; - -err_input: - gpio_free(gpio); - return res; -} - -static void button_gpio_deinit(void) -{ - if (button_gpio >= 0) { - gpio_free(button_gpio); - pr_info("Deinit GPIO%d\n", button_gpio); - } -} - -/* Module entry/exit points */ -static int __init gpio_poll_init(void) -{ - int res; - pr_info("GPIO Init\n"); - - res = button_gpio_init(BUTTON); - if (res != 0) { - pr_err("Can't set GPIO%d for button\n", BUTTON); - return res; - } -#ifdef TIMER_ENABLE - timer_period = ktime_set(0, 1000000); /*1 msec*/ - hrtimer_init(&button_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer_start(&button_timer, timer_period, HRTIMER_MODE_REL); - button_timer.function = timer_callback; -#endif - res = led_gpio_init(LED_GREEN, &ledg_gpio); - if (res != 0) { - pr_err("Can't set GPIO%d for output\n", LED_GREEN); - goto err_led; - } - - gpio_set_value(ledg_gpio, 0); - - res = led_gpio_init(LED_RED, &ledr_gpio); - if (res != 0) { - pr_err("Can't set GPIO%d for output\n", LED_RED); - goto err_led; - } - gpio_set_value(ledr_gpio, 1); - - return 0; - -err_led: - button_gpio_deinit(); - return res; -} - -static void __exit gpio_poll_exit(void) -{ - gpio_set_value(ledg_gpio, 0); - gpio_set_value(ledr_gpio, 0); - button_gpio_deinit(); -#ifdef TIMER_ENABLE - hrtimer_cancel(&button_timer); -#endif -} - -module_init(gpio_poll_init); -module_exit(gpio_poll_exit); - -MODULE_AUTHOR("Oleksandr Posukhov oleksandr.posukhov@gmail.com>"); -MODULE_DESCRIPTION("LED Test"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("0.1"); \ No newline at end of file