LuatOS ESP32C3 > strongswan MEDTH和ESP定时器

1.strongswan:MEDTH宏

#ifdef __cplusplus
    #define TEMPORARY decltype
#else
    #define TEMPORARY __typeof__
#endif

/**
 * Method declaration/definition macro, providing private and public interface.
 *
 * Defines a method name with this as first parameter and a return value ret,
 * and an alias for this method with a _ prefix, having the this argument
 * safely casted to the public interface iface.
 * _name is provided a function pointer, but will get optimized out by GCC.
 */
#define METHOD(iface, name, ret, this, ...)                    \
                                                               \
    static ret name(                                           \
        union {iface *_public; this; }                         \
        __attribute__((transparent_union)),                    \
        ##__VA_ARGS__);                                        \
                                                               \
    static TEMPORARY(name) *_##name = (TEMPORARY(name) *)name; \
                                                               \
    static ret name(this, ##__VA_ARGS__)

其中关于 typeof 和 METHOD 自行搜索学习

这里带入扩展一下

#define METHOD(iface, name, ret, this, ...)

METHOD(blink2_public_t, run, void, blink2_private_t *self, const int tick)

//

// 将私有和公共联合
static void run(
    union {blink2_public_t *_public; self;}
    __attribute__((transparent_union)), // 关键
    ##__VA_ARGS__);

// 该联合类型的函数指针,调用时用这个,##是连接符,_##name => _run
static __typeof__(run) *_##name = (__typeof__(name) *)name;

// 函数体
static void run(self, ##__VA_ARGS__)
{

}

2.使用

blink.h

#ifndef BLINK2_H
#define BLINK2_H

#ifdef __cplusplus
    #define TEMPORARY decltype
#else
    #define TEMPORARY __typeof__
#endif

/**
 * Method declaration/definition macro, providing private and public interface.
 *
 * Defines a method name with this as first parameter and a return value ret,
 * and an alias for this method with a _ prefix, having the this argument
 * safely casted to the public interface iface.
 * _name is provided a function pointer, but will get optimized out by GCC.
 */
#define METHOD(iface, name, ret, this, ...)                    \
                                                               \
    static ret name(                                           \
        union {iface *_public; this; }                         \
        __attribute__((transparent_union)),                    \
        ##__VA_ARGS__);                                        \
                                                               \
    static TEMPORARY(name) *_##name = (TEMPORARY(name) *)name; \
                                                               \
    static ret name(this, ##__VA_ARGS__)

typedef struct blink2_public blink2_public_t;
struct blink2_public {
    void (*run)(blink2_public_t *self, const int tick);
};

blink2_public_t *blink2_create(void (*hw_init)(void), 
                               void (*on)(void), 
                               void (*off)(void), 
                               const int on_time, 
                               const int off_time);

#endif

 blink.c

#include <stdio.h>
#include "blink2.h"

typedef struct blink2_private blink2_private_t;
struct blink2_private {
    blink2_public_t pub;

    int on_time;
    int off_time;
    int tick;
    int tick_count;

    void (*on)(void);
    void (*off)(void);
};

METHOD(blink2_public_t, run, void, blink2_private_t *self, const int tick)
{
    if (self->tick != tick) {
        self->tick = tick;
        self->tick_count++;
    }

    if (self->tick_count < self->on_time) {
        self->on();
    } else if (self->tick_count < (self->on_time + self->off_time)) {
        self->off();
    } else {
        self->tick_count = 0;
    }
}

blink2_public_t *blink2_create(void (*hw_init)(void), 
                               void (*on)(void), 
                               void (*off)(void), 
                               const int on_time, 
                               const int off_time)
{
    assert(hw_init);
    assert(on);
    assert(off);

    blink2_private_t *priv = malloc(sizeof(blink2_private_t));
    assert(priv);

    priv->on_time = on_time;
    priv->off_time = off_time;
    priv->on = on;
    priv->off = off;

    priv->pub.run = _run;

    hw_init();

    return &(priv->pub);
}

main.c

#include <stdio.h>
#include "driver/gpio.h"
#include "esp_timer.h"
#include "blink.h"
#include "blink2.h"

#define D4_PIN GPIO_NUM_12
#define D5_PIN GPIO_NUM_13

blink2_public_t *blink2;

void blink2_hw_init(void)
{
    gpio_reset_pin(D5_PIN);
    gpio_set_direction(D5_PIN, GPIO_MODE_OUTPUT);
}

void blink2_on(void)
{
    gpio_set_level(D5_PIN, 1);
}

void blink2_off(void)
{
    gpio_set_level(D5_PIN, 0);
}

static void periodic_timer_callback(void* arg);

void app_main(void)
{
    blink_init(D4_PIN);

    blink2 = blink2_create(blink2_hw_init, blink2_on, blink2_off, 500, 500);

    const esp_timer_create_args_t periodic_timer_args = {
            .callback = &periodic_timer_callback,
            .name = "periodic"
    };
    esp_timer_handle_t periodic_timer;
    ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 1000)); // 1000us

    while (1) {
        blink(D4_PIN);
    }
}

static void periodic_timer_callback(void* arg)
{
    int64_t time_since_boot = esp_timer_get_time();
    blink2->run(blink2, time_since_boot);
}

- 这么做是想 blink2 实现公私分离,缺点就是 debug 时(在 keil 中)没法直接查看私有部分。

其中esp的定时器参考:高分辨率定时器(ESP 定时器) - ESP32-C3 - — ESP-IDF 编程指南 latest 文档 (espressif.com)icon-default.png?t=N7T8https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32c3/api-reference/system/esp_timer.htmlesp的定时器github:esp-idf/examples/system/esp_timer/main/esp_timer_example_main.c at b3f7e2c8a4d354df8ef8558ea7caddc07283a57b · espressif/esp-idf · GitHub

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值