123
123 - 认证专家
This guy hasn't written anything yet

注册于 2 years ago

回答
282
文章
6
关注者
11

是不是clock的函数命名有些许的变化,我这边的名字是叫做system_clock_config,你可以代码跟踪一下,看一下 系统启动时,初始化时钟的函数 rt_hw_board_init 的最终调用的是哪个函数?或者简单点就看board.c的时钟初始化叫什么名字,然后将 STM32cubeMX 配置的时钟函数的代码替换过去就行了,命名保持之前的不变

将16进制数据转换为字符串格式,但是转成\0还是会被截断的。
at_client_obj_send 这个接口发送你想输入的buffer(16进制数据)就行了。

rt_pin_write() 是直接转成了index的索引数值,只能单个IO操作,不能用位运算符进行计算(因为或运算就相当于将数值改成了其他数字),不支持多个IO进行读写的。你要想多IO操作,就使用芯片的SDK提供的多个IO操作的接口去再封装一层了。

在H7上还没有进行过适配QSPI的DMA模式,所以这个可能暂时不能用。如果楼主进行验证成功,可以把这个功能加上去提交个PR,来修复这个BUG.

定时器HARD_TIMER 模式回调函数 已经属于进入的中断环境了,看下SysTick_Handler()代码

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}
void rt_tick_increase(void)
{
    struct rt_thread *thread;
    rt_base_t level;

    level = rt_hw_interrupt_disable();

    /* increase the global tick */
#ifdef RT_USING_SMP
    rt_cpu_self()->tick ++;
#else
    ++ rt_tick;
#endif /* RT_USING_SMP */

    /* check time slice */
    thread = rt_thread_self();

    -- thread->remaining_tick;
    if (thread->remaining_tick == 0)
    {
        /* change to initialized tick */
        thread->remaining_tick = thread->init_tick;
        thread->stat |= RT_THREAD_STAT_YIELD;

        rt_hw_interrupt_enable(level);
        rt_schedule();
    }
    else
    {
        rt_hw_interrupt_enable(level);
    }

    /* check timer */
    rt_timer_check();
}

不是的,你可以全局搜索一下,(struct spi_flash_device *) 这个关键字,user_data这个成员变量都是用于指向rtt_dev这个指针。用到spi_flash_device的都是从user_data来的。

另外就是你说的CS这个引脚,它是赋值给了user_data,但是它是给了rt_spi_device->parent->user_data。你可以看下 rt_spi_bus_attach_device这个函数理解一下。两个user_data不一样的。

rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device,
                                  const char           *name,
                                  const char           *bus_name,
                                  void                 *user_data)
{
    rt_err_t result;
    rt_device_t bus;

    /* get physical spi bus */
    bus = rt_device_find(bus_name);
    if (bus != RT_NULL && bus->type == RT_Device_Class_SPIBUS)
    {
        device->bus = (struct rt_spi_bus *)bus;

        /* initialize spidev device */
        result = rt_spidev_device_init(device, name);
        if (result != RT_EOK)
            return result;

        rt_memset(&device->config, 0, sizeof(device->config));
        device->parent.user_data = user_data;

        return RT_EOK;
    }

    /* not found the host bus */
    return -RT_ERROR;
}

选中你的代码段,然后 "Ctrl" + "/"

image.png

觉得有用,点个采纳哈

楼主已经验证过SDRAM数据是没问题的,然后推到屏是错误的了?比如刷个单色看看有没有杂点

串口接收使用DMA时,设置的接收缓冲区大小就是这个宏 RT_SERIAL_RB_BUFSZ ,默认是64字节,实际用的时候如果内存比较充足可以适当调大一些,至于能调整多大,这个是依据硬件配置的,比如STM32F4这个可以配置最大为65535字节
image.png

如果觉得对你有帮助,麻烦点个解决。

说两点,接收回调的意思是 接收到数据就触发一次函数调用,这个属于框架层面的东西,与应用层逻辑无关,另外接收回调不止是接收到一个字符就触发一次,当你用dma或者带fifo缓冲区的时候,接收回调的触发是接收到一帧数据才会触发一次,这个是和硬件特性结合的,另外你当然可以在接收回调做一些简单的处理,比如判断字符,等处理完成再用IPC通知线程唤醒,这样都是没问题的。

题主的意思已经耦合了应用逻辑,这样处理反而不好。换个意思说,硬件上串口接收中断接收到了数据,你要在串口中断中去判断接收到的数据是什么字符么,外设驱动层面的执行流,不能耦合到应用解析的对吧。

可能短期使用或者功能不复杂的时候没什么问题,甚至这样做反而简单些,但是系统越来越复杂时候,耦合度越高越不好做系统迭代的,牵一发动全身,因此做一个通用性的,层次结构分明的,可移植性的,是比较重要的。

如果觉得回答有用,记得点个 解决 哈。


#include <rtthread.h>

#define SAMPLE_UART_NAME       "uart1"      /* 串口设备名称 */

/* 串口接收消息结构*/
struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};
/* 串口设备句柄 */
static rt_device_t serial;
/* 消息队列控制块 */
static struct rt_messagequeue rx_mq;

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    struct rx_msg msg;
    rt_err_t result;
    msg.dev = dev;
    msg.size = size;

    result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
    if ( result == -RT_EFULL)
    {
        /* 消息队列满 */
        rt_kprintf("message queue full!\n");
    }
    return result;
}

static void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_err_t result;
    rt_uint32_t rx_length;
    static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];

    while (1)
    {
        rt_memset(&msg, 0, sizeof(msg));
        /* 从消息队列中读取消息*/
        result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
        if (result == RT_EOK)
        {
            /* 从串口读取数据*/
            rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
            rx_buffer[rx_length] = '\0';
            /* 通过串口设备 serial 输出读取到的消息 */
            rt_device_write(serial, 0, rx_buffer, rx_length);
            /* 打印数据 */
            rt_kprintf("%s\n",rx_buffer);
        }
    }
}

static int uart_dma_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    char uart_name[RT_NAME_MAX];
    static char msg_pool[256];
    char str[] = "hello RT-Thread!\r\n";

    if (argc == 2)
    {
        rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
    }
    else
    {
        rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
    }

    /* 查找串口设备 */
    serial = rt_device_find(uart_name);
    if (!serial)
    {
        rt_kprintf("find %s failed!\n", uart_name);
        return RT_ERROR;
    }

    /* 初始化消息队列 */
    rt_mq_init(&rx_mq, "rx_mq",
               msg_pool,                 /* 存放消息的缓冲区 */
               sizeof(struct rx_msg),    /* 一条消息的最大长度 */
               sizeof(msg_pool),         /* 存放消息的缓冲区大小 */
               RT_IPC_FLAG_FIFO);        /* 如果有多个线程等待,按照先来先得到的方法分配消息 */

    /* 以 DMA 接收及轮询发送方式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(serial, uart_input);
    /* 发送字符串 */
    rt_device_write(serial, 0, str, (sizeof(str) - 1));

    /* 创建 serial 线程 */
    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_dma_sample, uart device dma sample);

你这例子好几处使用不当的地方,你open的时候不是DMA模式,另外IPC也别这样用,做资源同步排队处理就行啦。试试这个,应该没什么问题的。然后这个例子如果收发正常不丢包之后,再把你的那个 if(ch == DATA_CMD_END) 加进去。

先说下结论:rt_sem_create是计数型信号量,你一直release,其value就一直增加。这个和freertos有区别的。

参照:

rt_err_t rt_sem_release(rt_sem_t sem)
{
    register rt_base_t temp;
    register rt_bool_t need_schedule;
... ...

    if (!rt_list_isempty(&sem->parent.suspend_thread))
    {
        /* resume the suspended thread */
        rt_ipc_list_resume(&(sem->parent.suspend_thread));
        need_schedule = RT_TRUE;
    }
    else
    {
        if(sem->value < RT_SEM_VALUE_MAX)
        {
            sem->value ++; /* increase value */
        }
... ...
}

二值信号量属于计数信号量的一种,用的时候不用区分的,只是说你在应用层的逻辑代码上人为控制其信号量释放的最大值为1即可,主要就是用在线程同步的场景下。
另外类似的线程同步的机制,还有 mutexrt_completion

你好,这个问题主要是usb识别出现的问题,可以断电重启解决。如果是UI文件导致的存储出现问题,可以使用命令行 mkfs -t lfs fs进行gui分区的格式化操作(重启生效),另外在开发的过程中,使用命令 df /gui 可以方便的查询磁盘剩余存储容量。如果未能解决问题,可以q群联系,我是群成员123

看样子好像是更改了BSP的连接路径,然后路径没找到,而且Kconfig的语法可能也有问题。看下这个链接是否与帮助。
https://club.rt-thread.org/ask/question/10708.html

回到
顶部

发布
问题

投诉
建议