0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于优先级调度的嵌入式实时操作系统内核详解(下)

瑞萨MCU小百科 来源:瑞萨MCU小百科 2023-09-06 12:46 次阅读

三、板载led和串口的驱动

3.1 板载led(GPIO)

RA6M5的引脚结构体定义

左右滑动查看

typedef struct _ra6m5_fire_pin_t
{
  cat_uint32_t       pin_num;
  ioport_instance_ctrl_t *p_ctrl_ptr;
  const bsp_io_port_pin_t gpio_pin;
}ra6m5_fire_pin_t;

暂时只用得上输出引脚,实现pin_write接口,利用fsp库实现引脚输出。

左右滑动查看

cat_uint8_t cat_pin_write(cat_uint32_t pin_num, cat_uint8_t val)
{
  cat_uint8_t ret = CAT_ERROR;
  ra6m5_fire_pin_t *p = &(pin_map[0]);


  /* 遍历pin_map数组 */
  for(; p->pin_num!=0xffff; p++)
  {
    if(p->pin_num == pin_num)
    {
      if(0 == val)
      {
        R_IOPORT_PinWrite(p->p_ctrl_ptr, p->gpio_pin, BSP_IO_LEVEL_LOW);
        ret = CAT_EOK;
      }
      else if(1 == val)
      {
        R_IOPORT_PinWrite(p->p_ctrl_ptr, p->gpio_pin, BSP_IO_LEVEL_HIGH);
        ret = CAT_EOK;
      }
      else
      {
        /* 非法值,之后打印错误信息 */
        ret = CAT_ERROR;
        while(1);
      }


      /* 写入结束结束循环 */
      break;
    } /* if */
  } /* for */


  return ret;
}

3.2 串口

野火教程以及我找到的官方例程中RA6M5的串口收发均使用中断实现,但在本内核中的标准输入输出函数大部分是以字符为单位,故发送接口用寄存器方式实现,串口接收仍然使用fsp库+中断实现

3.2.1 串口发送

左右滑动查看

static cat_int8_t ra6m5_uart_send_char(cat_device_t*dev, cat_uint32_t timeout, cat_uint8_t data)
{
  cat_int8_t ret = CAT_ERROR;
  struct _cat_ra6m5_fire_uart_private_data_t *private_data = NULL;


  /* 获取设备实例数据 */
  private_data = (struct _cat_ra6m5_fire_uart_private_data_t *)(dev->pri_data);


  sci_uart_instance_ctrl_t *p_ctrl = private_data->inst_ctrl_ptr;


  /* 将要发送的数据放进数据寄存器 */
  p_ctrl->p_reg->TDR = data;


  /* 等待发送完成或超时 */
  while(
    ((p_ctrl->p_reg->SSR_b.TEND) == 0) &&
    (0 != timeout)
  )
  {
    timeout--;
  }


  /* 未超时才成功 */
  if(0 != timeout)
  {
    ret = CAT_EOK;
  }


  return ret;
}


static cat_uint32_t ra6m5_uart_send(cat_device_t*dev, uint32_t timeout, uint8_t const * const buffer, uint32_t const size)
{
  (void)timeout;
  cat_uint32_t cnt = 0;
  cat_int8_t err = CAT_EOK;


  while(
    (CAT_EOK == err) &&
    (cnt < size)
    )
    {
        err = ra6m5_uart_send_char(dev, 0xffff, buffer[cnt]);
        cnt++;
    }


    /* 因为前面在一次 while 循环中无论发送是否成功 cnt 都会无条件加一,所以如果失败了就有一个多加上的计数 */
    if(CAT_ERROR == err)
    {
        cnt--;
    }


    return cnt;
}

3.2.2 串口接收

左右滑动查看

static cat_uint32_t ra6m5_uart_recv(cat_device_t*dev, uint32_t timeout, uint8_t *buffer, uint32_t const size)
{
cat_uint32_t recv_buffer_idx = 0; /**< 串口接收缓冲区访问索引 */
cat_uint32_t err = CAT_ERROR;
struct _cat_ra6m5_fire_uart_private_data_t *private_data = NULL;


/* 获取设备实例数据 */
private_data = (struct _cat_ra6m5_fire_uart_private_data_t *)(dev->pri_data);
assert(NULL != private_data);


/* 读取 */
while(recv_buffer_idx != size)
{
while(
(false == uart4_receive_char) &&
(0 != timeout)
)
{
timeout--;
};


if(0 == timeout)
{
break;
}


while(
(cat_ringbuffer_is_empty(private_data->p_ringbuffer) == 0)
)
{
/* 获取接收到的字符 */
err = cat_ringbuffer_get(private_data->p_ringbuffer, &(buffer[recv_buffer_idx++]));


if(CAT_ERROR == err)
{
/* 获取失败,因为while条件判断过非空,所以出大问题 */
while(1);
}


if(recv_buffer_idx == size)
{
break;
}
}


if(cat_ringbuffer_is_empty(private_data->p_ringbuffer))
{
/* 取完才改遍flag */
uart4_receive_char = false;
}
}


return recv_buffer_idx;
}

3.2.3 串口中断服务函数

左右滑动查看

/* uart4中断回调函数 */
void debug_uart4_callback(uart_callback_args_t *pargs)
{
  switch(pargs->event)
  {
    case UART_EVENT_RX_CHAR:
    {
      cat_ringbuffer_put(&uart4_rb, pargs->data);
      uart4_receive_char = true;
    }
    default:
    {
      break;
    }
  }
}

四、调试验证

4.1 创建demo项目

在Projects目录利用RASC工具生成Keil裸机工程,只需配置led引脚以及UART串口

eb88a170-4c6a-11ee-a25d-92fbcf53809c.png

eba6cb0a-4c6a-11ee-a25d-92fbcf53809c.png

4.2 编写程序创建任务

在hal_entry中创建用户任务

左右滑动查看

#include "hal_data.h"
#include "catos.h"


FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
#define TASK1_STACK_SIZE  (1024)
#define TASK2_STACK_SIZE  (1024)


struct _cat_task_t task1;
struct _cat_task_t task2;


cat_stack_type_t task1_env[TASK1_STACK_SIZE];
cat_stack_type_t task2_env[TASK2_STACK_SIZE];


uint32_t sched_task1_times = 0;
uint32_t sched_task2_times = 0;


#define BOARD_LED_PIN 0


void board_led_init(void)
{
  cat_pin_init(BOARD_LED_PIN, CAT_PIN_MODE_OUTPUT);
}


void board_led_on(void)
{
  cat_pin_write(BOARD_LED_PIN, CAT_PIN_LOW);
}


void board_led_off(void)
{
  cat_pin_write(BOARD_LED_PIN, CAT_PIN_HIGH);
}


void task1_entry(void *arg)
{


  for(;;)
  {
    sched_task1_times++;
    board_led_on();
    cat_sp_task_delay(100);
    board_led_off();
    cat_sp_task_delay(100);
  }
}


void task2_entry(void *arg)
{
  for(;;)
  {
    cat_sp_task_delay(100);
    //CAT_DEBUG_PRINTF("[task2] %d
", catos_systicks);
  }
}


void hal_entry(void)
{
  /* TODO: add your own code here */


  /* 初始化os */
  catos_init();


  /* 利用pin驱动初始化板载led */
  board_led_init();


  /* 测试创建任务运行 */
  cat_sp_task_create(
   (const uint8_t *)"task1_task",
   &task1,
   task1_entry,
   NULL,
   0,
   task1_env,
   TASK1_STACK_SIZE
  );


  cat_sp_task_create(
   (const uint8_t *)"task2_task",
   &task2,
   task2_entry,
   NULL,
   0,
   task2_env,
   sizeof(task2_env)
  );




  /* 开始调度 */
  catos_start_sched();


  /* 不会到达这里 */


  while(1);


#if BSP_TZ_SECURE_BUILD
  /* Enter non-secure code */
  R_BSP_NonSecureEnter();
#endif
}



4.3 烧写与验证

使用xshell连接串口并烧录程序,可以观察到l led闪烁,并且串口有shell的信息,命令可以正常使用。

ebfaf4aa-4c6a-11ee-a25d-92fbcf53809c.png

五、总结

在整个项目过程中,因为涉及底层操作,并且教程还比较少,走了不少弯路,但总体来说还是很不错的,特别是fsp配置方面。

建议瑞萨可以在e2 studio适配更多调试器方便开发者使用;并且在使用野火dap时发现其在ubuntu下要被识别比较麻烦,如果能改进,使用场景会更多。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    237

    文章

    22449

    浏览量

    645875
  • 嵌入式
    +关注

    关注

    4982

    文章

    18281

    浏览量

    288430
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39846
  • RTOS
    +关注

    关注

    20

    文章

    776

    浏览量

    118795
  • GPIO
    +关注

    关注

    16

    文章

    1133

    浏览量

    50570

原文标题:【瑞萨RA MCU创意氛围赛作品赏析】项目4——基于优先级的RTOS内核(下)

文章出处:【微信号:瑞萨MCU小百科,微信公众号:瑞萨MCU小百科】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于优先级调度嵌入式实时操作系统内核详解(上)

    今日分享参加瑞萨RA MCU创意氛围赛的选手项目——基于优先级的RTOS内核。本项目为基于优先级调度嵌入式
    发表于 09-04 14:12 316次阅读

    嵌入式实时操作系统uCos

    嵌入式实时操作系统uCos:嵌入式实时操作系统µCOS -II一、RTOS基础 
    发表于 12-10 14:35

    嵌入式领域linux作为实时操作系统的缺点

    几乎公平的分配任务时间,在特殊场合linux内核在任务调度上实现的是一种几乎公平的分配任务时间,在特殊场合Linux内核很难满足
    发表于 01-06 13:31

    详解RT-Thread实时操作系统

    操作系统,由国内一些专业开发人员开发、维护。它不仅仅是一款 高效、稳定的实时操作系统内核,也是一套面向嵌入式
    发表于 03-02 14:24

    五大适合STM32的嵌入式操作系统

    ,具有执行效率高、占用空间小、实时性能优良和扩展性强等特点。对于实时性的满足上,由于μC/OS-II内核是针对实时系统的要求设计实现的,所以
    发表于 04-15 15:39

    几种嵌入式实时操作系统分析与比较

    实时操作系统采用基于优先级抢占调度与时间片轮转调度相结合的
    发表于 06-11 09:14

    嵌入式操作系统FreeRTOS 的原理与实现

    的使用权后才能获得运行,这样可提高CPU的运行效率。2、FreeRTOS操作系统的原理与实现2.1任务调度机制的实现任务调度机制是嵌入式实时
    发表于 06-23 08:00

    实时操作系统概念

    对很多嵌入式系统来说,一个设计良好的实时操作系统可以让开发工程师把握系统执行任何任务或响应任何关键事件的时间,满足
    发表于 07-19 06:18

    如何进行嵌入式Linux内核实时化研究?

    嵌入式Linux是指对Linux进行剪裁后,将其固化在单片机或者存储器中,应用于特定场合的专用Linux系统嵌入式系统要求实时性能高,但L
    发表于 08-06 07:15

    嵌入式实时系统中的优先级反转是什么?

    的可抢占调度策略。系统为每一个任务分配一个优先权,调度程序保证当前运行的进程是优先权最高的进程
    发表于 09-17 07:16

    适合STM32的三大嵌入式操作系统

    ,μC/OS-II的移植相对比较简单,只需要修改与处理器相关的代码就可以。综上可知,μC/OS-II是一个结构简单、功能完备和实时性很强的嵌入式操作系统内核,针对于没有MMU功能的CP
    发表于 06-29 11:32

    嵌入式实时系统中的优先级反转问题怎么解决?

    嵌入式实时系统中的优先级反转问题怎么解决?
    发表于 04-27 06:44

    嵌入式操作系统为什么必须要有一个良好的任务调度算法呢

    引言随着嵌入式实时操作系统应用的不断深入,多个实时任务并发执行,再加上任务之间不停地动态切换,这对任务调度算法提出了较高的要求。
    发表于 12-21 06:24

    嵌入式实时操作系统VxWorks内核调度机制分析

    本文简要介绍了多任务内核,重点分析了嵌入式实时操作系统VxWorks的内核调度机制——
    发表于 12-11 16:15 14次下载

    嵌入式实时操作系统内核的设计

    针对广泛使用的微处理单元(MCU),从任务TCB设计、任务的创建和删除、任务调度的算法及实现、中断管理、优先级管理和操作系统及用户的接口等6个部分出发,提出了一个嵌入式
    发表于 08-26 14:34 63次下载
    <b class='flag-5'>嵌入式</b><b class='flag-5'>实时</b><b class='flag-5'>操作系统</b><b class='flag-5'>内核</b>的设计