先说下CC3200存在2个16*8的fifos, 分别用于发送和接收

当fifos被disable时,将会作为一个1字节深度的保持寄存器,

所以无论fifos是开是关,发送和接收都绕不开fifos

DMA

由于发送和接收都绕不过fifos,所以DMA也绕不开FIFOS.

MAP_UARTFIFOLevelSet(UARTA0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

上述代码的意思就是,设定FIFO,UART_FIFO_TX4_8当达到1/2 * 16字节时才会触发DMA传输,小于8字节时不触发DMA传输,所以这个时候要用到UART外设自带的接收超时中断,类似于STM32的idle中断.

需要注意的是,触发DMA后,仅仅是把数据从uart外设寄存器搬运到了用户指定的ram中

DMA中也有一个阈值参数,叫做仲裁大小,他决定了DMA每次最多连续搬运字节数.仲裁大小别称ARB, ARB<=FIFO阈值

所以在传输1024字节数据时,ARB设定为32,DMA就会以32字节为单位进行数据搬运

此外,在手册里有如下说明.

The arbitration size can also be thought of as a burst size, as it is the maximum number of items that are transferred at any one time in a burst. Here, the term arbitration refers to determination of μDMA channel priority, not arbitration for the bus. When the μDMA controller arbitrates for the bus, the processor always takes priority. Furthermore, the μDMA controller is held off whenever the processor must perform a bus transaction on the same bus, even in the middle of a burst transfer.

即对于总线竞争时,CPU > DMA, 上面的ARB大小的仲裁仅为DMA多通道之间优先级的仲裁,每搬运ARB SIZE大小的数据后检查一次DMA通道的优先级.

DMA

串口超时中断

UART的超时中断触发条件

这个和32的IDLE功能类似,但是触发机制完全不同.

32是超过一定时间没接收数据就触发,但是触发后除非再次接收到数据否则不会再触发

这个触发机制看原文描述

The receive timeout interrupt is asserted when the receive FIFO is not empty

and no further data is received over a 32-bit period when the HSE bit is clear, or over a 64-bit period when the HSE bit is set

即满足FIFO不为空,且在32周期或者64周期没接收(根据HSE位区分)FIFO数据。简单理解只要FIFO内存在数据超过一定时间就会触发,如果你一直不接受数据,则一直触发哪怕清除中断位后还是会不停触发.4

这个和FIFO阈值及ARB强相关。

FIFO阈值决定了FIFO达到多少数据触发DMA搬运,ARB决定了DMA单次搬运的数据大小.

举两个例子

FIFO = 1/8触发,ARB = 2 则仅在FIFO剩余1个字节时触发RT,为什么使用FIFO仅剩1个字节的字眼,因为当你单次发送奇数时即会触发该中断.

FIFO = 1/4触发,ARB = 2 ,FIFO字节大于等于4触发,每次搬运2个,即无论发送多少个都会触发RT中断

所以设定fifo要注意,如果fifo大小和URB大小一致,会导致发送数据为URB大小时,数据被完全搬运到了缓存,导致不触发RT中断.

DMARX_INT

这个也是串口的中断,体现在代码中叫做UART_INT_DMARX

这个中断在手册中描述如下

If DMA is enabled, then the μDMA controller triggers an interrupt when a transfer is complete. The
interrupt occurs on the UART interrupt vector. Therefore, if interrupts are used for UART operation and
DMA is enabled, the UART interrupt handler must be designed to handle the μDMA completion interrupt.

经过实际测试,在基础模式下,这个在仅在dma传输完成设定大小的数据后触发.

CC3200的DMA中断和STM32不太一样

参考文档给出说明如下所示

Few μDMA channels are dedicated to software-initiated transfers. This channel also has a dedicated
interrupt to signal completion of a μDMA transfer. A transfer is initiated by software by first configuring and
enabling the transfer, and then issuing a software request using the DMA Channel Software Request
(DMASWREQ) register. For software-based transfers, use the auto transfer mode.

When a μDMA transfer is complete, a dma_done signal is sent to the peripheral that initiated the μDMA
event. Interrupts can be enabled within the peripheral to trigger on μDMA transfer completion. If the
transfer uses the software μDMA channel, then the completion interrupt occurs on the dedicated software
μDMA interrupt vector.

可以看到DMA的中断仅针对软件dma有用,也就是说仅针对m to m有用,针对外设相关DMA,所有中断都发送到外设自己的中断内处理.

此外,本来想使用ping-pong模式,但是调试了1天在最开始接受的几组数据中始终会有丢包现象,不知道哪地方的设置出问题了,所以最后选用了基础模式.

示例1 测试rx及dmarx的功能

本demo测试基本dma传输.

主要测试超时中断及uart_dmarx

// Driverlib includes
#include "hw_types.h"
#include "hw_uart.h"
#include "hw_ints.h"
#include "hw_memmap.h"
#include "hw_common_reg.h"
#include "interrupt.h"
#include "hw_apps_rcm.h"
#include "prcm.h"
#include "rom.h"
#include "prcm.h"
#include "rom_map.h"
#include "gpio.h"
#include "utils.h"
#include "uart.h"
#include "udma.h"// user includes
#include "pin_mux_config.h"
#include "uart_if.h"
#include "systick_if.h"
#include "wifi.h"
#include "wlan.h"
#include "stdio.h"
#include "udma_if.h"
//*****************************************************************************
//                 GLOBAL VARIABLES -- Start
//*****************************************************************************
#if defined(ccs)extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)extern uVectorEntry __vector_table;
#endif
//*****************************************************************************
//                 GLOBAL VARIABLES -- End
//*****************************************************************************//*****************************************************************************
//                      LOCAL FUNCTION PROTOTYPES
//*****************************************************************************
void LEDBlinkyRoutine();
static void BoardInit(void);//*****************************************************************************
//                      LOCAL FUNCTION DEFINITIONS
//*****************************************************************************//*****************************************************************************static void BoardInit(void)
{/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS//// Set vector table base//
#if defined(ccs)MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)MAP_IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif//// Enable Processor//MAP_IntMasterEnable();MAP_IntEnable(FAULT_SYSTICK);PRCMCC3200MCUInit();
}
extern void tcp_rate_test_example(wifi_t wifi);
extern void cw_burst_forever();
#define UART_TXBUF_SIZE (256)
#define UART_RXBUF_SIZE (256)
static unsigned char g_ucTxBuf[UART_TXBUF_SIZE];
static unsigned char g_ucRxBufA[UART_RXBUF_SIZE];
static unsigned char g_ucRxBufB[UART_RXBUF_SIZE];
void
UART0IntHandler(void)
{static long recv_cnt = 0;unsigned long ulStatus;unsigned long ulMode;long cnt = 0;//// Read the interrupt status of the UART.//ulStatus = MAP_UARTIntStatus(UARTA0_BASE, 1);//// Clear any pending status, even though there should be none since no UART// interrupts were enabled.  //MAP_UARTIntClear(UARTA0_BASE, ulStatus);ulMode = MAP_uDMAChannelModeGet(UDMA_CH8_UARTA0_RX);if(ulMode == UDMA_MODE_STOP){Report("dma restart\r\n");//// Set up the next transfer for the "A" buffer, using the primary// control structure.  When the ongoing receive into the "B" buffer is// done, the uDMA controller will switch back to this one.  //UDMASetupTransfer(UDMA_CH8_UARTA0_RX, UDMA_MODE_BASIC,8,UDMA_SIZE_8, UDMA_ARB_4,(void *)(UARTA0_BASE + UART_O_DR), UDMA_SRC_INC_NONE,g_ucRxBufA, UDMA_DST_INC_8);// return;}if(ulStatus & UART_INT_RT) {while(MAP_UARTCharsAvail(UARTA0_BASE)) {uint8_t data = MAP_UARTCharGetNonBlocking(UARTA0_BASE);cnt ++;Report("cnt %d:0x%02x\r\n", cnt, data);if (cnt > 5)break;}}else if (ulStatus & UART_INT_DMARX){Report("rx int\r\n");}}
voidInitUART0Transfer(void)
{unsigned int uIdx;//// Fill the TX buffer with a simple data pattern.//for(uIdx = 0; uIdx < UART_TXBUF_SIZE; uIdx++){g_ucTxBuf[uIdx] = 65;}MAP_PRCMPeripheralReset(PRCM_UARTA0);MAP_PRCMPeripheralClkEnable(PRCM_UARTA0,PRCM_RUN_MODE_CLK);MAP_UARTConfigSetExpClk(CONSOLE,SYSCLK, UART_BAUD_RATE,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE));MAP_uDMAChannelAssign(UDMA_CH8_UARTA0_RX);MAP_uDMAChannelAssign(UDMA_CH9_UARTA0_TX);MAP_UARTIntRegister(UARTA0_BASE,UART0IntHandler);//// Set both the TX and RX trigger thresholds to 4.  This will be used by// the uDMA controller to signal when more data should be transferred.  The// uDMA TX and RX channels will be configured so that it can transfer 4// bytes in a burst when the UART is ready to transfer more data.//MAP_UARTFIFOLevelSet(UARTA0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX2_8);//// Enable the UART for operation, and enable the uDMA interface for both TX// and RX channels.//MAP_UARTEnable(UARTA0_BASE);//// Enable the UART peripheral interrupts. uDMA controller will cause an // interrupt on the UART interrupt signal when a uDMA transfer is complete.//MAP_UARTIntEnable(UARTA0_BASE,UART_INT_DMARX);MAP_UARTIntEnable(UARTA0_BASE,UART_INT_RT);UDMASetupTransfer(UDMA_CH8_UARTA0_RX,UDMA_MODE_BASIC,//                      sizeof(g_ucRxBufA),8,UDMA_SIZE_8,UDMA_ARB_4,(void *)(UARTA0_BASE+UART_O_DR),UDMA_SRC_INC_NONE,(void *)g_ucRxBufA,UDMA_DST_INC_8);MAP_UARTDMAEnable(UARTA0_BASE,UART_DMA_RX);
}void main()
{BoardInit();PinMuxConfig();SysTickInit();InitTerm();UDMAInit();// wifi_t wifi = wifi_create();
#define GPIOSetLevel(gpio_port, gpio_pin, value) GPIOPinWrite(gpio_port, gpio_pin, value != 0 ? gpio_pin : 0)// wifi_connect(wifi, "ultra-wifi", "ultra@2021", SL_SEC_TYPE_WPA_WPA2);// wifi_connect(wifi, "360WiFi-864040", "87654321", SL_SEC_TYPE_WPA_WPA2);// wifi_connect(wifi, "quanjing_test", "Iot@tytc00!", SL_SEC_TYPE_WPA_WPA2);InitUART0Transfer();while (1){// cw_burst_forever();// tcp_rate_test_example(wifi);// GPIOSetLevel(GPIOA1_BASE, GPIO_PIN_1, !GPIOPinRead(GPIOA1_BASE,GPIO_PIN_1));// UTUtilsDelay(10000 * 1000);}
}

示例2 测试basic dma2M全速接收串口数据

// Driverlib includes
#include "hw_types.h"
#include "hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"#include "hw_uart.h"
#
#include "uart.h"
#include "udma.h"// sdk user includes
#include "uart_if.h"
#include "udma_if.h"
#include "systick_if.h"// user includes
#include "uart_itf.h"
#include "RingBuf.h"
#undef UART_BAUD_RATE
// #define UART_BAUD_RATE  115200
#define UART_BAUD_RATE  2000000
#define SYSCLK          80000000#define UART_TXBUF_SIZE (1024)
#define UART_RXBUF_SIZE (1024)
static unsigned char g_ucRxBufA[UART_RXBUF_SIZE];static rb_t rb;
static unsigned char rx_data[UART_RXBUF_SIZE * 100];static uint64_t last_time = 0;
static void UARTIntHandler(void)
{unsigned long ulStatus;unsigned long ulMode;ulStatus = MAP_UARTIntStatus(UART_ITF_BASE, 1);MAP_UARTIntClear(UART_ITF_BASE, ulStatus);Report("ulStatus:%x\r\n", ulStatus);if (ulStatus & UART_INT_DMARX){       ulMode = MAP_uDMAChannelModeGet(UART_ITF_RX_DMA_CH);if(ulMode == UDMA_MODE_STOP){rbWrite(&rb, g_ucRxBufA, UART_RXBUF_SIZE);UDMASetupTransfer(UART_ITF_RX_DMA_CH,UDMA_MODE_BASIC,sizeof(g_ucRxBufA),//    8,UDMA_SIZE_8,UDMA_ARB_8,(void *)(UART_ITF_BASE+UART_O_DR),UDMA_SRC_INC_NONE,(void *)g_ucRxBufA,UDMA_DST_INC_8);}}else if(ulStatus & UART_INT_RT) {UDMAStopTransfer(UART_ITF_RX_DMA_CH);uint32_t received = UART_RXBUF_SIZE - MAP_uDMAChannelSizeGet(UART_ITF_RX_DMA_CH);if (received != 0 && received <=  UART_RXBUF_SIZE){rbWrite(&rb, g_ucRxBufA, received);UDMASetupTransfer(UART_ITF_RX_DMA_CH,UDMA_MODE_BASIC,sizeof(g_ucRxBufA),//    8,UDMA_SIZE_8,UDMA_ARB_8,(void *)(UART_ITF_BASE+UART_O_DR),UDMA_SRC_INC_NONE,(void *)g_ucRxBufA,UDMA_DST_INC_8);}while(MAP_UARTCharsAvail(UART_ITF_BASE)) {uint8_t data = MAP_UARTCharGetNonBlocking(UART_ITF_BASE);rbWrite(&rb, &data, 1);}}}void uart_itf_init(void)
{UDMAInit();MAP_PRCMPeripheralReset(UART_ITF_PRCM);MAP_PRCMPeripheralClkEnable(UART_ITF_PRCM,PRCM_RUN_MODE_CLK);MAP_UARTConfigSetExpClk(UART_ITF_BASE,SYSCLK, UART_BAUD_RATE,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE));MAP_uDMAChannelAssign(UART_ITF_RX_DMA_CH);// MAP_uDMAChannelAssign(UART_ITF_TX_DMA_CH);MAP_UARTIntRegister(UART_ITF_BASE,UARTIntHandler);MAP_UARTFIFOLevelSet(UART_ITF_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);MAP_UARTEnable(UART_ITF_BASE);MAP_UARTIntEnable(UART_ITF_BASE,UART_INT_DMARX | UART_INT_RT);UDMASetupTransfer(UART_ITF_RX_DMA_CH,UDMA_MODE_BASIC,sizeof(g_ucRxBufA),//    8,UDMA_SIZE_8,UDMA_ARB_8,(void *)(UART_ITF_BASE+UART_O_DR),UDMA_SRC_INC_NONE,(void *)g_ucRxBufA,UDMA_DST_INC_8);MAP_UARTDMAEnable(UART_ITF_BASE,UART_DMA_RX);rbInit(&rb, rx_data, sizeof(rx_data));
}int32_t uart_itf_get_can_read(void)
{return rbCanRead(&rb);
}int32_t uart_itf_recv(void *data, uint32_t count)
{return rbRead(&rb, data, count);
}int32_t uart_itf_send(void *data, uint32_t count)
{for (int i = 0; i < count; i++){while (UARTBusy(UART_ITF_BASE));UARTCharPut(UART_ITF_BASE, ((uint8_t *)data)[i]);}return count;
}#define SEND_CHUNK_SIZE 1460
void test_uart_recv_basic_process()
{uart_itf_init();uint64_t total_bytes = 0;uint64_t max_size = 0;uint64_t old_time = UTUtilsGetSysTime();uint64_t new_time = 0;char buf[SEND_CHUNK_SIZE * 3] = {0};while(1){long size = uart_itf_get_can_read();if (size > 0){long len = uart_itf_recv(buf, (size > sizeof(buf)) ? sizeof(buf) : size);total_bytes += len;max_size = size > max_size ? size : max_size;Report("t:%lld l:%ld %ld %ld\r\n", total_bytes, len, size, max_size);old_time = new_time;}new_time = UTUtilsGetSysTime();if (new_time - old_time > 800){total_bytes = 0;max_size = 0;old_time = new_time;}}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从游戏NPC到手术助手:Agent AI重构多模态交互,具身智能打开AGI新大门

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《GPT多模态大模型与AI Agent智能体》&#xff08;跟我一起学人工智能&#xff09;【陈敬雷编著】【清华大学出版社】 清华《GPT多模态大模型与AI Agent智能体》书籍配套视频课程【陈敬雷…

Lesson 29 Taxi!

Lesson 29 Taxi! taxi n.出租车 同义词:cab n.出租车 相关:taxi meter计价器 taxi stand taxi rank 出租车站 call ataxi 叫车&#xff0c;打车 例句:对不起,请问出租车站在哪里? Excuse me, do you know where the taxi rank is please? land v.着陆&#xff0c;登陆n.陆地…

怎样将allegro的brd文件转化为AD的PCB文件

由于工作需要将allegro的PCB转成ad给同事&#xff0c;在使用AD软件导入Allegro的brd格式文件时出现各种的异常报错弹窗问题&#xff0c;现分享两种将Allegro PCB文件导入到AD中的方法。一、第1种方法使用高版本的AD软件&#xff08;AD22&#xff0c;同时操作电脑需安装了Allegr…

[免费]【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts)【论文+源码+SQL脚本】

大家好&#xff0c;我是python222_小锋老师&#xff0c;看到一个不错的【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)&#xff0c;分享下哈。 项目视频演示 【免费】【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts爬虫) Pytho…

什么是CI/CD?

CI/CD是持续集成&#xff08;Continuous Integration&#xff09;和持续交付/持续部署&#xff08;Continuous Delivery/Continuous Deployment&#xff09;的缩写&#xff1a;持续集成&#xff08;Continuous Integration, CI&#xff09;&#xff1a;CI是一种开发实践&#x…

【Linux】重生之从零开始学习运维之Mysql

一主一从主12主机准备工作mkdir -p /data/mysql/logbin chown -R mysql:mysql /data/mysql主节点mysql配置vim /etc/my.cnf.d/mysql-server.cnf server-id177 log_bin/data/mysql/logbin/mysql-bin default_authentication_pluginmysql_native_password查看效果systemctl resta…

Trust Management System (TMS)

Trust Management System &#xff08;TMS&#xff09;信托管理系统学习信托管理系统&#xff08;TMS&#xff09;是一种用于高效管理信托业务的综合平台&#xff0c;涵盖客户信息、资产配置、风险监控等功能。通过学习TMS&#xff0c;可以掌握信托产品设计、业务流程优化及合规…

Spring Boot中使用Bouncy Castle实现SM2国密算法(与前端JS加密交互)

Spring Boot中使用Bouncy Castle实现SM2国密算法&#xff08;与前端JS加密交互&#xff09;一、环境准备二、核心实现三、前后端交互流程四、关键问题解决方案五、常见问题排查六、最佳实践建议在现代Web应用中&#xff0c;数据安全传输至关重要。SM2作为我国自主设计的非对称加…

机器学习sklearn:随机森林的决策树

bg&#xff1a;对比决策树来说&#xff0c;搞多几棵树就是随机森林了rlf_1 [] rlf_2 [] for i in range(10):rfc RandomForestClassifier(n_estimators25)rfc_s cross_val_score(rfc, wine.data, wine.target, cv10).mean()rlf_1.append(rfc_s)clf DecisionTreeClassifier…

上海月赛kk

1.十六进制#include<bits/stdc.h> using namespace std;int n;int main(){cin>>n;stack<int>re;if(n<16)cout<<0;while(n){re.push(n%16);n/16;}while(!re.empty()){int xre.top();re.pop();if(x<10)cout<<x;else cout<<char(Ax-10)…

暑期算法训练.12

目录 52. 力扣1 两数之和 52.1 题目解析&#xff1a; 52.2 算法思路&#xff1a; 52.3 代码演示&#xff1a; ​编辑 52.4 总结反思&#xff1a; 53 面试题&#xff1a;判定是否互为字符重排 53.1 题目解析&#xff1a; 53.2 算法思路&#xff1a; 53.3 代码演示&…

MySQL时间处理完全指南:从存储到查询优化

时间是数据库中最活跃的数据维度之一&#xff0c;正确处理时间数据关系到系统稳定性、数据分析准确性和业务逻辑正确性。本文将深入剖析MySQL时间处理的完整知识体系。一、MySQL时间数据类型详解1. 核心时间类型对比类型存储空间范围特性时区影响DATE3字节1000-01-01~9999-12-3…

Text2SQL 智能问答系统开发-预定义模板(二)

背景 在构建一个支持多轮对话的 Text2SQL 系统过程中&#xff0c;我完成了以下关键功能&#xff1a; 已完成 基础 Text2SQL 功能实现 实现用户输入自然语言问题后&#xff0c;系统能够自动生成 SQL 并执行返回结果。用户交互优化 支持用户通过补充信息对查询进行调整&#xff0…

JavaScript 异步编程:Promise 与 async/await 详解

一、Promise 1. 什么是 Promise&#xff1f; Promise 是 JavaScript 中用于处理异步操作的对象&#xff0c;它代表一个异步操作的最终完成&#xff08;或失败&#xff09;及其结果值。 2. Promise 的三种状态 ​​Pending&#xff08;待定&#xff09;​​&#xff1a;初始状态…

OS架构整理

OS架构整理引导启动部分bios bootloader区别启动流程&#xff08;x86 BIOS 启动&#xff09;&#xff1a;biosboot_loader3.切换进保护模式实模式的限制如何切换进保护模式加载kernel到内存地址1M加载内核映像文件elf一些基础知识链接脚本与代码数据段创建GDT表段页式内存管理显…

【WRF-Chem第二期】WRF-Chem有关 namelist 详解

目录namelist 选项&#xff1a;chem_opt 的选择其他化学相关的 namelist 选项气溶胶光学属性与输出边界与初始条件配置&#xff08;气体&#xff09;参考本博客详细介绍 WRF-Chem有关 namelist 选项。 namelist 选项&#xff1a;chem_opt 的选择 chem_opt 是什么&#xff1f;…

STM32-USART串口实现接收数据三种方法(1.根据\r\n标志符、2.空闲帧中断、3.根据定时器辅助接收)

本章概述思维导图&#xff1a;USART串口初始化配置串口初始化配置在&#xff08;STM32-USART串口初始化章节有详细教程配置&#xff09;&#xff0c;本章不做讲解直接代码示例&#xff0c;本章重点在于串口实现接收数据三种方法&#xff1b;配置USART1串口接收初始化函数步骤&a…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博评论数据可视化分析-点赞区间折线图实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解微博评论数据可视化分析-点赞区间折线图实现…

Unity_SRP Batcher

SRP Batcher 全面解析&#xff1a;原理、启用、优化与调试一、什么是 SRP Batcher&#xff1f;SRP Batcher 是 Unity Scriptable Render Pipeline&#xff08;URP、HDRP 或自定义 SRP&#xff09; 专属的 CPU 渲染性能优化技术&#xff0c;核心目标是 减少材质切换时的 CPU 开销…

详解Vite 配置中的代理功能

在前端开发过程中&#xff0c;你可能经常会遇到一个头疼的问题&#xff1a;当你在本地启动的前端项目中调用后端接口时&#xff0c;浏览器控制台会报出类似 “Access to fetch at ‘http://xxx’ from origin ‘http://localhost:3000’ has been blocked by CORS policy” 的错…