瑞萨RA系列FSP库开发实战指南之DTC外部中断触发传输实验

描述

19.9

实验3:DTC外部中断触发传输

19.9.1

硬件设计

本实验的目标是使用外部中断来触发DTC传输,因此需要用到一个按键。

外部中断在前面已经学过了,按键的硬件电路请参考前面的第16章“外部中断”章节。

19.9.2

软件设计

19.9.2.1

新建工程

对于e2 studio开发环境:

拷贝一份我们之前的e2s工程 “19_UART_Receive_Send”,然后将工程文件夹重命名为“20_DTC_External_IRQ”,最后再将它导入到我们的e2 studio工作空间中。

对于Keil开发环境:

拷贝一份我们之前的Keil工程“19_UART_Receive_Send”,然后将工程文件夹重命名为“20_DTC_External_IRQ”,并进入该文件夹里面双击Keil工程文件,打开该工程。

工程新建好之后,在工程根目录的“src”文件夹下面新建“dtc”文件夹,再进入“dtc”文件夹里面新建源文件和头文件:“bsp_dtc.c”和“bsp_dtc.h”。工程文件结构如下。

列表18:文件结构

左右滑动查看完整内容

 

20_DTC_External_IRQ
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ debug_uart
│ ├─ bsp_debug_uart.c
│ └─ bsp_debug_uart.h
├─ dtc
│ ├─ bsp_dtc.c
│ └─ bsp_dtc.h
└─ hal_entry.c

 

19.9.2.2

FSP配置

在前面的“外部中断”章节,相信大家已经学会如何配置外部中断了。这次实验我们要使用外部中断来触发/激活DTC传输,而使用外部中断要用到我们的按键。

打开该工程的FSP配置界面。我们先加入外部中断。点到“Pins”页面,在ICU0里面找到IRQ09,这里我们选用P004引脚(SW2按键连接的引脚)连接到外部中断IRQ09

外部中断

然后点到“Stacks”页面,按照“New Stack”→“Input”→“External IRQ”的步骤添加一个ICU模块来配置外部中断。ICU模块的配置可按照如下图所示进行配置,中断触发方式默认选择上升沿触发,中断优先级设置比UART中断大一点,设置为优先级10。

外部中断

接着我们在“Stacks”页面继续加入DTC模块,按如下图所示步骤添加。

外部中断

我们按如下图配置一下DTC:

外部中断

DTC配置项(与上图相对应)

表8:DTC配置属性描述

外部中断

配置完成后,直接右上角点击生成代码。

注:读者可能会疑惑不需要设置DTC中断回调函数?

19.9.2.3

使用FSP配置器生成的配置

下面的是与我们之前在FSP配置界面上的配置等效的配置代码:

列表19:代码清单20‑16与FSP配置界面上的配置等效的配置代码

左右滑动查看完整内容

 

/* FSP 配置界面的传输信息配置(正常传输模式)等效于下面 fsp_transfer_info_normal 里
的配置(除了源地址和目标地址)
源地址和目标地址在 FSP 配置界面设置的话不太方便,我们会在 DTC_Init 函数里设置。
关于偏移值(Offset value)和源缓冲大小(Source Buffer Size),在 transfer_info_
→t 里没有这两项设置,建议在 FSP 配置界面设置
- 偏移值只有在地址模式是偏移模式的情况下才会用到;
- 而源缓冲大小与之相关的功能本例程不会涉及到,所以暂不考虑。
下面的 fsp_transfer_info_normal 仅作为对比参考,在本例程中是没有用到的。
*/
//transfer_info_t fsp_transfer_info_normal =
//{
// .transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_FIXED,␣
→ //每次传输后,目标地址指针固定不变
// .transfer_settings_word_b.repeat_area = TRANSFER_REPEAT_AREA_
→SOURCE, //源区域重复 (正常模式下无效)
// .transfer_settings_word_b.irq = TRANSFER_IRQ_END, ␣
→ //传输完成后中断
// .transfer_settings_word_b.chain_mode = TRANSFER_CHAIN_MODE_
→DISABLED, //不使能(DMAC 没有该功能,仅 DTC 有)
// .transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_FIXED,␣
→ //每次传输后,源地址指针固定不变
// .transfer_settings_word_b.size = TRANSFER_SIZE_2_BYTE, ␣
→ //每次传输 2 字节
// .transfer_settings_word_b.mode = TRANSFER_MODE_NORMAL, ␣
→ //正常传输模式
// .p_dest = (void *) DST_Buffer, ␣
→ //目标地址
// .p_src = (void const *) SRC_Buffer,
→ //源地址
// .num_blocks = 0, //指定传输的块数(正常模式和重复模式下均无效,仅
块模式下有效)
// .length = 1, //指定传输的长度(即正常的传输次数或重复模式下重
复大小 或 块模式下传输的块大小)
//};
// 按照上述传输信息配置,期待的正确传输结果为:
uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
0x00000304,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000 };

 

19.9.2.4

使用代码配置:正常传输模式

下面是DTC在正常模式下传输的配置代码:

列表20:代码清单20‑17 DTC正常传输模式配置

左右滑动查看完整内容

 

/* 正常传输模式 */
transfer_info_t my_transfer_info_normal =
{
.transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,目标地址指针都会增加
.transfer_settings_word_b.repeat_area = TRANSFER_REPEAT_AREA_SOURCE,
→ //源区域重复 (正常模式下无效)
.transfer_settings_word_b.irq = TRANSFER_IRQ_END, ␣
→ //传输完成后中断
.transfer_settings_word_b.chain_mode = TRANSFER_CHAIN_MODE_
→DISABLED, //不使能(DMAC 没有该功能,仅 DTC 有)
.transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,源地址指针都会增加
.transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE, ␣
→ //每次传输 4 字节
.transfer_settings_word_b.mode = TRANSFER_MODE_NORMAL, ␣
→ //正常传输模式
.p_dest = (void *) DST_Buffer, ␣
→ //目标地址
.p_src = (voidconst *) SRC_Buffer, ␣
→ //源地址
.num_blocks = 0, //指定传输的块数(正常模式和重复模式下均无效,仅块
模式下有效)
.length = 1, //指定传输的长度(即正常的传输次数或重复模式下重复
大小 或 块模式下传输的块大小)
};
// 按照上述传输信息配置,期待的正确传输结果为:
uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
0x01020304,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000 };

 

19.9.2.5

使用代码配置:重复传输模式

下面是DTC在重复传输模式下传输的配置代码:

列表21:代码清单20‑18 DTC重复传输模式配置

左右滑动查看完整内容

 

/* 重复传输模式 */
transfer_info_t my_transfer_info_repeat =
{
.transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,目标地址指针都会增加
.transfer_settings_word_b.repeat_area = TRANSFER_REPEAT_AREA_SOURCE,
→ //源区域重复 (正常模式下无效)
.transfer_settings_word_b.irq = TRANSFER_IRQ_EACH, ␣
→ //传输完成后中断
.transfer_settings_word_b.chain_mode = TRANSFER_CHAIN_MODE_
→DISABLED, //不使能(DMAC 没有该功能,仅 DTC 有)
.transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,源地址指针都会增加
.transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE, ␣
→ //每次传输 4 字节
.transfer_settings_word_b.mode = TRANSFER_MODE_REPEAT, ␣
→ //重复传输模式
.p_dest = (void *) DST_Buffer, ␣
→ //目标地址
.p_src = (voidconst *) SRC_Buffer, ␣
→ //源地址
.num_blocks = 0, //指定传输的块数(正常模式和重复模式下均无效,仅块
模式下有效)
.length = 2, //指定传输的长度(即正常的传输次数或重复模式下重复
大小 或 块模式下传输的块大小)
};
// 按照上述传输信息配置,期待的正确传输结果为:
uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
0x01020304,0x05060708,0x01020304,0x05060708,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000 };

 

19.9.2.6

使用代码配置:块传输模式

下面是DTC在块传输模式下传输的配置代码:

列表22:代码清单20‑19 DTC块传输模式配置

左右滑动查看完整内容

 

/* 块传输模式 */
transfer_info_t my_transfer_info_block =
{
.transfer_settings_word_b.dest_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,目标地址指针都会增加
.transfer_settings_word_b.repeat_area = TRANSFER_REPEAT_AREA_SOURCE,
→ //源区域重复 (正常模式下无效)
.transfer_settings_word_b.irq = TRANSFER_IRQ_END, ␣
→ //传输完成后中断
.transfer_settings_word_b.chain_mode = TRANSFER_CHAIN_MODE_
→DISABLED, //不使能(DMAC 没有该功能,仅 DTC 有)
.transfer_settings_word_b.src_addr_mode = TRANSFER_ADDR_MODE_
→INCREMENTED, //每次传输后,源地址指针都会增加
.transfer_settings_word_b.size = TRANSFER_SIZE_4_BYTE, ␣
→ //每次传输 4 字节
.transfer_settings_word_b.mode = TRANSFER_MODE_BLOCK, ␣
→ //块传输模式
.p_dest = (void *) DST_Buffer, ␣
→ //目标地址
.p_src = (voidconst *) SRC_Buffer, ␣
→ //源地址
.num_blocks = 1, //指定传输的块数(正常模式和重复模式下均无效,仅块
模式下有效)
.length = BUFFER_SIZE, //指定传输的长度(即正常的传输次数或重复模式下重复
大小 或 块模式下传输的块大小)
};
// 按照上述传输信息配置,期待的正确传输结果为:
uint32_t Expected_DST_Buffer[BUFFER_SIZE] = {
0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80 };

 

19.9.2.7

DTC初始化函数

DTC初始化函数如下所示:

列表23:代码清单20‑20 DTC初始化函数

左右滑动查看完整内容

 

/* DTC 初始化函数 */
voidDTC_Init(void)
{
fsp_err_t err;
/* 使用 FSP 界面的配置:需要先重新设置传输的源地址和目的地址 */
#ifndef USE_MY_TRANSFER_INFOR_CONFIG
set_transfer_dst_src_address(&g_transfer_dtc_cfg, SRC_Buffer, DST_
→Buffer);
#endif
err = R_DTC_Open(&g_transfer_dtc_ctrl, &g_transfer_dtc_cfg);
assert(FSP_SUCCESS == err);
/* 使用我们新的自定义的传输信息:重新配置传输 */
#ifdef USE_MY_TRANSFER_INFOR_CONFIG
// 根据我们要使用的传输模式进行选择配置:
#if (DTC_TRANSFER_MODE == DTC_TRANSFER_NORMAL_MODE) //正常模式
err = R_DTC_Reconfigure(&g_transfer_dtc_ctrl, &my_transfer_info_
→normal);
assert(FSP_SUCCESS == err);
#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_REPEAT_MODE) //重复模式
err = R_DTC_Reconfigure(&g_transfer_dtc_ctrl, &my_transfer_info_
→repeat);
assert(FSP_SUCCESS == err);
#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_BLOCK_MODE) //块模式
err = R_DTC_Reconfigure(&g_transfer_dtc_ctrl, &my_transfer_info_block);
assert(FSP_SUCCESS == err);
#endif//DTC_TRANSFER_MODE
#endif//USE_MY_TRANSFER_INFOR_CONFIG
}

 

19.9.2.8

按键外部中断回调函数

按键外部中断回调函数如下所示:

列表24:代码清单20‑21按键外部中断回调函数

左右滑动查看完整内容

 

/* 按键按下标志 */
volatilebool key_sw2_press = false;
/* 按键中断回调函数 */
voidicu_external_irq_callback(external_irq_callback_args_t *p_args)
{
/* 判断中断通道 */
if (9 == p_args->channel)
{
key_sw2_press = true; // 按键 SW2 按下
}
}

 

19.9.2.9

hal_entry入口函数

列表25:代码清单20‑22 hal_entry.c文件

左右滑动查看完整内容

 

/* 用户头文件包含 */
#include"led/bsp_led.h"
#include"debug_uart/bsp_debug_uart.h"
#include"dtc/bsp_dtc.h"
externconstuint32_t SRC_Buffer[BUFFER_SIZE];
externuint32_t DST_Buffer[BUFFER_SIZE];
externuint32_t Expected_DST_Buffer[BUFFER_SIZE];
externvolatilebool dtc_complete_transmission_sign;
uint8_tBufferCompare(constuint32_t *pBuffer1, constuint32_t *pBuffer2,␣
→uint16_t BufferLength)
voidBufferShow_HexData(constuint32_t *pBuffer, uint16_t BufferLength);
voidhal_entry(void)
{
/* TODO: add your own code here */
uint8_t res;
LED_Init(); // LED 初始化
Debug_UART4_Init(); // SCI4 UART 调试串口初始化
/* 初始化 DTC */
DTC_Init();
printf("这是一个 DTC 存储器到存储器的传输实验例程
");
printf("打开串口助手,查看接收窗口打印的相关提示信息
");
printf("按下按键 SW2 激活 DTC 传输
");
printf("观察板载 LED 灯,本实验使用两个 LED 灯来指示 DTC 传输结果
");
printf("- DTC 数据传输失败,则 LED1 亮(红色)
");
printf("- DTC 数据传输成功,则 LED2 亮(蓝色)
");
printf("--------------------------------------------
");
/* Open ICU module */
R_ICU_ExternalIrqOpen(&g_external_irq9_ctrl, &g_external_irq9_cfg);
/* 允许中断 */
R_ICU_ExternalIrqEnable(&g_external_irq9_ctrl);
/* 使能 DTC 模块 */
R_DTC_Enable(&g_transfer_dtc_ctrl);
/*************************************/
/* 使用按键外部中断触发激活 DTC 传输 */
/*************************************/
#ifndef USE_MY_TRANSFER_INFOR_CONFIG
/* 根据 FSP 配置界面的传输信息进行传输 */
/* 等待激活 DTC 传输 */
for (uint16_t i = 0; i < 1; i++)
{
/* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
while (false == key_sw2_press);
key_sw2_press = false;
/* 等待本次传输完成 */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); //加上延时确
保传输完成
}
#else// 下面的这些是使用自定义的传输配置信息配置
#if (DTC_TRANSFER_MODE == DTC_TRANSFER_NORMAL_MODE) //正常模式
/* 等待激活 DTC 传输 */
for (uint16_t i = 0; i < 1; i++)
{
/* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
while (false == key_sw2_press);
key_sw2_press = false;
/* 等待本次传输完成 */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); //加上延时确
保传输完成
}
#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_REPEAT_MODE) //重复模式
/* 等待激活 DTC 传输 */
for (uint16_t i = 0; i < 4; i++)
{
/* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
while (false == key_sw2_press);
key_sw2_press = false;
/* 等待本次传输完成 */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); //加上延时确
保传输完成
}
#elif (DTC_TRANSFER_MODE == DTC_TRANSFER_BLOCK_MODE) //块模式
/* 等待激活 DTC 传输 */
for (uint16_t i = 0; i < 1; i++)
{
/* 等待按键按下,按键按下一次即激活一次 DTC 传输 */
while (false == key_sw2_press);
key_sw2_press = false;
/* 等待本次传输完成 */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS); //加上延时确
保传输完成
}
#endif//DTC_TRANSFER_MODE
#endif//USE_MY_TRANSFER_INFOR_CONFIG
/* 将传输后的数据与我们所期待的结果相比较 */
res = BufferCompare(DST_Buffer, Expected_DST_Buffer, BUFFER_SIZE);
printf("传输结果:");
/* 根据两者数据的比较结果进行判断 */
if( res != 0)
{
/* 源数据与传输后数据不相等时,LED1 亮(红色),表示传输失败 */
LED1_ON;
printf("< 传输失败>
");
}
else
{
/* 源数据与传输后数据相等时,LED1 亮(蓝色),表示传输成功 */
LED2_ON;
printf("< 传输成功>
");
}
printf("
SRC:");
BufferShow_HexData(SRC_Buffer, BUFFER_SIZE);
printf("
DST:(应与 Expected_DST 一致)");
BufferShow_HexData(DST_Buffer, BUFFER_SIZE);
printf("
Expected_DST:");
BufferShow_HexData(Expected_DST_Buffer, BUFFER_SIZE);
while(1)
{
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}

 

19.9.3

实验现象

首先通过宏 USE_MY_TRANSFER_INFOR_CONFIG(在bsp_dtc.h文件中)来选择是使用我们自定义的传输信息,还是使用在FSP配置界面配置的传输信息。

其次通过宏DMAC_TRANSFER_MODE(在bsp_dtc.h文件中)来选择不同的传输模式。

最后编译工程并下载到开发板上,打开串口助手可以查看程序运行打印的提示信息。按下启明6M5开发板上的按键SW2,即触发DT传输。如果DTC传输成功,则蓝色LED2亮起,如果传输失败则红色LED1亮起。

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分