NuMaker tickless example

Committer:
cyliang
Date:
Wed Mar 01 03:53:04 2023 +0000
Revision:
25:51d3dccddd8b
Parent:
16:ed2c228cbc9c
Update os v6.17.0 for M467 target

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 1:eb1da9d36e12 1 #include "mbed.h"
ccli8 1:eb1da9d36e12 2 #include "wakeup.h"
ccli8 1:eb1da9d36e12 3 #include "PeripheralPins.h"
ccli8 1:eb1da9d36e12 4
ccli8 1:eb1da9d36e12 5 #define I2C_ADDR (0x90)
ccli8 1:eb1da9d36e12 6
ccli8 1:eb1da9d36e12 7 #if defined(TARGET_NUMAKER_PFM_NUC472)
ccli8 1:eb1da9d36e12 8 // I2C
ccli8 1:eb1da9d36e12 9 #define I2C_SDA D14
ccli8 1:eb1da9d36e12 10 #define I2C_SCL D15
ccli8 1:eb1da9d36e12 11
ccli8 1:eb1da9d36e12 12 #elif defined(TARGET_NUMAKER_PFM_M453)
ccli8 1:eb1da9d36e12 13 // I2C
ccli8 1:eb1da9d36e12 14 #define I2C_SDA D14
ccli8 1:eb1da9d36e12 15 #define I2C_SCL D15
ccli8 1:eb1da9d36e12 16
ccli8 1:eb1da9d36e12 17 #elif defined(TARGET_NUMAKER_PFM_M487)
ccli8 1:eb1da9d36e12 18 // I2C
ccli8 1:eb1da9d36e12 19 #define I2C_SDA D9
ccli8 1:eb1da9d36e12 20 #define I2C_SCL D8
ccli8 1:eb1da9d36e12 21
ccli8 10:d2e2c79389e1 22 #elif defined(TARGET_NUMAKER_PFM_NANO130)
ccli8 10:d2e2c79389e1 23 // I2C
ccli8 10:d2e2c79389e1 24 #define I2C_SDA D14
ccli8 10:d2e2c79389e1 25 #define I2C_SCL D15
ccli8 10:d2e2c79389e1 26
ccli8 1:eb1da9d36e12 27 #endif
ccli8 1:eb1da9d36e12 28
ccli8 1:eb1da9d36e12 29 /* NOTE: Per test (on NUC472/M453/M487), we could handle in time from idle mode (shallow sleep) wake-up,
ccli8 1:eb1da9d36e12 30 * but fail from power-down mode (deep sleep). */
ccli8 1:eb1da9d36e12 31
ccli8 1:eb1da9d36e12 32 /* Support wake-up by I2C traffic */
ccli8 1:eb1da9d36e12 33 static Semaphore sem_i2c(0, 1);
ccli8 1:eb1da9d36e12 34
ccli8 1:eb1da9d36e12 35 static void poll_i2c(void);
ccli8 1:eb1da9d36e12 36 /* This handler is to be called in I2C interrupt context (which is extended by Nuvoton's I2C HAL implementation
ccli8 1:eb1da9d36e12 37 * on mbed OS) to support wake-up by I2C traffic. */
ccli8 1:eb1da9d36e12 38 extern "C" void nu_i2c_wakeup_handler(I2C_T *i2c_base);
ccli8 1:eb1da9d36e12 39
ccli8 1:eb1da9d36e12 40 void config_i2c_wakeup(void)
ccli8 1:eb1da9d36e12 41 {
ccli8 1:eb1da9d36e12 42 /* I2C engine is clocked by external I2C bus clock, so its support for wake-up is irrespective of HXT/HIRC
ccli8 1:eb1da9d36e12 43 * which are disabled during deep sleep (power-down). */
ccli8 1:eb1da9d36e12 44
ccli8 1:eb1da9d36e12 45 static Thread thread_i2c;
ccli8 1:eb1da9d36e12 46
ccli8 1:eb1da9d36e12 47 Callback<void()> callback(&poll_i2c);
ccli8 1:eb1da9d36e12 48 thread_i2c.start(callback);
ccli8 1:eb1da9d36e12 49 }
ccli8 1:eb1da9d36e12 50
ccli8 1:eb1da9d36e12 51 static void poll_i2c(void)
ccli8 1:eb1da9d36e12 52 {
ccli8 1:eb1da9d36e12 53 static I2CSlave i2c_slave(I2C_SDA, I2C_SCL);
ccli8 1:eb1da9d36e12 54
ccli8 1:eb1da9d36e12 55 static char i2c_buf[32];
ccli8 1:eb1da9d36e12 56
ccli8 1:eb1da9d36e12 57 i2c_slave.address(I2C_ADDR);
ccli8 1:eb1da9d36e12 58
ccli8 1:eb1da9d36e12 59 while (true) {
ccli8 16:ed2c228cbc9c 60 sem_i2c.acquire();
ccli8 16:ed2c228cbc9c 61
ccli8 1:eb1da9d36e12 62 bool has_notified_wakeup = false;
ccli8 1:eb1da9d36e12 63 /* This timer is to check if there is I2C traffic remaining. */
ccli8 1:eb1da9d36e12 64 Timer timer;
ccli8 1:eb1da9d36e12 65 timer.start();
ccli8 1:eb1da9d36e12 66
ccli8 1:eb1da9d36e12 67 /* With no I2C traffic for 5 ms, we go back to wait on next I2C traffic. */
ccli8 1:eb1da9d36e12 68 while (timer.read_high_resolution_us() < 5000) {
ccli8 1:eb1da9d36e12 69 /* We shall call I2CSlave::receive to enable I2C interrupt again which may be disabled in handling
ccli8 1:eb1da9d36e12 70 * I2C interrupt in Nuvoton's I2C HAL implementation on mbed OS. */
ccli8 1:eb1da9d36e12 71 int addr_status = i2c_slave.receive();
ccli8 1:eb1da9d36e12 72 switch (addr_status) {
ccli8 1:eb1da9d36e12 73 case I2CSlave::ReadAddressed:
ccli8 1:eb1da9d36e12 74 if (! has_notified_wakeup) {
ccli8 1:eb1da9d36e12 75 has_notified_wakeup = true;
ccli8 1:eb1da9d36e12 76 wakeup_eventflags.set(EventFlag_Wakeup_I2C_AddrMatch);
ccli8 1:eb1da9d36e12 77 }
ccli8 1:eb1da9d36e12 78 i2c_slave.write(i2c_buf, sizeof (i2c_buf));
ccli8 1:eb1da9d36e12 79 timer.reset();
ccli8 1:eb1da9d36e12 80 break;
ccli8 1:eb1da9d36e12 81
ccli8 1:eb1da9d36e12 82 case I2CSlave::WriteAddressed:
ccli8 1:eb1da9d36e12 83 if (! has_notified_wakeup) {
ccli8 1:eb1da9d36e12 84 has_notified_wakeup = true;
ccli8 1:eb1da9d36e12 85 wakeup_eventflags.set(EventFlag_Wakeup_I2C_AddrMatch);
ccli8 1:eb1da9d36e12 86 }
ccli8 1:eb1da9d36e12 87 i2c_slave.read(i2c_buf, sizeof (i2c_buf));
ccli8 1:eb1da9d36e12 88 timer.reset();
ccli8 1:eb1da9d36e12 89 break;
ccli8 1:eb1da9d36e12 90 }
ccli8 1:eb1da9d36e12 91 }
ccli8 1:eb1da9d36e12 92 }
ccli8 1:eb1da9d36e12 93 }
ccli8 1:eb1da9d36e12 94
ccli8 1:eb1da9d36e12 95 void nu_i2c_wakeup_handler(I2C_T *i2c_base)
ccli8 1:eb1da9d36e12 96 {
ccli8 1:eb1da9d36e12 97 (void) i2c_base;
ccli8 16:ed2c228cbc9c 98
ccli8 16:ed2c228cbc9c 99 /* FIXME: Clear wake-up event to enable re-entering Power-down mode */
ccli8 16:ed2c228cbc9c 100
ccli8 1:eb1da9d36e12 101 sem_i2c.release();
ccli8 1:eb1da9d36e12 102 }