三、板载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串口


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的信息,命令可以正常使用。

五、总结
在整个项目过程中,因为涉及底层操作,并且教程还比较少,走了不少弯路,但总体来说还是很不错的,特别是fsp配置方面。
建议瑞萨可以在e2 studio适配更多调试器方便开发者使用;并且在使用野火dap时发现其在ubuntu下要被识别比较麻烦,如果能改进,使用场景会更多。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !