硬汉嵌入式论坛

 找回密码
 立即注册
查看: 421|回复: 8
收起左侧

2025年总结与感悟。给我最大感触的还是AI。

[复制链接]

111

主题

613

回帖

961

积分

金牌会员

积分
961
QQ
发表于 2026-1-1 10:06:48 | 显示全部楼层 |阅读模式
早上一起床,家庭微信群中外公分享了一个视频号链接,标题和作者就是一股浓浓的营销号风格——"唱出了50,60,70后的心声#正能量",作者:“人生品不透的茶8072”。看来是瞄准老年人作为目标群体啊。

点进去是一个AI生成的老奶奶在唱歌,歌词大概为:“记得小时候,晚上点灯都用油。犁耙耕地都是牛,上学放学自己走。”

评论区大概是这样一个状况。

ID:“感悟”(头像荷花):唱的就是我啊。👍👍👍

ID:“平安吉祥”(头像为中老年妇女):这首歌唱的非常真实全是大突话





看着这个AI视频,听着AI歌曲,我脑海里回血起5年前看过一本小说——《这不是娱乐》,作者是“睡觉会变白”。上架于2021年6月1日,是都市类型的。

image-20260101085646930.png

这本书是一本比较有意思的娱乐文。它讲述了在未来世界里,娱乐业的消亡——真人演员被AI生成的虚拟人所代替。

这个故事当然可以写的很长,虚拟人是怎么慢慢替代真人的?这个过程中又会发生哪些波澜壮阔的冲突?

但是作者没有这样子处理,这是他宣泄情绪之作,他只用了60W字,故事在刚要展开的时候就戛然而止。

在后记中白白写道:
娱乐文本质上就是怀旧,原创作品的除外。



怀旧的东西我在《1983》里写的太多,不想重复。

而且写完《1983》后,我发现自己越来越有书里提到的那种:信息茧房、人为的把心态变老、排斥新生事物等等。

这样很不好,所以便有了这本书。

老读者都能感受到,本书的节奏飞快,字数不多,信息量巨大,因为就没打算写太长。

主线是干翻娱乐圈,干完了就该完本,没必要再水。重建不重建的,意义不大,就那点破事儿。

女主没怎么写,因为舍弃了日常内容。叠楼的作用在书里也提过,一块精神自留地,顺便跟现世有一个参照。

其次,我也不否认成绩因素。

订阅太烂了,不仅没有增长,反而越来越少。大部分人还是习惯传统套路的娱乐文,我这种的太偏门。

所以能陪到最后的朋友们,由衷感谢了。

娱乐文呢,过去那点事已经写完了,现在和未来也写完了,对我个人而言,娱乐文没什么好写的了。

下本书应该会隔很久,我得集中精力相亲,解决我的终身大事,毕竟也老大不小的了。

就这样吧。





一曲终了,我划拉了一下手机,退出了视频。

我知道小说里描绘的那个情况,就快要发生了。

不仅仅是老年人爱看AI视频,年轻人也爱看。

B站的BV号为`BV19n4y1f7Dh`



包括还有AI歌曲。

从前的伊丽莎白鼠(B站up主),那都是古法鬼畜。

现在新的丁曲,那都是活字印刷术。


最后还有AI编程。以前那都是古法手工编程。
前面几年AI只能写一些小模块。
今年AI给我带来了真得完全不一样的体验。

在2025年的最后一个月,我尝试了vibe coding。

基本上这个月来我的代码全部由AI生成。古法编程占比20%不到。剩下的都由AI来完成。
image-20260101094751525.png

它已经能够使用grep去搜索代码,自己理解需求,自己修改。
为此我写了一个python脚本,让mdk能够编译
image-20260101094950440.png

编译后的报错文件生成在build_log.txt
image-20260101095046748.png

根据这些消息,现在的AI已经能自己编译,自己修改代码了。

你只需要告诉它用`python fbtools.py build`可以编译代码。编译后的日志输出在哪个文档。
另外我特别喜欢AI写的注释,下面来展示一下AI帮我写的驱动,代码质量已经和我自己古法编程差不多,而且注释写的特别详细:
[C] 纯文本查看 复制代码
/*
 * Copyright (c) 2025 by Lu Xianfan.
 * @FilePath     : dev_uart.c
 * @Author       : lxf
 * @Date         : 2025-12-24 09:08:16
 * @LastEditors  : [email]lxf_zjnb@qq.com[/email]
 * @LastEditTime : 2025-12-29 15:26:26
 * @Brief        : UART设备驱动实现
 * @features     :
 *               - 非阻塞异步收发(基于HAL中断模式)
 *               - 乒乓缓冲区管理(支持连续收发)
 *               - RS485软件收发切换
 *               - IDLE中断接收(支持变长数据包)
 *               - 发送完成自动流控(支持队列发送)
 *               - 三种接收模式: 标准/零拷贝/流式 (互斥使用,自动冲突检测)
 *
 * @usage        :
 *               @code
 *               device_t *uart = device_open("usart2");
 *               if (!uart) {
 *                   return -1;
 *               }
 *
 *               // ========== 方式1: 标准模式(带拷贝,简单) ==========
 *               // 发送数据(非阻塞)
 *               uint8_t tx_buf[] = "Hello UART!";
 *               device_write(uart, tx_buf, 0, sizeof(tx_buf));
 *
 *               // 接收数据(非阻塞,自动释放缓冲区)
 *               uint8_t rx_buf[256];
 *               int32_t len = device_read(uart, rx_buf, 0, sizeof(rx_buf));
 *               if (len > 0) {
 *                   process_data(rx_buf, len);  // ✅ 无需调用 RX_DONE!
 *               }
 *
 *               // ========== 方式2: 零拷贝模式(高性能) ==========
 *               // 接收
 *               struct dev_uart_buf rx_buf;
 *               if (device_ioctl(uart, IOCTL_UART_GET_RX_BUF, &rx_buf) == E_OK) {
 *                   process_data(rx_buf.ptr, rx_buf.size);  // 直接使用数据
 *                   device_ioctl(uart, IOCTL_UART_RX_DONE, NULL);  // 释放缓冲区
 *               }
 *
 *               // 发送
 *               struct dev_uart_buf tx_buf;
 *               if (device_ioctl(uart, IOCTL_UART_GET_TX_BUF, &tx_buf) == E_OK) {
 *                   memcpy(tx_buf.ptr, my_data, my_len);  // 或直接配置 DMA
 *                   tx_msg->pos = my_len;  // 设置发送长度
 *                   device_ioctl(uart, IOCTL_UART_TX_DONE, NULL);  // 触发发送
 *               }
 *
 *               // ========== 方式3: 流式模式(协议栈适配,零拷贝) ==========
 *               // 逐字节读取,驱动层维护游标,跨包读取
 *               // 适用于 Modbus 等需要单字节接收的协议栈
 *               uint8_t byte;
 *               if (device_ioctl(uart, IOCTL_UART_GET_BYTE, &byte) == E_OK) {
 *                   // 成功读取一个字节
 *               }
 *
 *               device_close(uart);
 *               @endcode
 *
 * @warning  接收模式冲突检测 - 三种接收方式互斥,只能选择一种!
 *            混合使用会返回 E_BUSY / -1 错误。详见 dev_uart.h 文件头说明。
 *
 * @performance  :
 *               ┌─────────────────┬──────────────────┬─────────────────┐
 *               │     模式        │    拷贝次数      │    性能         │
 *               ├─────────────────┼──────────────────┼─────────────────┤
 *               │  标准模式(回显) │  2次(RX+TX各1次) │    一般         │
 *               │  零拷贝模式     │  1次(仅RX→TX)    │    优秀         │
 *               │  流式模式       │  0次(直接访问)   │    协议栈优化    │
 *               └─────────────────┴──────────────────┴─────────────────┘
 *
 *               标准模式: 数据流 硬件→rxpp→应用层→txpp→硬件 (2次memcpy)
 *               零拷贝模式: 数据流 硬件→rxpp→txpp→硬件 (1次memcpy)
 *               流式模式:   数据流 硬件→rxpp→协议栈 (0次memcpy,游标管理)
 *
 * @transmit_flow :
 *               device_write("ABC")
 *               └─> memcpy(拷贝到txpp乒乓缓冲) [第1次拷贝]
 *               └─> ptransmitter==NULL? 立即发送 : 排队等待
 *                   └─> HAL_UART_Transmit_IT("ABC")
 *                       └─> TC中断
 *                           └─> HAL_UART_TxCpltCallback()
 *                               └─> device_irq_process(TX_COMPLETE)
 *                                   └─> 释放缓冲区 + 启动下一次发送
 *
 * @receive_flow  :
 *               HAL_UARTEx_ReceiveToIdle_IT(启动接收)
 *               └─> 硬件接收数据到rxpp->pbuf
 *               └─> IDLE中断或缓冲区满
 *                   └─> HAL_UARTEx_RxEventCallback()
 *                       └─> device_irq_process(RX_COMPLETE)
 *                           └─> 切换乒乓缓冲区, 驱动层自动重启接收
 *                               └─> 应用层获取数据:
 *                                   ├─ 标准模式: device_read() memcpy到应用层 [第2次拷贝]
 *                                   ├─ 零拷贝模式: IOCTL_GET_RX_BUF 直接访问rxpp
 *                                   │           └─> device_ioctl(RX_DONE) 释放缓冲区
 *                                   └─ 流式模式: IOCTL_GET_BYTE 游标读取,跨包消费
 */

/*---------- includes ----------*/
#include "options.h"
#include "dev_uart.h"
#include "driver.h"
#include "device.h"
/*---------- macro ----------*/

/* 默认配置 */
#if !defined(CONFIG_UART_BUF_SIZE_RX)
#define CONFIG_UART_BUF_SIZE_RX 256
#endif

#if !defined(CONFIG_UART_BUF_SIZE_TX)
#define CONFIG_UART_BUF_SIZE_TX 256
#endif
/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
static fp_err_t _dev_uart_open(driver_t **pdrv);
static void _dev_uart_close(driver_t **pdrv);
static int32_t _dev_uart_write(driver_t **pdrv, void *buf, uint32_t addition, uint32_t len);
static int32_t _dev_uart_read(driver_t **pdrv, void *buf, uint32_t addition, uint32_t len);
static fp_err_t _dev_uart_ioctl(driver_t **pdrv, uint32_t cmd, void *args);
static fp_err_t _dev_uart_irq_handler(driver_t **pdrv, uint32_t irq_event, void *args, uint32_t length);

/* 内部辅助函数 - IOCTL 查表回调 */
static fp_err_t ioctl_get_rx_buf(struct dev_uart_describe *self, void *arg);
static fp_err_t ioctl_get_tx_buf(struct dev_uart_describe *self, void *arg);
static fp_err_t ioctl_rx_done(struct dev_uart_describe *self, void *arg);
static fp_err_t ioctl_tx_done(struct dev_uart_describe *self, void *arg);
static fp_err_t ioctl_get_byte(struct dev_uart_describe *self, void *arg);

/*---------- variable ----------*/
DRIVER_DEFINED(
    dev_uart, _dev_uart_open, _dev_uart_close, _dev_uart_write, _dev_uart_read, _dev_uart_ioctl, _dev_uart_irq_handler);

// clang-format off
static struct protocol_callback ioctl_cbs[] = {
    { IOCTL_UART_GET_RX_BUF, ioctl_get_rx_buf },
    { IOCTL_UART_GET_TX_BUF, ioctl_get_tx_buf },
    { IOCTL_UART_RX_DONE, ioctl_rx_done },
    { IOCTL_UART_TX_DONE, ioctl_tx_done },
    { IOCTL_UART_GET_BYTE, ioctl_get_byte },
};
// clang-format on

/*---------- function ----------*/

/**
 * @brief 打开UART设备,分配缓冲区并初始化硬件
 */
static fp_err_t _dev_uart_open(driver_t **pdrv)
{
    struct dev_uart_describe *pdesc = NULL;
    fp_err_t err = E_WRONG_ARGS;
    uint8_t *rxbuf = NULL, *txbuf = NULL;
    uint32_t rxwantsz = 0, txwantsz = 0;
    assert(pdrv != NULL);
    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;

    do {
        if (!pdesc) {
            break;
        }

        /* 如果未设置缓冲区大小 */
        if (pdesc->config.bufsz_rx == 0 || pdesc->config.bufsz_tx == 0) {
            break;
        }

        /* 1. 分配缓冲区 */
        err = E_NO_MEMORY;
        if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
            /* DMA模式:一次性分配两个 dev_uart_msg 结构体 */
            rxwantsz = (offsetof(struct dev_uart_msg, pbuf) + pdesc->config.bufsz_rx);
            txwantsz = (offsetof(struct dev_uart_msg, pbuf) + pdesc->config.bufsz_tx);
            rxbuf = malloc(rxwantsz * 2);
            txbuf = malloc(txwantsz * 2);
            if (!rxbuf || !txbuf) {
                free(rxbuf);
                free(txbuf);
                break;
            }

            /* 初始化乒乓缓冲,管理完整的 struct dev_uart_msg */
            pingpong_buffer_init(&pdesc->rxpp, rxbuf, rxbuf + rxwantsz);
            pingpong_buffer_init(&pdesc->txpp, txbuf, txbuf + txwantsz);
            /* preveiver 指向当前写入缓冲区 */
            pingpong_buffer_get_write_buf(&pdesc->rxpp, (void **)&pdesc->preveiver);
        }

        /* 5. 调用底层硬件初始化 */
        if (pdesc->ops && pdesc->ops->init) {
            if (pdesc->ops->init(pdesc, &pdesc->config) != E_OK) {
                err = E_ERROR;
                break;
            }
        }

        /* 6. 启动首次接收 */
        if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
            if (pdesc->ops && pdesc->ops->start_receive) {
                if (pdesc->ops->start_receive(pdesc, pdesc->preveiver->pbuf, pdesc->config.bufsz_rx) != E_OK) {
                    err = E_ERROR;
                    break;
                }
            }
        }

        err = E_OK;
    } while (0);

    /* 失败时释放已分配的资源 */
    if (err != E_OK) {
        if (txbuf) {
            free(txbuf);
        }
        if (rxbuf) {
            free(rxbuf);
        }
    }
    return err;
}

/**
 * @brief 关闭UART设备,释放资源
 */
static void _dev_uart_close(driver_t **pdrv)
{
    struct dev_uart_describe *pdesc = NULL;
    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;

    if (pdesc) {
        if (pdesc->ops->deinit) {
            pdesc->ops->deinit(pdesc);
        }
        /* 释放缓冲区 */
        if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
            free(pdesc->txpp.buffer[0]);
            free(pdesc->rxpp.buffer[0]);
        }
    }
}

/**
 * @brief 串口发送
 */
static int32_t _dev_uart_write(driver_t **pdrv, void *buf, uint32_t addition, uint32_t len)
{
    struct dev_uart_describe *pdesc = NULL;
    uint8_t *pdata = (uint8_t *)buf;
    uint32_t i;
    fp_err_t err = E_WRONG_ARGS;

    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;

    do {
        if (!pdesc || !buf || len == 0 || !pdesc->ops) {
            break;
        }

        if (len > pdesc->config.bufsz_tx) {
            break;
        }

        /* RS485模式:切换到发送 */
        if (pdesc->config.flags & DEV_UART_FLAG_SWRS485) {
            if (pdesc->ops->control) {
                pdesc->ops->control(pdesc, UART_CTRL_SET_RS485_TX, NULL);
            }
        }

        /* DEV_UART_FLAG_PKT_MODE: 拷贝到乒乓缓冲并触发发送 */
        if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
            struct dev_uart_msg *tx_msg = NULL;

            /* 1. 拷贝数据到发送缓冲区 */
            pingpong_buffer_get_write_buf(&pdesc->txpp, (void **)&tx_msg);
            if (tx_msg) {
                tx_msg->pos = len;
                memcpy(tx_msg->pbuf, buf, len);
                pingpong_buffer_set_write_done(&pdesc->txpp);

                /* 2. 如果发送空闲,立即启动发送 */
                if (pdesc->ptransmitter == NULL) {
                    pingpong_buffer_get_read_buf(&pdesc->txpp, (void **)&pdesc->ptransmitter);
                    if (pdesc->ptransmitter && pdesc->ops->start_transmit) {
                        pdesc->ops->start_transmit(pdesc, pdesc->ptransmitter->pbuf, pdesc->ptransmitter->pos);
                    }
                }
            }
        }
        err = E_OK;
    } while (0);

    return E_OK;
}

/**
 * @brief 从接收缓冲区读取数据(带拷贝模式)
 * @note  读取后自动释放缓冲区,无需调用 RX_DONE
 * @retval >0      读取的字节数
 * @retval 0       无数据
 * @retval -1      接收模式冲突(已使用其他接收模式)
 */
static int32_t _dev_uart_read(driver_t **pdrv, void *buf, uint32_t addition, uint32_t len)
{
    struct dev_uart_describe *pdesc = NULL;
    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;
    int32_t retval = 0;

    do {
        if (!pdesc || !buf) {
            break;
        }

        /* 检测接收模式冲突 */
        if (pdesc->config.rx_mode != UART_RX_MODE_NONE && pdesc->config.rx_mode != UART_RX_MODE_STANDARD) {
            retval = -1; /* 模式冲突 */
            break;
        }
        pdesc->config.rx_mode = UART_RX_MODE_STANDARD;

        /* PKT_MODE: 从乒乓缓冲区读取数据 */
        if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
            struct dev_uart_msg *read_msg = NULL;

            /* 尝试获取读取缓冲区 */
            if (pingpong_buffer_get_read_buf(&pdesc->rxpp, (void **)&read_msg)) {
                /* 计算实际拷贝长度 */
                uint32_t copy_len = (read_msg->pos < len) ? read_msg->pos : len;

                /* 拷贝数据到应用层缓冲区 */
                memcpy(buf, read_msg->pbuf, copy_len);
                retval = copy_len;

                /* 自动释放已读缓冲区,无需应用层调用 RX_DONE */
                pingpong_buffer_set_read_done(&pdesc->rxpp);
            }
        }

    } while (0);

    return retval;
}

/**
 * @brief IOCTL命令处理
 */
static fp_err_t _dev_uart_ioctl(driver_t **pdrv, uint32_t cmd, void *args)
{
    fp_err_t err = E_WRONG_ARGS;
    struct dev_uart_describe *pdesc = NULL;
    fp_err_t (*cb)(struct dev_uart_describe *, void *) = NULL;

    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;

    do {
        if (!pdesc) {
            break;
        }

        /* 查表找到对应的回调函数 */
        cb = (fp_err_t (*)(struct dev_uart_describe *, void *))protocol_callback_find(
            cmd, ioctl_cbs, ARRAY_SIZE(ioctl_cbs));
        if (!cb) {
            break;
        }

        /* 执行回调 */
        err = cb(pdesc, args);

    } while (0);

    return err;
}

/**
 * @brief UART中断事件处理
 * @param irq_event 中断事件类型(UART_EVENT_XXX)
 */
static fp_err_t _dev_uart_irq_handler(driver_t **pdrv, uint32_t irq_event, void *args, uint32_t length)
{
    struct dev_uart_describe *pdesc = NULL;
    fp_err_t err = E_WRONG_ARGS;

    pdesc = container_of(pdrv, device_t, pdrv)->pdesc;

    do {
        if (!pdesc) {
            break;
        }

        /* 接收完成(所有数据接收完成或缓冲区满) */
        if (irq_event == DEV_UART_EVENT_RX_COMPLETE) {
            /* 切换乒乓缓冲区 */
            if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
                pdesc->preveiver->pos = length;
                pingpong_buffer_set_write_done(&pdesc->rxpp);
                pingpong_buffer_get_write_buf(&pdesc->rxpp, (void **)&pdesc->preveiver);

                /* 驱动层主动重启接收 */
                if (pdesc->ops->start_receive) {
                    pdesc->ops->start_receive(pdesc, pdesc->preveiver->pbuf, pdesc->config.bufsz_rx);
                }
            }
        } else if (irq_event == DEV_UART_EVENT_RX_ERROR) {
            /* 接收错误: 重启接收(不切换缓冲区) */
            if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
                if (pdesc->ops->start_receive) {
                    pdesc->ops->start_receive(pdesc, pdesc->preveiver->pbuf, pdesc->config.bufsz_rx);
                }
            }
        } else if (irq_event == DEV_UART_EVENT_TX_COMPLETE) {
            /* 发送完成: 释放已发送缓冲区并启动下一次发送 */
            if (pdesc->config.flags & DEV_UART_FLAG_PKT_MODE) {
                /* 1. 释放已发送的缓冲区 */
                pingpong_buffer_set_read_done(&pdesc->txpp);
                pdesc->ptransmitter = NULL;

                /* 2. RS485模式: 切换回接收 */
                if (pdesc->config.flags & DEV_UART_FLAG_SWRS485) {
                    if (pdesc->ops->control) {
                        pdesc->ops->control(pdesc, UART_CTRL_SET_RS485_RX, NULL);
                    }
                }

                /* 3. 自动启动下一次发送(如果有待发送数据) */
                pingpong_buffer_get_read_buf(&pdesc->txpp, (void **)&pdesc->ptransmitter);
                if (pdesc->ptransmitter && pdesc->ops->start_transmit) {
                    /* RS485模式: 再次切换到发送 */
                    if (pdesc->config.flags & DEV_UART_FLAG_SWRS485) {
                        if (pdesc->ops->control) {
                            pdesc->ops->control(pdesc, UART_CTRL_SET_RS485_TX, NULL);
                        }
                    }
                    pdesc->ops->start_transmit(pdesc, pdesc->ptransmitter->pbuf, pdesc->ptransmitter->pos);
                }
            }
        }

        err = E_OK;
    } while (0);

    return err;
}

/**
 * @brief IOCTL: 获取接收缓冲区(零拷贝模式)
 * @retval E_OK     成功
 * @retval E_WRONG_ARGS 参数错误
 * @retval E_BUSY   接收模式冲突(已使用其他接收模式)
 */
static fp_err_t ioctl_get_rx_buf(struct dev_uart_describe *self, void *arg)
{
    fp_err_t err = E_WRONG_ARGS;

    do {
        if (!self || !arg) {
            break;
        }

        /* 检测接收模式冲突 */
        if (self->config.rx_mode != UART_RX_MODE_NONE && self->config.rx_mode != UART_RX_MODE_ZERO_COPY) {
            err = E_BUSY;
            break;
        }
        self->config.rx_mode = UART_RX_MODE_ZERO_COPY;

        if (self->config.flags & DEV_UART_FLAG_PKT_MODE) {
            struct dev_uart_msg *read_msg = NULL;
            if (pingpong_buffer_get_read_buf(&self->rxpp, (void **)&read_msg)) {
                struct dev_uart_buf *buf = (struct dev_uart_buf *)arg;
                buf->ptr = read_msg->pbuf;
                buf->size = read_msg->pos;
                err = E_OK;
            }
        }
    } while (0);

    return err;
}

/**
 * @brief IOCTL: 获取发送缓冲区(零拷贝模式)
 */
static fp_err_t ioctl_get_tx_buf(struct dev_uart_describe *self, void *arg)
{
    fp_err_t err = E_WRONG_ARGS;

    do {
        if (!self || !arg) {
            break;
        }

        if (self->config.flags & DEV_UART_FLAG_PKT_MODE) {
            struct dev_uart_msg *tx_msg = NULL;
            if (pingpong_buffer_get_write_buf(&self->txpp, (void **)&tx_msg)) {
                struct dev_uart_buf *buf = (struct dev_uart_buf *)arg;
                buf->ptr = tx_msg->pbuf;
                buf->size = self->config.bufsz_tx;
                err = E_OK;
            }
        }
    } while (0);

    return err;
}

/**
 * @brief IOCTL: 接收完成(零拷贝模式-释放缓冲区)
 */
static fp_err_t ioctl_rx_done(struct dev_uart_describe *self, void *arg)
{
    fp_err_t err = E_WRONG_ARGS;

    do {
        if (!self) {
            break;
        }

        if (self->config.flags & DEV_UART_FLAG_PKT_MODE) {
            pingpong_buffer_set_read_done(&self->rxpp);
            err = E_OK;
        }
    } while (0);

    return err;
}

/**
 * @brief IOCTL: 发送完成(零拷贝模式-触发发送)
 */
static fp_err_t ioctl_tx_done(struct dev_uart_describe *self, void *arg)
{
    fp_err_t err = E_WRONG_ARGS;

    do {
        if (!self) {
            break;
        }

        if (self->config.flags & DEV_UART_FLAG_PKT_MODE) {
            struct dev_uart_msg *tx_msg = NULL;
            pingpong_buffer_get_write_buf(&self->txpp, (void **)&tx_msg);
            if (tx_msg) {
                /* 标记写入完成 */
                pingpong_buffer_set_write_done(&self->txpp);

                /* 启动发送 */
                if (self->ptransmitter == NULL) {
                    pingpong_buffer_get_read_buf(&self->txpp, (void **)&self->ptransmitter);
                    if (self->ptransmitter && self->ops->start_transmit) {
                        self->ops->start_transmit(self, self->ptransmitter->pbuf, self->ptransmitter->pos);
                    }
                }
                err = E_OK;
            }
        }
    } while (0);

    return err;
}

/**
 * @brief IOCTL: 获取单字节(流式模式-用于协议栈)
 * @note   驱动层维护游标,跨包读取,适合 Modbus 等需要单字节接收的协议栈
 * @retval E_OK     成功读取一个字节
 * @retval E_EMPTY   无数据可读
 * @retval E_BUSY   接收模式冲突(已使用其他接收模式)
 */
static fp_err_t ioctl_get_byte(struct dev_uart_describe *self, void *arg)
{
    fp_err_t err = E_EMPTY;
    struct dev_uart_msg *msg = NULL;
    uint8_t *byte = (uint8_t *)arg;

    do {
        if (!self || !byte) {
            err = E_WRONG_ARGS;
            break;
        }

        /* 检测接收模式冲突 */
        if (self->config.rx_mode != UART_RX_MODE_NONE && self->config.rx_mode != UART_RX_MODE_STREAM) {
            err = E_BUSY;
            break;
        }
        self->config.rx_mode = UART_RX_MODE_STREAM;

        if (!(self->config.flags & DEV_UART_FLAG_PKT_MODE)) {
            break;
        }

        /* 1. 如果没有当前消息,尝试获取一个 */
        if (self->stream.current_msg == NULL) {
            if (!pingpong_buffer_get_read_buf(&self->rxpp, (void **)&msg)) {
                err = E_EMPTY; /* 无数据 */
                break;
            }
            self->stream.current_msg = msg;
            self->stream.read_pos = 0;
        }

        /* 2. 检查当前消息是否读完 */
        if (self->stream.read_pos >= self->stream.current_msg->pos) {
            /* 读完这个包,释放并尝试获取下一个 */
            pingpong_buffer_set_read_done(&self->rxpp);
            self->stream.current_msg = NULL;

            if (!pingpong_buffer_get_read_buf(&self->rxpp, (void **)&msg)) {
                err = E_EMPTY; /* 无更多数据 */
                break;
            }
            self->stream.current_msg = msg;
            self->stream.read_pos = 0;
        }

        /* 3. 读取一个字节,游标后移 */
        *byte = self->stream.current_msg->pbuf[self->stream.read_pos++];
        err = E_OK;

    } while (0);

    return err;
}

/*---------- end of file ----------*/


[C] 纯文本查看 复制代码
/*
 * Copyright (c) 2025 by Lu Xianfan.
 * @FilePath     : dev_uart.h
 * @Author       : lxf
 * @Date         : 2025-12-24 09:08:24
 * @LastEditors  : [email]lxf_zjnb@qq.com[/email]
 * @LastEditTime : 2025-12-25 16:28:23
 * @Brief        : UART设备驱动框架
 * @features     :
 *               - 非阻塞异步收发(基于HAL中断模式)
 *               - 乒乓缓冲区管理(支持连续收发)
 *               - IDLE中断接收(支持变长数据包)
 *               - RS485软件收发切换
 *               - 发送完成自动流控(支持队列发送)
 *
 * @architecture :
 *               ┌─────────────────────────────────────────────┐
 *               │              应用层                          │
 *               │  device_open/write/read/ioctl/close         │
 *               └─────────────────┬───────────────────────────┘
 *                                 │
 *               ┌─────────────────▼───────────────────────────┐
 *               │          dev_uart驱动层                      │
 *               │  - _dev_uart_write   拷贝到txpp              │
 *               │  - _dev_uart_read    从rxpp读取              │
 *               │  - _dev_uart_irq_handler 处理TX/RX事件      │
 *               │  - 接收完成后自动重启接收                    │
 *               └─────────────────┬───────────────────────────┘
 *                                 │
 *               ┌─────────────────▼───────────────────────────┐
 *               │         bsp_uart硬件抽象层                   │
 *               │  - uart_init            HAL初始化            │
 *               │  - uart_start_transmit  启动发送             │
 *               │  - uart_start_receive   启动接收             │
 *               │  - HAL_xxxCallback      中断回调             │
 *               └─────────────────┬───────────────────────────┘
 *                                 │
 *               ┌─────────────────▼───────────────────────────┐
 *               │            STM32 HAL库                      │
 *               └─────────────────────────────────────────────┘
 *
 * ============================================================================
 * @warning  接收模式冲突检测 - 三种接收方式互斥,只能选择一种!
 * ============================================================================
 *
 * UART驱动提供三种接收方式,共享同一个 rxpp 乒乓缓冲,混合使用会导致数据竞争:
 *
 * ┌────────────────┬─────────────────────────────────────────────────────────┐
 * │   接收模式      │                       使用方法                        │
 * ├────────────────┼─────────────────────────────────────────────────────────┤
 * │ STANDARD       │ device_read(uart, buf, 0, len)                         │
 * │ (标准模式)      │ 批量读取,自动释放缓冲区                                │
 * │                │ 适用: 一般应用,简单数据处理                            │
 * ├────────────────┼─────────────────────────────────────────────────────────┤
 * │ ZERO_COPY      │ device_ioctl(uart, IOCTL_UART_GET_RX_BUF, &rx_buf)      │
 * │ (零拷贝模式)    │ process_data(rx_buf.ptr, rx_buf.size)                 │
 * │                │ device_ioctl(uart, IOCTL_UART_RX_DONE, NULL)            │
 * │                │ 适用: 大数据量,回显,DMA转发                           │
 * ├────────────────┼─────────────────────────────────────────────────────────┤
 * │ STREAM         │ device_ioctl(uart, IOCTL_UART_GET_BYTE, &byte)         │
 * │ (流式模式)      │ 逐字节读取,驱动层维护游标,跨包读取                     │
 * │                │ 适用: Modbus/其他需要单字节接收的协议栈                 │
 * └────────────────┴─────────────────────────────────────────────────────────┘
 *
 * 冲突检测机制:
 *   - 首次调用任一接收接口时,自动锁定对应模式
 *   - 后续调用其他模式的接口时,返回 E_BUSY / -1 错误
 *   - 模式锁定状态保存在 config.rx_mode 中
 *
 * 示例:
 *   @code
 *   device_t *uart = device_open("usart2");
 *
 *   // 正确: 只使用 STREAM 模式
 *   uint8_t byte;
 *   device_ioctl(uart, IOCTL_UART_GET_BYTE, &byte);  // 锁定 STREAM 模式
 *
 *   // 错误: 混合使用模式
 *   device_read(uart, buf, 0, len);  // 返回 -1 (模式冲突)
 *   @endcode
 */
#ifndef __DEV_UART_H__
#define __DEV_UART_H__
#ifdef __cplusplus
extern "C" {
#endif
/*---------- includes ----------*/
#include "define.h"
#include <stdint.h>
#include <stdbool.h>
#include "device.h"
#include "pingpong.h"
/*---------- macro ----------*/

/* IOCTL 命令定义 */
#define IOCTL_UART_GET_RX_BUF      (IOCTL_USER_START + 0x00) /* 获取接收缓冲区(零拷贝) */
#define IOCTL_UART_GET_TX_BUF      (IOCTL_USER_START + 0x01) /* 获取发送缓冲区(零拷贝) */
#define IOCTL_UART_RX_DONE         (IOCTL_USER_START + 0x02) /* 接收完成(零拷贝模式-释放缓冲区) */
#define IOCTL_UART_TX_DONE         (IOCTL_USER_START + 0x03) /* 发送完成(零拷贝模式-触发发送) */
#define IOCTL_UART_GET_BYTE        (IOCTL_USER_START + 0x04) /* 获取单字节(流式模式-用于协议栈) */

/* UART 标志位 */
#define DEV_UART_FLAG_SWRS485      (1 << 0) /* 软件RS485模式,收发切换由软件控制 */
#define DEV_UART_FLAG_PKT_MODE     (1 << 1) /* 使用整包收发模式(IDLE或者DMA),内部采用乒乓缓冲 */

/*---------- type define ----------*/

/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
struct dev_uart_describe; /* 前向声明 */

/**
 * @brief UART 接收模式 (用于 config.rx_mode,三种模式互斥,只能选择一种)
 * @note  三种接收方式共享同一个 rxpp 乒乓缓冲,混合使用会导致数据竞争
 *
 * @verbatim
 * 模式1: UART_RX_MODE_STANDARD - 标准模式(带拷贝,简单易用)
 *         device_read(uart, buf, 0, len)  → 批量读取,自动释放缓冲区
 *         适用场景: 一般应用,简单数据处理
 *
 * 模式2: UART_RX_MODE_ZERO_COPY - 零拷贝模式(高性能)
 *         device_ioctl(uart, IOCTL_UART_GET_RX_BUF, &rx_buf)  → 获取缓冲区
 *         process_data(rx_buf.ptr, rx_buf.size)              → 直接处理
 *         device_ioctl(uart, IOCTL_UART_RX_DONE, NULL)        → 释放缓冲区
 *         适用场景: 大数据量,回显,DMA转发
 *
 * 模式3: UART_RX_MODE_STREAM - 单字节流式模式(协议栈适配)
 *         device_ioctl(uart, IOCTL_UART_GET_BYTE, &byte)      → 逐字节读取
 *         驱动层维护游标,跨包读取
 *         适用场景: Modbus/其他需要单字节接收的协议栈
 * @endverbatim
 *
 * @warning 三种模式互斥,只能选择一种!混合使用会返回 E_BUSY 错误
 */
enum uart_rx_mode {
    UART_RX_MODE_NONE = 0,       /* 未使用接收功能 */
    UART_RX_MODE_STANDARD,       /* 标准模式: device_read() */
    UART_RX_MODE_ZERO_COPY,      /* 零拷贝模式: IOCTL_GET_RX_BUF/DONE */
    UART_RX_MODE_STREAM,         /* 流式模式: IOCTL_GET_BYTE */
};

/**
 * @brief UART 硬件控制命令 (ops->control 使用)
 */
enum {
    UART_CTRL_SET_RS485_TX, /* RS485 切换到发送模式 */
    UART_CTRL_SET_RS485_RX, /* RS485 切换到接收模式 */
};

/**
 * @brief UART 中断事件类型 (IRQ Handler 入参)
 */
enum {
    DEV_UART_EVENT_TX_COMPLETE, /* 发送物理完成 (TC) - 所有位发完,用于RS485切向 */
    DEV_UART_EVENT_RX_COMPLETE, /* 接收完成 - IDLE中断或DMA完成 */
    DEV_UART_EVENT_RX_ERROR,    /* 接收错误 - ORE/FE/NE/PE等错误,需要重启接收 */
};

/**
 * @brief UART 缓冲区描述(用于零拷贝模式)
 */
struct dev_uart_buf {
    uint8_t *ptr;  /* 缓冲区指针 */
    uint32_t size; /* 缥冲区大小或数据长度 */
};

/**
 * @brief UART 配置结构体
 */
struct dev_uart_config {
    uint32_t baudrate;         /* 波特率: 9600, 19200, 38400, 57600, 115200等 */
    uint32_t databits;         /* 数据位: 8, 9 */
    uint32_t stopbits;         /* 停止位: 1, 2 */
    uint32_t parity;           /* 校验位: 0=None, 1=Odd, 2=Even */
    uint32_t bufsz_rx;         /* 软件接收FIFO大小 */
    uint32_t bufsz_tx;         /* 软件发送FIFO大小 */
    uint32_t flags;            /* UART标志位: DEV_UART_FLAG_XXX */
    enum uart_rx_mode rx_mode; /* 接收模式: UART_RX_MODE_XXX (默认 STANDARD) */
};

/**
 * @brief UART 底层硬件操作接口
 */
struct dev_uart_ops {
    /**
     * @brief 硬件初始化
     * @param self UART设备描述符指针
     * @param cfg 配置参数
     * @return E_OK=成功,其他=失败
     */
    fp_err_t (*init)(struct dev_uart_describe *self, struct dev_uart_config *cfg);

    /**
     * @brief 硬件反初始化
     * @param {dev_uart_describe} *self UART设备描述符指针
     * @return {*}
     */
    void (*deinit)(struct dev_uart_describe *self);

    /**
     * @brief 控制操作(开关中断、RS485方向控制等)
     * @param self UART设备描述符指针
     * @param cmd 控制命令
     * @param arg 命令参数
     * @return E_OK=成功,其他=失败
     */
    fp_err_t (*control)(struct dev_uart_describe *self, uint32_t cmd, void *arg);

    /**
     * @brief 启动异步发送
     * @param self UART设备描述符指针
     * @param buf 要发送的数据缓冲区
     * @param len 发送长度
     * @note 发送完成后会触发DEV_UART_EVENT_TX_COMPLETE事件
     */
    void (*start_transmit)(struct dev_uart_describe *self, uint8_t *buf, uint32_t len);

    /**
     * @brief 启动异步接收
     * @param self UART设备描述符指针
     * @param buf 接收缓冲区
     * @param len 缓冲区大小
     * @return E_OK=成功,其他=失败
     * @note 接收完成后会触发DEV_UART_EVENT_RX_COMPLETE事件
     */
    fp_err_t (*start_receive)(struct dev_uart_describe *self, uint8_t *buf, uint32_t len);

};

struct dev_uart_msg {
    uint32_t pos;
    uint8_t pbuf[];
};

/**
 * @brief UART 设备描述符
 */
struct dev_uart_describe {
    struct dev_uart_config config; /* 配置参数 */
    struct dev_uart_ops *ops;      /* 底层硬件操作接口指针 */
    void *hw_handle;               /* 硬件接口 */
    /* 私有变量不需要用户初始化 */
    struct dev_uart_msg *preveiver;    /* 指向当前接收的 dev_uart_msg */
    struct dev_uart_msg *ptransmitter; /* 指向当前发送的 dev_uart_msg */
    struct pingpong_buffer txpp;       /* 发送乒乓缓冲 */
    struct pingpong_buffer rxpp;       /* 接收乒乓缓冲 */

    /* 流式单字节读取状态 (UART_RX_MODE_STREAM 模式使用) */
    struct {
        struct dev_uart_msg *current_msg;   /* 当前正在读取的消息包 */
        uint32_t read_pos;                  /* 当前读取位置(游标) */
    } stream;
};

/*---------- end of file ----------*/
#ifdef __cplusplus
}
#endif
#endif





总之,我对程序员未来的生存空间不带乐观了。大部分应用层代码都可以通过AI实现了。
(像我这样的初级程序员,不知道未来何去何从)

回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120427
QQ
发表于 2026-1-1 13:38:43 | 显示全部楼层
嵌入式这块我感觉还不用太担心,特别是软硬概结合的程序员,AI再厉害,当前是无法替代人做硬件测试的,特别是bug的处理。

纯软件开发,确实影响比较大。
回复

使用道具 举报

9

主题

168

回帖

195

积分

初级会员

积分
195
发表于 2026-1-1 20:54:35 | 显示全部楼层
linux软件开发,绝大多数问题AI基本都能解决,硬件部分AI可以辅助排查一些问题。
回复

使用道具 举报

38

主题

231

回帖

345

积分

高级会员

积分
345
发表于 5 天前 | 显示全部楼层
以前是面向过程和面向对象编程
现在变成面向AI编程
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
发表于 5 天前 | 显示全部楼层
请问一下使用的什么平台的vibe coding呢
回复

使用道具 举报

111

主题

613

回帖

961

积分

金牌会员

积分
961
QQ
 楼主| 发表于 5 天前 | 显示全部楼层
嵌入式小萌新 发表于 2026-1-4 09:40
请问一下使用的什么平台的vibe coding呢

Claude code + glm4.7
回复

使用道具 举报

1

主题

7

回帖

10

积分

新手上路

积分
10
发表于 4 天前 | 显示全部楼层

我部署到了VSCode,确实好用
回复

使用道具 举报

111

主题

613

回帖

961

积分

金牌会员

积分
961
QQ
 楼主| 发表于 4 天前 | 显示全部楼层
嵌入式小萌新 发表于 2026-1-5 12:01
我部署到了VSCode,确实好用

相当牛逼,完成大部分手敲代码的工作。
只需要做code review。
回复

使用道具 举报

11

主题

724

回帖

757

积分

金牌会员

积分
757
发表于 4 天前 | 显示全部楼层
牛叉。硬件暂时还可以,毕竟样品焊接调试,现场安装调试,需要工程师。还有PLC工程师暂时还不能替代,跑现场调试的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-1-9 17:39 , Processed in 0.066848 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表