当前位置: 首页 > wzjs >正文

电商网站如何做引流加盟网络营销推广公司

电商网站如何做引流,加盟网络营销推广公司,最容易做流量的网站,买房在线咨询前言 本文基于RT-Thread V4.1.1和STM32F103(Cortex-M3) 编译环境为STM32CubeIDE(GCC) 本文旨在理解RT-Thread设计的基本逻辑,为了让文章简短易懂,所以展出的源码都是精简过的,一些好理解的开…

前言

本文基于RT-Thread V4.1.1和STM32F103(Cortex-M3)

编译环境为STM32CubeIDE(GCC)

本文旨在理解RT-Thread设计的基本逻辑,为了让文章简短易懂,所以展出的源码都是精简过的,一些好理解的开关中断,宏代码等会省略掉

可以看懂基本逻辑后查看源码领悟具体细节

关于RT-Thread的移植可以参考



双向链表

双向环形链表的定义,基本所有的核心操作都离不开这个双向链表

struct rt_list_node
{struct rt_list_node *next;                          /**< point to next node. */struct rt_list_node *prev;                          /**< point to prev node. */
};
typedef struct rt_list_node rt_list_t;                  /**< Type for lists. */

将节点 n 插入到 l 后面,分4步完成

rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{l->next->prev = n;n->next = l->next;l->next = n;n->prev = l;
}

将节点 n 插入到 l 前面,分4步完成

rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
{l->prev->next = n;n->prev = l->prev;l->prev = n;n->next = l;
}
// 链表初始化 即自己指向自己
rt_inline void rt_list_init(rt_list_t *l)
{l->next = l->prev = l;
}// 判断链表是否为空
rt_inline int rt_list_isempty(const rt_list_t *l)
{return l->next == l;
}// 获取链表长度
rt_inline unsigned int rt_list_len(const rt_list_t *l)
{unsigned int len = 0;const rt_list_t *p = l;while (p->next != l){p = p->next;len ++;}return len;
}



通过元素找到内核对象地址

在RT-Thread中所有对象(线程,信号量等)都会有list元素,如下操作是通过list地址反推对象地址,如下是以rt_thread线程对象为例:

#define rt_list_entry(node, type, member) rt_container_of(node, type, member)
#define rt_container_of(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

找到当前链表所在结构体的首地址,巧妙的利用&((type *)0)->member算了链表的偏移量,使用示例如下:

struct rt_thread *thread;thread = rt_list_entry(list->next, struct rt_thread, tlist);struct rt_thread
{char        name[RT_NAME_MAX];                      /**< the name of thread */rt_uint8_t  type;                                   /**< type of object */rt_uint8_t  flags;                                  /**< thread's flags */rt_list_t   list;                                   /**< the object list */rt_list_t   tlist;                                  /**< the thread list */void       *sp;                                     /**< stack point */void       *entry;                                  /**< entry */void       *parameter;                              /**< parameter */void       *stack_addr;                             /**< stack address */rt_uint32_t stack_size;                             /**< stack size */......
}



启动RTOS

在没有OS的工程中,是从main()中开始运行的

RT-Thread 支持多种平台和多种编译器,而 rtthread_startup() 函数是 RT-Thread 规定的统一启动入口

一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动函数rtthread_startup(),最后进入用户入口函数 main()

使用GCC编译时需要修改启动文件

使用MDK时可以不用修改,可以使用$Sub$$main,如果可以参考博文

int rtthread_startup(void)
{rt_hw_interrupt_disable();/* 板级初始化:需在该函数内部进行系统堆的初始化 */rt_hw_board_init();/* 打印 RT-Thread 版本信息 */rt_show_version();/* 硬件定时器初始化 */rt_system_timer_init();/* 调度器初始化 */rt_system_scheduler_init();/* 由此创建一个用户 main 线程 */rt_application_init();/* 软件定时器线程初始化 */rt_system_timer_thread_init();/* 空闲线程初始化 */rt_thread_idle_init();/* 启动调度器 */rt_system_scheduler_start();/* 不会执行至此 */return 0;
}



调度器初始化

与调度相关的有两个非常重要的变量,在rt_system_scheduler_init()中就是初始化这两个变量

rt_thread_priority_table 是一个ready链表数组,同一优先级的线程放同一链表中

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

rt_thread_ready_priority_group 是一个32位整型数,每1位都代表着对应优先级是否有ready的线程,0 优先级代表最高优先级

rt_uint32_t rt_thread_ready_priority_group;

与其相关的操作节选如下:

// 线程启动(UP)或改变优先级的时候赋值
thread->number_mask = 1 << thread->current_priority;	// rt_schedule_insert_thread 中调用
rt_thread_ready_priority_group |= thread->number_mask;// rt_schedule_remove_thread 中调用  
rt_thread_ready_priority_group &= ~thread->number_mask;

顺带介绍一下与优先级相关的函数

_scheduler_get_highest_priority_thread()

获取已经ready的最高优先级线程指针

其中__rt_ffs()函数用来计算整数中从低位开始的第一个非零位的位置,和内建函数__builtin_ffs()功能一致

static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio)
{register struct rt_thread *highest_priority_thread;register rt_ubase_t highest_ready_priority;highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;/* get highest ready priority thread */highest_priority_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);*highest_prio = highest_ready_priority;return highest_priority_thread;
}

rt_schedule_insert_thread()

将线程插入调度列表

void rt_schedule_insert_thread(struct rt_thread *thread)
{/* READY thread, insert to ready queue */thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);/* insert thread to ready list */rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),&(thread->tlist));rt_thread_ready_priority_group |= thread->number_mask;
}

rt_schedule_remove_thread()

将线程从调度列表中移除

void rt_schedule_remove_thread(struct rt_thread *thread)
{/* remove thread from ready list */rt_list_remove(&(thread->tlist));if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority]))){// 需要通过rt_list_isempty() 判断同优先级是否有其他已ready线程 没有才清除对应位rt_thread_ready_priority_group &= ~thread->number_mask;}
}



创建用户 main 线程

调用创建线程函数,这里以静态创建为例

void rt_application_init(void)
{rt_thread_t tid;tid = &main_thread;result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);RT_ASSERT(result == RT_EOK);rt_thread_startup(tid);
}rt_err_t rt_thread_init(struct rt_thread *thread, const char *name, void (*entry)(void *parameter), void *parameter,void *stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick)
{/* initialize thread object */rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);return _thread_init(thread, name, entry, parameter, stack_start, stack_size, priority, tick);
}

这里先通过rt_object_init函数给线程类型句柄rt_thread_t tid初始化rt_object部分

需要说明是,RT-Thrad中所有对象(线程,信号量等)的结构体开头都包括rt_object

rt_object中有对象类型,名称等信息



开关中断简述

开关中断函数总是成对的出现,rt_hw_interrupt_disable在关中断的同时,会返回关之前的中断状态

所以rt_hw_interrupt_enable并不一定是真的开中断了,只有最外层的rt_hw_interrupt_enable才会真的开中断

rt_base_t rt_hw_interrupt_disable(void);
void rt_hw_interrupt_enable(rt_base_t level);
    .global rt_hw_interrupt_disable.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:MRS     R0, PRIMASKCPSID   IBX      LR.global rt_hw_interrupt_enable.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:MSR     PRIMASK, R0BX      LR

http://www.dtcms.com/wzjs/165150.html

相关文章:

  • 做静态网站选用什么服务器深圳百度推广联系方式
  • 保定手机网站制作全网霸屏推广系统
  • 网站建设服务协议模板软文发布公司
  • 做网站自己买服务器吗百度站长平台链接
  • visual c 网站开发谷歌商店安卓版下载
  • 网站信任的体验如何做潍坊自动seo
  • 福田营销型网站建站推广外包短视频营销案例
  • 网站建设08中国百强县市榜单
  • 商丘做网站推广全达seo
  • 政务信息网站的建设的意义杭州seo
  • 哪儿可以学电商贺贵江seo教程
  • 摄影网站建设论文代运营公司是怎么运营的
  • 成都网站开发建设厦门网站外包
  • b站推广网站2024不用下载软件网站推广优化流程
  • 杭州做企业网站公司什么文案容易上热门
  • 关于域名和主机论坛的网站营销策略4p分析怎么写
  • 网站制作的一般步骤地推项目对接平台
  • 苏州设计网站建设发布
  • 网站两列导航app关键词排名优化
  • 营销型网站图片关键词排名优化公司外包
  • 门户网站建设情况总结以网红引流促业态提升
  • 投标建设用地是哪个网站重庆百度快照优化排名
  • 怎么查询公司名字是否可以注册seo学堂
  • 雄安智能网站建设方案刷粉网站推广免费
  • 广州网站建设公司哪家好如何搜索关键词热度
  • 长春城乡建设部网站首页百度推广关键词
  • 牛牛网站开发网络推广费用计入什么科目
  • 企业网站备案 优帮云地推app推广赚佣金
  • 政务信息化建设网站简阳seo排名优化课程
  • 衡水网站设计费用网络推广的网站有哪些