From d9c8d851005f7ec60ec33ef93fb9d30a8b63c849 Mon Sep 17 00:00:00 2001
From: Fabian Arnold <fabi.arnold@ci4you.com>
Date: Tue, 22 May 2018 11:06:00 +0200
Subject: [PATCH] Added IRQ sample app for Button 2 on XMC4500

---
 app/system/CMakeLists.txt                    |   7 ++
 app/system/test_dispatch_complex.cc          |  12 ++-
 app/system/test_dispatch_complex.oil         |   5 +
 app/system/test_interrupt.cc                 |  76 +++++++++++++
 app/system/test_interrupt.oil                |  36 +++++++
 arch/armv7/dispatch.cc                       |   2 +-
 arch/armv7/gpio.h                            |  14 ++-
 arch/armv7/platforms/xmc4500/CMakeLists.txt  |   2 +
 arch/armv7/platforms/xmc4500/boot.cc         |   2 +-
 arch/armv7/platforms/xmc4500/gpio_xmc4500.cc | 106 +++++++++++++------
 arch/armv7/platforms/xmc4500/gpio_xmc4500.h  |  42 --------
 arch/armv7/platforms/xmc4500/machine_impl.cc |   9 --
 12 files changed, 225 insertions(+), 88 deletions(-)
 create mode 100644 app/system/test_interrupt.cc
 create mode 100644 app/system/test_interrupt.oil
 delete mode 100644 arch/armv7/platforms/xmc4500/gpio_xmc4500.h

diff --git a/app/system/CMakeLists.txt b/app/system/CMakeLists.txt
index 97e38ce0..a9d33bff 100644
--- a/app/system/CMakeLists.txt
+++ b/app/system/CMakeLists.txt
@@ -19,4 +19,11 @@ DOSEK_BINARY(
         LIBS libtest timing
         TEST_ISO
         test_context_save.cc
+)
+DOSEK_BINARY(
+        NAME test_interrupt
+        SYSTEM_DESC test_interrupt.oil
+        LIBS libtest timing
+        TEST_ISO
+        test_interrupt.cc
 )
\ No newline at end of file
diff --git a/app/system/test_dispatch_complex.cc b/app/system/test_dispatch_complex.cc
index 6495fec2..77753aea 100644
--- a/app/system/test_dispatch_complex.cc
+++ b/app/system/test_dispatch_complex.cc
@@ -18,21 +18,30 @@ DeclareTask(T2);
 DeclareTask(T3);
 
 DeclareEvent(E1);
+DeclareEvent(E2);
 
 TEST_MAKE_OS_MAIN(StartOS(0));
 
 TASK(T1) {
     ActivateTask(T3);
 
+    for (int i = 0; i < 5; i++) {
+        kout << "T1 triggers E2" << endl;
+        SetEvent(T2, E2);
+    }
 
+    kout << "T1 finished execution" << endl;
     TerminateTask();
 }
 
 TASK(T2) {
     for (int i = 0; i < 5; i++) {
-        kout << "T2 triggers E1 "  << endl;
+        kout << "T2 triggers E1" << endl;
+        WaitEvent(E2);
+        ClearEvent(E2);
         SetEvent(T3, E1);
     }
+    kout << "T2 finished execution" << endl;
     TerminateTask();
 }
 
@@ -46,6 +55,7 @@ TASK(T3) {
         WaitEvent(E1);
         ClearEvent(E1);
     }
+    kout << "T3 finished execution" << endl;
 
     TerminateTask();
 }
diff --git a/app/system/test_dispatch_complex.oil b/app/system/test_dispatch_complex.oil
index 575f29b8..84167774 100644
--- a/app/system/test_dispatch_complex.oil
+++ b/app/system/test_dispatch_complex.oil
@@ -20,6 +20,7 @@ CPU TestSystem {
         PRIORITY     = 2;
         ACTIVATION   = 1;
         AUTOSTART    = FALSE;
+        EVENT        = E2;
     };
 
     TASK T3 {
@@ -34,5 +35,9 @@ CPU TestSystem {
         MASK = AUTO;
     };
 
+    EVENT E2 {
+        MASK = AUTO;
+    };
+
 };
 
diff --git a/app/system/test_interrupt.cc b/app/system/test_interrupt.cc
new file mode 100644
index 00000000..ec4ce23d
--- /dev/null
+++ b/app/system/test_interrupt.cc
@@ -0,0 +1,76 @@
+/**
+ * @defgroup apps Applications
+ * @brief The applications...
+ */
+
+/**
+ * @file
+ * @ingroup apps
+ * @brief Just a simple test application
+ */
+#include <arch/armv7/gpio.h>
+#include <arch/armv7/syscall.h>
+#include "os.h"
+#include "test/test.h"
+#include "machine.h"
+#include "os/timing.h"
+
+DeclareTask(T1);
+DeclareTask(T2);
+
+DeclareEvent(E1);
+
+TEST_MAKE_OS_MAIN(StartOS(0));
+
+
+volatile int val1;
+volatile int val2;
+
+#define PORT0_BASE 0x48028100UL
+
+GPIO_Port gpioPort;
+
+int button_count = 0;
+
+extern "C" void configure_gpio_irq() {
+    // enable irqs on button 2 of the xmc4500 board
+    gpioPort.init(reinterpret_cast<void *>(PORT0_BASE), 15, true);
+    gpioPort.enable_input_irq(15);
+}
+
+TASK(T1) {
+    arch::syscall(configure_gpio_irq);
+    kout << "GPIO init successfull" << endl;
+
+    ActivateTask(T2);
+    while (true) {
+        WaitEvent(E1);
+        ClearEvent(E1);
+        kout << "Event processed: " << ++button_count << endl;
+    }
+
+
+    TerminateTask();
+
+}
+
+
+ISR2(ISR1) {
+    kout << "isr running" << endl;
+    SetEvent(T1, E1);
+}
+
+
+TASK(T2) {
+    while (true) {
+
+    }
+    TerminateTask();
+}
+
+
+void PreIdleHook() {
+    /* Dump and Shutdown */
+    timing_dump();
+    ShutdownMachine();
+}
diff --git a/app/system/test_interrupt.oil b/app/system/test_interrupt.oil
new file mode 100644
index 00000000..41f19e76
--- /dev/null
+++ b/app/system/test_interrupt.oil
@@ -0,0 +1,36 @@
+CPU TestSystem {
+    OS TestSystem {
+        STATUS       = STANDARD;
+        ERRORHOOK    = FALSE;
+        STARTUPHOOK  = FALSE;
+        SHUTDOWNHOOK = FALSE;
+        PRETASKHOOK  = FALSE;
+        POSTTASKHOOK = FALSE;
+    };
+
+    TASK T1 {
+        SCHEDULE     = FULL;
+        PRIORITY     = 4;
+        ACTIVATION   = 1;
+        AUTOSTART    = TRUE;
+        EVENT        = E1;
+    };
+
+    TASK T2 {
+        SCHEDULE     = FULL;
+        PRIORITY     = 3;
+        ACTIVATION   = 1;
+        AUTOSTART    = FALSE;
+    };
+
+	ISR ISR1 {
+		CATEGORY = 2;
+		DEVICE = 5;
+        PRIORITY = 1337;
+	};
+
+    EVENT E1 {
+        MASK = AUTO;
+    };
+};
+
diff --git a/arch/armv7/dispatch.cc b/arch/armv7/dispatch.cc
index 5513394c..23e12381 100644
--- a/arch/armv7/dispatch.cc
+++ b/arch/armv7/dispatch.cc
@@ -33,7 +33,7 @@ namespace arch {
         // save context
         asm volatile (
                 "mrs       r0, msp               \n" // store the msp in r0
-                "mrs       r1, psp               \n" // store the psp in r0
+                "mrs       r1, psp               \n" // store the psp in r1
                 "cmp       r1, #0                \n" // check if the psp is 0
                 "itt       ne                    \n" // next 2 lines are conditional executed
                 "mrsne     r12, psp              \n" // move program stack pointer to r12
diff --git a/arch/armv7/gpio.h b/arch/armv7/gpio.h
index b075d9fb..9758d775 100644
--- a/arch/armv7/gpio.h
+++ b/arch/armv7/gpio.h
@@ -8,11 +8,17 @@
 #include <stdint.h>
 
 class GPIO_Port {
+    void* m_port;
+public:
+    void init(void *port, uint8_t pin, bool input);
 
-    virtual void init(uint8_t pin) = 0;
-    virtual void setHigh(uint8_t pin)= 0;
-    virtual void setLow(uint8_t pin)= 0;
-    virtual void toggle(uint8_t pin)= 0;
+    void setHigh(uint8_t pin);
+
+    void setLow(uint8_t pin);
+
+    void toggle(uint8_t pin);
+
+    void enable_input_irq(uint8_t pin);
 };
 
 
diff --git a/arch/armv7/platforms/xmc4500/CMakeLists.txt b/arch/armv7/platforms/xmc4500/CMakeLists.txt
index 9a8823a3..c46a520b 100644
--- a/arch/armv7/platforms/xmc4500/CMakeLists.txt
+++ b/arch/armv7/platforms/xmc4500/CMakeLists.txt
@@ -43,6 +43,8 @@ set(SRCS ${SRCS}
     ${CMAKE_CURRENT_SOURCE_DIR}/gpio_xmc4500.cc
     ${CMAKE_CURRENT_SOURCE_DIR}/libs/CMSIS/Infineon/XMC4500_series/Source/system_XMC4500.c
     ${CMAKE_CURRENT_SOURCE_DIR}/libs/XMCLib/src/xmc4_gpio.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/libs/XMCLib/src/xmc4_eru.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/libs/XMCLib/src/xmc_eru.c
     ${CMAKE_CURRENT_SOURCE_DIR}/libs/XMCLib/src/xmc4_scu.c
     ${CMAKE_CURRENT_SOURCE_DIR}/libs/XMCLib/src/xmc_usbd.c
     ${LIB_USB_CDC}
diff --git a/arch/armv7/platforms/xmc4500/boot.cc b/arch/armv7/platforms/xmc4500/boot.cc
index fd324872..cd1a55fb 100644
--- a/arch/armv7/platforms/xmc4500/boot.cc
+++ b/arch/armv7/platforms/xmc4500/boot.cc
@@ -1,5 +1,5 @@
 #include <arch/arm/output.h>
-#include <arch/armv7/platforms/xmc4500/gpio_xmc4500.h>
+#include <arch/armv7/gpio.h>
 #include <arch/armv7/machine.h>
 #include "XMC4500.h"
 #include "stddef.h"
diff --git a/arch/armv7/platforms/xmc4500/gpio_xmc4500.cc b/arch/armv7/platforms/xmc4500/gpio_xmc4500.cc
index c8b86b84..2d6020f0 100644
--- a/arch/armv7/platforms/xmc4500/gpio_xmc4500.cc
+++ b/arch/armv7/platforms/xmc4500/gpio_xmc4500.cc
@@ -2,60 +2,106 @@
 // Created by fabian on 05.01.18.
 //
 
-#include "gpio_xmc4500.h"
+#include <platform.h>
+#include <arch/armv7/output.h>
+#include <arch/armv7/gpio.h>
+#include <arch/armv7/platforms/xmc4500/libs/XMCLib/inc/xmc_gpio.h>
+#include <arch/armv7/platforms/xmc4500/libs/XMCLib/inc/xmc4_gpio.h>
+#include <arch/armv7/platforms/xmc4500/libs/XMCLib/inc/xmc_eru.h>
 
 #define PORT_IOCR_PC_Size                (8U)
 #define PORT_PDR_Size             (4U)
 
-XMC4500_GPIO_Port::XMC4500_GPIO_Port(XMC_GPIO_PORT_t *const port) : m_port(port) {
+#define PORT (static_cast<XMC_GPIO_PORT_t *const>(this->m_port))
 
-}
-
-void XMC4500_GPIO_Port::init(uint8_t pin) {
-
-    /* Switch to input */
-    this->m_port->IOCR[pin >> 2U] &= (uint32_t) ~(PORT0_IOCR0_PC0_Msk << (PORT_IOCR_PC_Size * (pin & 0x3U)));
-
-    /* HW port control is disabled */
-    this->m_port->HWSEL &= ~(uint32_t) ((uint32_t) PORT0_HWSEL_HW0_Msk << ((uint32_t) pin << 1U));
+XMC_GPIO_MODE_t m_outputMode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL;
+XMC_GPIO_OUTPUT_STRENGTH_t m_outputStrength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
 
+void GPIO_Port::init(void *port, uint8_t pin, bool input) {
+    this->m_port = port;
+    if (!input) {
+        /* Switch to input */
+        PORT->IOCR[pin >> 2U] &= (uint32_t) ~(PORT0_IOCR0_PC0_Msk << (PORT_IOCR_PC_Size * (pin & 0x3U)));
 
+        /* HW port control is disabled */
+        PORT->HWSEL &= ~(uint32_t) ((uint32_t) PORT0_HWSEL_HW0_Msk << ((uint32_t) pin << 1U));
 
-    /* Set output level */
-    this->m_port->OMR = (uint32_t) XMC_GPIO_OUTPUT_LEVEL_LOW << pin;
 
-    /* Set output driver strength */
-    this->m_port->PDR[pin >> 3U] &= (uint32_t) ~(PORT0_PDR0_PD0_Msk
-            << ((uint32_t) PORT_PDR_Size * ((uint32_t) pin & 0x7U)));
-    this->m_port->PDR[pin >> 3U] |=
-            (uint32_t) this->m_outputStrength << ((uint32_t) PORT_PDR_Size * ((uint32_t) pin & 0x7U));
+        /* Set output level */
+        PORT->OMR = (uint32_t) XMC_GPIO_OUTPUT_LEVEL_LOW << pin;
 
+        /* Set output driver strength */
+        PORT->PDR[pin >> 3U] &= (uint32_t) ~(PORT0_PDR0_PD0_Msk
+                << ((uint32_t) PORT_PDR_Size * ((uint32_t) pin & 0x7U)));
+        PORT->PDR[pin >> 3U] |=
+                (uint32_t) m_outputStrength << ((uint32_t) PORT_PDR_Size * ((uint32_t) pin & 0x7U));
 
-    /* Set mode */
-    this->m_port->IOCR[pin >> 2U] |=
-            (uint32_t) this->m_outputMode << ((uint32_t) PORT_IOCR_PC_Size * ((uint32_t) pin & 0x3U));
 
+        /* Set mode */
+        PORT->IOCR[pin >> 2U] |=
+                (uint32_t) m_outputMode << ((uint32_t) PORT_IOCR_PC_Size * ((uint32_t) pin & 0x3U));
+    }
 }
 
-void XMC4500_GPIO_Port::setOuput(uint8_t pin, XMC_GPIO_OUTPUT_LEVEL_t level) {
-    this->m_port->OMR = (uint32_t) level << pin;
+void GPIO_Port::setHigh(uint8_t pin) {
+    PORT->OMR = (uint32_t) XMC_GPIO_OUTPUT_LEVEL_HIGH << pin;
 }
 
-void XMC4500_GPIO_Port::setHigh(uint8_t pin) {
-    setOuput(pin, XMC_GPIO_OUTPUT_LEVEL_HIGH);
+void GPIO_Port::setLow(uint8_t pin) {
+    PORT->OMR = (uint32_t) XMC_GPIO_OUTPUT_LEVEL_LOW << pin;
 }
 
-void XMC4500_GPIO_Port::setLow(uint8_t pin) {
-    setOuput(pin, XMC_GPIO_OUTPUT_LEVEL_LOW);
+void GPIO_Port::toggle(uint8_t pin) {
+    PORT->OMR = 0x10001U << pin;
 }
 
-void XMC4500_GPIO_Port::toggle(uint8_t pin) {
-    this->m_port->OMR = 0x10001U << pin;
+void GPIO_Port::enable_input_irq(uint8_t pin) {
+
+    if (this->m_port == reinterpret_cast<XMC_GPIO_PORT_t *const>(PORT1_BASE)) {
+        // Ereignis-Quelle konfigurieren
+        XMC_ERU_ETL_CONFIG_t eruInit;
+        // Initialisierungsstruktur aufräumen
+        memset(&eruInit, 0, sizeof(XMC_ERU_ETL_CONFIG_t));
+
+        // Eingabekanal und PIN laut Matrix festlegen
+       if(pin == 15) {
+           eruInit.input_a = ERU1_ETL1_INPUTA_P1_15;
+       }else{
+           kout << "i don't know how to enable interrupts on this pin" << endl;
+       }
+
+        // Triggerlogik festlegen
+        eruInit.edge_detection = XMC_ERU_ETL_EDGE_DETECTION_FALLING;
+        // Triggerausgabe erlauben
+        eruInit.enable_output_trigger = true;
+        // Triggerausgabe-Ziel festlegen
+        eruInit.output_trigger_channel = XMC_ERU_ETL_OUTPUT_TRIGGER_CHANNEL0;
+
+        // Ereignis Ziel konfigurieren
+        XMC_ERU_OGU_CONFIG_t oguInit;
+        // Initialisierungsstruktur aufräumen
+        memset(&oguInit, 0, sizeof(XMC_ERU_OGU_CONFIG_t));
+        // Interrupt erlauben
+        oguInit.service_request = true;
+
+        // ERU Eingangsseite Konfigurieren
+        XMC_ERU_ETL_Init(ERU1_ETL1, &eruInit);
+        // ERU Ausgangsseite Konfigurieren
+        XMC_ERU_OGU_Init(ERU1_OGU0, &oguInit);
+
+        NVIC_SetPriority(ERU1_0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 63, 0));
+
+        NVIC_EnableIRQ(ERU1_0_IRQn);
+
+        PORT1_BASE;
+    } else {
+        kout << "i don't know how to enable this interrupt" << endl;
+    }
 }
 
 //
 //XMC4500_GPIO_Port GPIO_PORT0((XMC_GPIO_PORT_t *) PORT0_BASE);
-XMC4500_GPIO_Port GPIO_PORT1((XMC_GPIO_PORT_t *) PORT1_BASE);
+// GPIO_Port GPIO_PORT1;
 //XMC4500_GPIO_Port GPIO_PORT2((XMC_GPIO_PORT_t *) PORT2_BASE);
 //XMC4500_GPIO_Port GPIO_PORT3((XMC_GPIO_PORT_t *) PORT3_BASE);
 //XMC4500_GPIO_Port GPIO_PORT4((XMC_GPIO_PORT_t *) PORT4_BASE);
diff --git a/arch/armv7/platforms/xmc4500/gpio_xmc4500.h b/arch/armv7/platforms/xmc4500/gpio_xmc4500.h
deleted file mode 100644
index fe65c91a..00000000
--- a/arch/armv7/platforms/xmc4500/gpio_xmc4500.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Created by fabian on 05.01.18.
-//
-
-#ifndef DOSEK_GPIO_XMC4500_H
-#define DOSEK_GPIO_XMC4500_H
-
-#include <platform.h>
-#include <xmc_common.h>
-#include <xmc_gpio.h>
-#include <arch/armv7/gpio.h>
-
-class XMC4500_GPIO_Port : public GPIO_Port {
-private:
-    XMC_GPIO_MODE_t m_outputMode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL;
-    XMC_GPIO_OUTPUT_STRENGTH_t m_outputStrength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
-
-    XMC_GPIO_PORT_t *const m_port;
-    void setOuput(uint8_t pin, XMC_GPIO_OUTPUT_LEVEL_t level);
-
-public:
-    explicit XMC4500_GPIO_Port(XMC_GPIO_PORT_t *const m_port);
-
-    void init(uint8_t pin) override;
-
-    void setHigh(uint8_t pin) override;
-
-    void setLow(uint8_t pin) override;
-
-    void toggle(uint8_t pin) override;
-
-};
-//
-//extern XMC4500_GPIO_Port GPIO_PORT0;
-extern XMC4500_GPIO_Port GPIO_PORT1;
-//extern XMC4500_GPIO_Port GPIO_PORT2;
-//extern XMC4500_GPIO_Port GPIO_PORT3;
-//extern XMC4500_GPIO_Port GPIO_PORT4;
-//extern XMC4500_GPIO_Port GPIO_PORT5;
-//extern XMC4500_GPIO_Port GPIO_PORT6;
-
-#endif //DOSEK_GPIO_H_H
diff --git a/arch/armv7/platforms/xmc4500/machine_impl.cc b/arch/armv7/platforms/xmc4500/machine_impl.cc
index 1a2396c7..939f82e1 100644
--- a/arch/armv7/platforms/xmc4500/machine_impl.cc
+++ b/arch/armv7/platforms/xmc4500/machine_impl.cc
@@ -3,19 +3,10 @@
 
 #include "nvic.h"
 #include "machine.h"
-#include "gpio_xmc4500.h"
 
 
 void Machine::reset(void) {
     kout << "Reset called" << endl;
-
-    // Flash light before reset
-    GPIO_PORT1.init(0);
-    GPIO_PORT1.setHigh(0);
-    for(volatile int i = 0; i < 1000000; ++i);
-    GPIO_PORT1.setLow(0);
-    for(volatile int i = 0; i < 1000000; ++i);
-
     NVIC_SystemReset();
 }
 
-- 
GitLab