【RTD MCAL 篇2】 K312 UART DMA

news2024/11/26 20:21:38

【RTD MCAL 篇2】 K312 UART DMA

  • 一,文档简介
  • 二, 功能实现
    • 2.1 K312 MINIEVB硬件配置
    • 2.2 EB 配置
      • 2.2.1 Mcl module
      • 2.2.2 Mcu module
      • 2.2.3 Platform module
      • 2.2.4 Port module
      • 2.2.5 Uart module
      • 2.2.6 Rm module
    • 2.3 main code
  • 三,测试结果

一,文档简介

十一假期时间余额已经不足了,抓紧时间赶一篇MCAL的K312 UART DMA。本篇文章讲解同样是基于S32DS+EB配置,RTD400, 以后其他模块的MCAL锻炼都会基于这样的结构,不过,本文会提供一个命令行版本的代码。如果需要命令行模式,完全可以直接在RTD MCAL的代码包下拷贝一个,并且利用VScode去编译。本篇文章硬件基于K312-miniEVB,板子情况是这样的:

在这里插入图片描述

图 1

功能:在K312 MCAL代码中,使用DMA方式实现UART的收发功能。
由于RTD400不带有K312的例程,这里还涉及到一个从RTD400移植到K312 MCAL的过程,当然前面的文章已经讲的非常清楚,并且还给出了S32DS工程模版。本文将基于之前的S32DS EB工程模版去做。

二, 功能实现

2.1 K312 MINIEVB硬件配置

谈到硬件配置,由于本文只是使用UART,所以结构非常简单,用到引脚:
LPUART3_TX : PTD2
LPUART3_RX : PTD3
并且外接TTL-USB工具实现信号通讯。

2.2 EB 配置

这里罗列出所有本文相关的EB tresos里面使用到的模块,并且重点给予需要具体配置的模块讲解。

在这里插入图片描述

图 2

2.2.1 Mcl module

需要配置Dma Logic Channel界面,主要目的是为LPUART3_TX 和RX配置两个DMA通道。
(1)dmalogicChannel_Type_0
在这里插入图片描述

图 3

(2)dmalogicChannel_Type_2
在这里插入图片描述

图 4

这里面注册的callback也是可以直接在代码里面去调用的。

2.2.2 Mcu module

Mcu->McuClockSettingConfig->McuClockReferencePoint->Lpuart3_clk
在这里插入图片描述

图5

实际上就是配置LPUART的时钟源频率为24Mhz,来源于AIPS_SLOW_CLK。

2.2.3 Platform module

Platform->Interrupt Controller->IntCtrlConfig,配置3个通道:
在这里插入图片描述

图 6

这里只需要关注LPUART3中断,以及DMA0 通道6, 通道7中断,因为这两个DMA通道是配置给UART的TX,RX的。FlexIO忽略,只是原始例程里面有没有删掉而已。

2.2.4 Port module

Port->PortContainer, 添加PTD2,PTD3引脚:
在这里插入图片描述

图7

在这里插入图片描述

图 8

2.2.5 Uart module

有两个地方需要配置:
(1)uart->General
在这里插入图片描述

图 9

(2)uart->uartChannel
在这里插入图片描述

图 10

这里有4个点要注意:
点1:选择mcu里面配置的时钟源
点2:配置波特率为115200
点3:选择异步方式为DMA
点4:选择mcl里面配置的两个DMA通道,需要把TX和RX匹配到对应的DMA通道。

2.2.6 Rm module

Rm->DMA MUX
配置两个DMA_MUX通道。
在这里插入图片描述

图11

在这里插入图片描述

图 12

2.3 main code

#include "Mcl.h"
#include "Mcu.h"
#include "CDD_Uart.h"
#include "CDD_Rm.h"
#include "Port.h"
#include "Platform.h"
#include "Lpuart_Uart_Ip_Irq.h"
#include "Flexio_Uart_Ip_Irq.h"
//#include "check_example.h"
#include <string.h>
#include "Port_Cfg.h"

#define UART_LPUART_INTERNAL_CHANNEL  0U
#define UART_FLEXIO_TX_CHANNEL  1U
#define UART_FLEXIO_RX_CHANNEL  2U

/* Welcome messages displayed at the console */
#define WELCOME_MSG "MCAL UART DMA Helloworld for automotive with S32K312!\r\n"
/* Error message displayed at the console, in case data is received erroneously */
#define ERROR_MSG "An error occurred! The application will stop!\r\n"

/* Length of the message to be received from the console */
#define MSG_LEN  50U
#define UART_BUFFER_LENGTH		((uint32)10U)
Std_ReturnType T_Uart_Status;
//uint8 Rx_Buffer[UART_BUFFER_LENGTH];

#define UART_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_Memmap.h"
__attribute__(( aligned(32) )) uint8 Rx_Buffer[UART_BUFFER_LENGTH];
#define UART_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_Memmap.h"

uint32 g_Uart_CallbackCounter = 0U;

uint32 g_DmaCh16_ErrorCallbackCounter = 0U;
uint32 g_DmaCh17_ErrorCallbackCounter = 0U;

//void Uart_Callback (void);
void Uart_Callback(const uint8 HwInstance, const Lpuart_Uart_Ip_EventType Event, void *UserData);

void Mcl_DmaCh16_ErrorCallback (void);
void Mcl_DmaCh17_ErrorCallback (void);
void Uart_Callback(const uint8 HwInstance, const Lpuart_Uart_Ip_EventType Event, void *UserData)
{
	if(Event == LPUART_UART_IP_EVENT_END_TRANSFER)
	{
		__asm volatile ("nop");
		__asm volatile ("nop");
		__asm volatile ("nop");
		__asm volatile ("nop");
		__asm volatile ("nop");
		__asm volatile ("nop");
	}
	else if (Event == LPUART_UART_IP_EVENT_TX_EMPTY)
	{
		__asm volatile ("nop");
		__asm volatile ("nop");
	}
	else if (Event == LPUART_UART_IP_EVENT_RX_FULL)
	{
		__asm volatile ("nop");
	}
	else if (Event == LPUART_UART_IP_EVENT_ERROR)
	{
		__asm volatile ("nop");
	}
	else
	{
		__asm volatile ("nop");
	}
}

void Mcl_DmaCh6_ErrorCallback (void)
{
	g_DmaCh16_ErrorCallbackCounter++;
}

void Mcl_DmaCh7_ErrorCallback (void)
{
	g_DmaCh17_ErrorCallbackCounter++;
}

boolean User_Str_Cmp(const uint8 * pBuffer1, const uint8 * pBuffer2, const uint32 length)
{
    uint32 idx = 0;
    for (idx = 0; idx < length; idx++)
    {
        if(pBuffer1[idx] != pBuffer2[idx])
        {
            return FALSE;
        }
    }
    return TRUE;
}
/**
* @brief        Main function of the example
* @details      Initializez the used drivers and uses the Icu
*               and Dio drivers to toggle a LED on a push button
*/
int main(void)
{
    Std_ReturnType   UartStatus = E_NOT_OK;
    uint32           RemainingBytes;
	uint32           Timeout   = 0xFFFFFF;
    Uart_StatusType  UartReceiveStatus  = UART_STATUS_TIMEOUT;
    Uart_StatusType  UartTransmitStatus = UART_STATUS_TIMEOUT;
    /* Initialize the Mcu driver */
    Mcu_Init(NULL_PTR);
    Mcu_InitClock(McuClockSettingConfig_0);
    Mcu_SetMode(McuModeSettingConf_0);
    /* Initialize Mcl module */
    Mcl_Init(NULL_PTR);
    /* Initialize Rm driver for using DmaMux*/
    Rm_Init (NULL_PTR);
    /* Initialize all pins using the Port driver */
    Port_Init(NULL_PTR);
    /* Initialize IRQs */
    Platform_Init(NULL_PTR);
    /* Initializes an UART driver*/
    Uart_Init(NULL_PTR);
     T_Uart_Status = Uart_AsyncSend(UART_LPUART_INTERNAL_CHANNEL, (const uint8 *)WELCOME_MSG, strlen(WELCOME_MSG));
        if (E_OK == T_Uart_Status)
        {
			do
			{
				/* Get transmission status */
				UartTransmitStatus = Uart_GetStatus (UART_LPUART_INTERNAL_CHANNEL, &RemainingBytes, UART_SEND);
			}
			while (UART_STATUS_NO_ERROR != UartTransmitStatus && 0 < Timeout--);

			Timeout = 0xFFFFFF;
			UartTransmitStatus = UART_STATUS_TIMEOUT;
        }

	for(;;)
    {
    	/* Receive data from the PC - Get 10 bytes in total */
    	UartStatus = Uart_AsyncReceive (UART_LPUART_INTERNAL_CHANNEL, Rx_Buffer, UART_BUFFER_LENGTH);

        if (E_OK == UartStatus)
        {
			do
			{
				/* Get receive status */
				UartReceiveStatus = Uart_GetStatus (UART_LPUART_INTERNAL_CHANNEL, &RemainingBytes, UART_RECEIVE);
			}
			while (UART_STATUS_NO_ERROR != UartReceiveStatus && 0 < Timeout--);

			Timeout = 0xFFFFFF;
			UartReceiveStatus = UART_STATUS_TIMEOUT;
        }
        UartStatus = E_NOT_OK;

    	/* Send data to the PC - Echo back the received data */
    	UartStatus = Uart_AsyncSend (UART_LPUART_INTERNAL_CHANNEL, Rx_Buffer, UART_BUFFER_LENGTH);

        if (E_OK == UartStatus)
        {
			do
			{
				/* Get transmission status */
				UartTransmitStatus = Uart_GetStatus (UART_LPUART_INTERNAL_CHANNEL, &RemainingBytes, UART_SEND);
			}
			while (UART_STATUS_NO_ERROR != UartTransmitStatus && 0 < Timeout--);
			Timeout = 0xFFFFFF;
			UartTransmitStatus = UART_STATUS_TIMEOUT;
        }
        UartStatus = E_NOT_OK;
    }
    Uart_Deinit();
    Mcl_DeInit();
 //   Exit_Example((T_Uart_Status1 == E_OK) && (T_Uart_Status2 == E_OK));
    return (0U);
}

这里需要注意的是,根据RTD C:\NXP\SW32K3_S32M27x_RTD_R21-11_4.0.0\eclipse\plugins\Uart_TS_T40D34M40I0R0\doc的RTD_UART_IM.pdf, RTD_UART_UM.pdf.
在这里插入图片描述

图 13

在做DMA传输的时候,需要把buffer放到noncacheable区域。
所以才有本文的:

#define UART_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_Memmap.h"
__attribute__(( aligned(32) )) uint8 Rx_Buffer[UART_BUFFER_LENGTH];
#define UART_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Uart_Memmap.h"

三,测试结果

使用UART3,引脚UART3_TX:PTD2, UART3_RX:PTD3
芯片复位之后,先发送:
Helloworld for automotive with S32K344!
然后等待接受,接收到10个字节的数据之后,产生uart_callback中断,进入到LPUART_UART_IP_ENET_END_TRANSFER里面,你这里打断点会看到,RX_Buffer里面收到的数据和发送的数据一致。
然后,代码会将收到的数据回环出去。测试情况如下:
我下图是测试了两组:
PC发送: 1234567890,MCU收到之后,回环回来。
PC发送:0987654321,MCU收到之后,debug停到断点,可以查看收到的buffer情况,你可以看到,buffer数据已经正确。
在这里插入图片描述

图14

在这里插入图片描述

图 15

附件两个代码包:
(1)Uart_TS_T40D34M40I0R0_miniK312_3.zipEB MCAL 命令行方式
该代码,解压之后放到:C:\NXP\SW32K3_S32M27x_RTD_R21-11_4.0.0\eclipse\plugins,然后就可以直接用命令行去编译。
在这里插入图片描述

图 16

(2)Mcal_UARTDMA_S32K312_RTD400_S32DS.zip:导入到S32DS的方式,当然里面已经包含了EB的工程:
在这里插入图片描述

图 17

文章附件代码链接:
https://community.nxp.com/t5/S32K-Knowledge-Base/RTD400-MCAL-K312-UART-DMA/ta-p/1967467

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Clio——麻省理工学院增强机器人场景理解算法

概述 机器人感知长期以来一直受到现实世界环境复杂性的挑战&#xff0c;通常需要固定设置和预定义对象。麻省理工学院的工程师 已经开发了Clio这项突破性的系统可以让机器人直观地理解并优先考虑周围环境中的相关元素&#xff0c;从而提高其高效执行任务的能力。 了解对更智…

【Python】Marmir 使用指南:Python 驱动的电子表格生成器

Marmir 是一个由 Python 驱动的电子表格生成工具&#xff0c;专门用于将 Python 数据结构&#xff08;如字典、列表等&#xff09;转换为电子表格文件&#xff08;如 Excel&#xff09;。Marmir 的设计目标是提供比传统电子表格库&#xff08;如 xlwt&#xff09;更强大和灵活的…

ctf.bugku-备份是个好习惯

访问页面得到字符串 这串字符串是重复的&#xff1b; d41d8cd98f00b204e9800998ecf8427e 从前端、源码上看&#xff0c;除了这段字符串&#xff0c;没有其他信息&#xff1b;尝试解密&#xff0c;长度32位&#xff1b;各种解密方式试试&#xff1b; MD5免费在线解密破解_MD5在…

文件后缀名不见了怎么办?

有一天&#xff0c;突然有需要更改文件的后缀名&#xff0c;可奇怪的是文件只有名称&#xff0c;后缀不见了&#xff0c;这该如何修改呢&#xff1f; 第一步&#xff1a;打开此电脑&#xff0c;最上面一栏选择“查看” 第二步&#xff1a;将“文件扩展名”勾选上 第三步&…

会议时如何实现扫码签到?

如何实现扫码签到&#xff1f; 在现代活动管理中&#xff0c;签到环节是不可或缺的一部分。它不仅关系到活动的顺利进行&#xff0c;还涉及到参与者的体验。传统的签到方式往往耗时且效率不高&#xff0c;而随着技术的发展&#xff0c;扫码签到成为了一种高效且便捷的解决方案。…

用小学生可以理解的语言讲一下什么是大模型

好的&#xff0c;用小学生的语言来说&#xff0c;大模型就像是一个超级聪明的机器人老师&#xff0c;它懂得很多东西&#xff0c;可以帮助我们做很多事情。 1. **懂得很多**&#xff1a;大模型知道很多知识&#xff0c;就像一个巨大的图书馆&#xff0c;里面有很多书&#xff0…

【星汇极客】单片机竞赛之2024睿抗机器人大赛-火线速递赛道(持续更新)

前言 本人是一名嵌入式学习者&#xff0c;在大学期间也参加了不少的竞赛并获奖&#xff0c;包括但不限于&#xff1a;江苏省电子设计竞赛省一、睿抗机器人国二、中国高校智能机器人国二、嵌入式设计竞赛国三、光电设计竞赛国三、节能减排竞赛国三。 后面会经常写一下博客&…

归并排序:递归、非递归实现、文件排序(归并排序实现)

目录 归并排序递归实现 1.归并排序基本思想 2.归并排序单趟思路 3.代码思路步骤 3.1.归并排序实现思路步骤 3.2.总结 3.2.1.数组归并与链表归并的差异 (1)数组归并 (2)链表归并 (3)总结 3.2.2.归并排序的递归实现总结 4.归并排序递归实现代码 5.归并排序递归递归展…

用AI做电子萌宠,快速涨粉变现

今天给大家分享一个很热门的小副业—AI宠物视频 项目介绍 前一阵刷到一个萌宠账号&#xff0c;爆款率可真高&#xff0c;涨粉可真快呀。 28篇笔记涨粉3.2万&#xff0c;点赞更是达到了十几万。其中有6篇点赞上万。 至于究竟是不是AI其实没那么重要&#xff0c;重要的是&…

华为OD机试 - Excel单元格数值统计(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

安可数据库产品目录

‌国家安可数据库产品目录包括以下主要产品‌&#xff1a; ‌华为GaussDB、openguass&#xff1a; 由华为云计算技术有限公司提供。‌金仓数据库管理系统&#xff1a;由中电科金仓&#xff08;北京&#xff09;科技股份有限公司提供。‌神通数据库管理系统&#xff1a;由天津神…

上学迟到问题

刚看到这题时&#xff0c;我突然就有了思路。说起来挺可笑的当我写完这题后&#xff0c;并成功AC时&#xff0c;看着我那冗长的代码我陷入了深思&#xff0c;难道真的有必要写这么一长串吗? 这是我的代码 #include<stdio.h> int main(){int s,v,t;scanf("%d %d&q…

ROW_NUMBER

How to rewrite a query which uses the ROW_NUMBER() window function in versions 5.7 or earlier before window functions were supported e.g., SELECT ROW_NUMBER() OVER (PARTITION BY fieldA) AS rownum, myTable.* FROM myTable; index 用不上的 Solution Assuming…

Linux高阶——0928—Github数据上传markdown语言

1、Github三要素 仓库、提交、分支 提交 绿色&#xff1a;新加 红色&#xff1a;删除 主分支master或main 项目的存储单位——仓库 实际代码的存储单位——分支 分支的协同开发 2、本地数据上传到云端的过程 3、markdown

OpenHarmony(鸿蒙南向开发)——轻量和小型系统三方库移植指南(一)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 本文为OpenHarmony开发者提供一些组织编译形式比较常见&…

【C/C++】错题记录(四)

题目一 一个函数可以有很多个返回值&#xff08;有很多个return语句&#xff09;&#xff0c;但是最终只能有一个return语句执行。 题目二 题目三 题目四 题目五 程序数据结构算法 题目六 题目七 题目八 题目九 D选项是语句……

leetcode第189题:轮转数组(C语言版)

思路1&#xff08;不推荐&#xff09; 保存数组最后一个元素&#xff0c;然后数组全体元素后移一位&#xff0c;把保存的最后一个元素存放到数组的第一个位置&#xff0c;重复这一操作&#xff0c;直到执行完了k次。 时间复杂度&#xff1a;需要用k次循环&#xff0c;里面套一层…

【2024】前端学习笔记14-JavaScript常用数据类型-变量常量

学习笔记 1.JavaScript常用数据类型1.1.Number&#xff08;数字&#xff09;1.2.String&#xff08;字符串&#xff09;1.3.Boolean&#xff08;布尔值&#xff09;1.4.Null&#xff08;空值&#xff09;1.5.Undefined&#xff08;未定义&#xff09;1.6.Object&#xff08;对象…

从WIFI到NB-IoT,探秘智能门锁的高科技接入方式

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! Hello大家好!我是小米,一个29岁、活力满满、热爱分享技术的小米!今天,我想和大家聊聊一个与智能家居密切相关的技术话题——智能门锁的接入方式。无…

标准正态分布的数据 tensorflow 实现正态分布图,python 编程,数据分析和人工智能

import tensorflow as tf import matplotlib.pyplot as plt # 设置随机种子以获得可重复的结果 tf.random.set_seed(42) # 生成正态分布的数据 # mean0 和 stddev1 表示生成标准正态分布的数据 # shape(1000,) 表示生成1000个数据点 data tf.random.normal(mean0, stddev1, …