【ARM Cortex-M3指南】3:Cortex-M3基础

文章目录

  • 三、Cortex-M3基础
    • 3.1 寄存器
      • 3.1.1 通用目的寄存器 R0~R7
      • 3.1.2 通用目的寄存器 R8~R12
      • 3.1.3 栈指针 R13
      • 3.1.4 链接寄存器 R14
      • 3.1.5 程序计数器 R15
    • 3.2 特殊寄存器
      • 3.2.1 程序状态寄存器
      • 3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器
      • 3.2.3 控制寄存器
    • 3.3 操作模式
    • 3.4 异常和中断
    • 3.5 向量表
    • 3.6 栈存储操作
      • 3.6.1 栈的基本操作
      • 3.6.2 Cortex-M3 栈的应用
      • 3.6.3 Cortex-M3 的双栈模型
    • 3.7 复位流程

三、Cortex-M3基础

3.1 寄存器

前面已经介绍过了,Cortex-M3处理器具有寄存器R0~R15以及多个特殊寄存器。 R0R12为通用目的寄存器,不过有些16位Thumb指令只能访问R0R7(低寄存器),而 32位Thumb-2指令则可以访问所有的寄存器,特殊寄存器具有预定义的功能,并且只能通过特殊寄存器访问指令操作。

3.1.1 通用目的寄存器 R0~R7

通用目的寄存器R0~R7也称作低寄存器,它们可以通过所有的16位Thumb指令和 32位Thumb-2指令访问。这些寄存器都是32位宽的,并且复位值为不可预测的。

3.1.2 通用目的寄存器 R8~R12

寄存器R8~R12也称作高寄存器,它们可以通过所有的Thumb-2指令访问,而有些 16位的Thumb指令则不可以。这些寄存器都是32位宽,并且复位值是不可预测的。

3.1.3 栈指针 R13

R13为栈指针(SP),Cortex-M3中存在两个SP,利用这种结构,我们可以设置两个独立的栈指针。在使用寄存器名为R13时,只能访问当前的SP,要访问另一个的话,只能通过特殊指令

  1. 从通用目的寄存器到特殊寄存器 - MSR
  2. 从特殊寄存器到通用目的寄存器 - MRS

这两个栈指针为:

  1. 主栈指针(MSP):在ARM文献中也叫SP_main,这是默认的SP,用于操作系统内核、异常处理和所有需要特权访问的应用程序代码。
  2. 进程栈指针(PSP):在ARM文献中也叫SP_process,用于基本的应用程序代码(未运行异常处理时)。

image.png

image.png

使用两个SP是没有必要的,简单的应用程序可以完全依赖MSP。SP用于像PUSH和POP之类的栈存储处理。

对于Cortex-M3,访问栈空间的指令为PUSH和POP,汇编语法如下(每个分号[;]之后的文字为注释)。

PUSH {R0}
步骤1:R13 = R13 - 4
步骤2:存储器[R13] = R0POP {R0}
步骤1:R0 = 存储器[R13]
步骤2:R13 = R13 + 4

Cortex-M3使用满递减的栈处理(本章的“栈存储操作”中有对这方面的详细介绍),因此,当新的数据存入栈后,SP减小。PUSH和POP通常用于在子例程开始时将寄存器内容保存至栈空间,之后会在子例程结束后将寄存器内容从栈中恢复。PUSH和POP可以在一条指令中操作多个寄存器:

subroutine_1
PUSH {R0 - R7, R12, R14}
...
POP {R0 - R7, R12, R14}
BX R14

在程序代码中,可以使用SP(栈指针)代替R13。这就意味着,在程序代码内部,MSP和PSP都可以被称作R13/SP。不过,你可以使用特殊寄存器访问指令(MRS/MSR)来操作特定的SP。

由于寄存器的PUSH和POP操作总是字对齐(0x4,0x8),故SP的第0位和第1位被硬连接为0,并且读出总是0。

image.png

3.1.4 链接寄存器 R14

R14为链接寄存器(LR),在汇编程序中,可以写作R14或LR。LR用于子例程或函数调用时保存返回地址,例如,在使用跳转链接(BL)指令时:
image.png

尽管PC的第0位总是为0(由于指令都是字对齐或者半字对齐的),LR的第0位是可读可写的。这是因为在Thumb指令集中,第0位通常用于指明ARM/Thumb状态,要将 Cortex-M3上实现的Thumb-2程序运行在其他支持Thumb-2技术的ARM处理器上,这个最低位(LSB)需要为可读可写的。

3.1.5 程序计数器 R15

R15就是PC,在汇编代码中可以使用R15或PC进行访问。由于Cortex-M3处理器的流水线特性,在读这个寄存器时,你会发现读出值和正在执行的指令位置不同,通常差4,例如:

image.png

对PC的写操作会引起跳转(但LR不会更新),由于指令地址必须是半字对齐的,PC读出值的LSB(最低位)总是0。不过,对于跳转,不管是通过写PC还是使用跳转指令,目标地址的LSB都应该置1,以指明当前处于Thumb状态;如果为0的话,处理器会试图切换至ARM状态,而Cortex-M3的这一操作会导致错误异常。

3.2 特殊寄存器

Cortex-M3处理器具有多个特殊寄存器:

  • 程序状态寄存器(PSR);
  • 中断屏蔽寄存器(PRIMASK、FAULTMASK、BASEPRI);
  • 控制寄存器(CONTROL)。

特殊寄存器只能通过指令MSRMRS访问,它们没有存储器地址:

  • MSR <special_reg> <reg>:写入特殊寄存器。
  • MRS <reg> <special_reg>:读取特殊寄存器。

3.2.1 程序状态寄存器

PSR分为三个状态寄存器:

  1. 应用程序状态寄存器 - APSR
  2. 中断程序状态寄存器 - IPSR(只读)
  3. 执行程序状态寄存器 - EPSR(只读)

这三个PSR可以通过特殊寄存器访问指令MSRMRS进行整体操作或者分开操作,整体操作时使用寄存器名xPSR

image.png

image.png

image.png

如果将这个寄存器同ARM7的当前程序状态寄存器(CPSR)相比,可能会发现ARM7中用的某些位域已经不存在了。由于Cortex-M3不具有ARM7定义的操作模式,模式(M)位就去掉了;Tumb(T)位变为了第24位;中断状态(I和F)位则被新的中断寄存器(PRIMASK)代替,这些寄存器同PSR是相互独立的。为了便于比较,传统ARM处理器的 CPSR寄存器如图3.5所示。

image.png

3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器

PRIMASK、FAULTMASK和BASEPRI寄存器用于禁止异常。

寄存器名描述
PRIMASK寄存器中仅有1位,在其置位时,允许不可屏蔽中断和硬件错误异常,其他所有中断和异常都会被屏蔽;默认为0,不屏蔽中断。
FAULTMASK寄存器中仅有1位,在其置位时,允许不可屏蔽中断NMI,其他所有中断和硬件错误处理异常都会被屏蔽;默认为0,不屏蔽中断。
BASEPRI寄存器中最多8位(取决于优先级的实际位宽),定义了屏蔽优先级。在其置位时,相同或者更低等级的所有中断都被禁止,更高优先级的中断仍可执行。如果设置为0,则屏蔽功能禁止(默认)。

在时间敏感的任务中需要暂时禁止中断时,可以使用PRIMASK和BASEPRI寄存器。当一个任务崩溃时,OS可以使用FAULTMASK暂时禁止错误处理。在这种情况下,任务崩溃时可能会产生多个不同错误。内核开始清理操作时,它也许不想被崩溃进程引起的其他错误打断,因此,利用FAULTMASK,OS内核就获得了处理错误状态的时间。

image.png

image.png
image.png

3.2.3 控制寄存器

控制寄存器用于定义特权等级和SP的选择,该寄存器为2位宽。

image.png

  1. CONTROL[1]

对于Cortex-M3,CONTROL[1]位在处理模式时总是0(使用MSP),不过在线程或者基本等级中,它可以是0或者1。

该位只有在内核处于特权线程下才可写,在其他模式下,该位是不允许进行写操作的。除了写这个寄存器外,也可以在异常返回时修改LR的第2位来修改这一位。

  1. CONTROL[0]

CONTROL[0]位只有在特权等级下可写,一旦进入用户等级,要想切换回特权状态,只能触发一次中断并且在异常处理中进行修改。

image.png

3.3 操作模式

当处理器运行在线程模式中时,它可以处在特权或用户等级,不过处理模式只能位于特权等级。当处理器退出复位时,它处于线程模式并且具有特权访问权限。

在用户访问等级(线程模式),对系统控制空间(SCS,存储器空间的一部分,用于配置寄存器和调试部件)的访问是不允许的。另外,访问特殊寄存器的指令(如MSR,访问APSR时除外)也不可以使用。如果用户访问等级的程序要访问SCS或特殊寄存器,错误异常就会产生。

处在特权访问等级的软件可以通过控制寄存器将程序切换至用户访问等级。异常发生时,处理器总会切换至特权状态,并且在退出异常处理时返回到之前的状态。用户程序无法直接通过写控制寄存器切回特权状态,在返回线程模式时,它必须通过设置控制寄存器的异常处理才可以切换至特权访问等级(见图3.7)。

image.png

对特权和用户访问等级的支持提供了一个更加安全和健壮的架构,例如,当用户程序错误时,它不会破坏嵌套向量中断控制器(NVIC)中的控制寄存器。另外,如果存储器保护单元(MPU)存在的话,用户程序对特权进程使用的存储器区域的访问可能会被禁止。

在简单的应用中,无须区分特权和用户访问等级。在这种情况下,也无须使用用户访问等级以及设置控制寄存器。

你可以将用户应用程序的栈同内核栈相分离,这样可以避免用户程序栈的错误操作引起的系统崩溃。根据这种设计,用户程序(运行在线程模式)使用PSP,而异常处理则使用 MSP。SP在进入或离开异常处理时自动切换(见3.6.3节),第8章有这个方面的详细介绍。

控制寄存器定义了处理器的模式和访问等级,当控制寄存器的第0位为0时,异常发生会引起处理器模式的改变(见图3.8和图3.9)。

image.png

当控制寄存器的第0位为1时(运行用户应用程序的线程),异常发生会引起处理器模式和访问等级的改变(见图3.10)。

只有在特权等级中,控制寄存器的第0位才是可编程的(见图2.5)。用户等级的程序要想切换至特权状态,它必须发起一个中断(例如,请求管理调用[SVC])并在中断处理中修改CONTROL[0]。

3.4 异常和中断

Cortex-M3支持多个异常,其中包括固定数量的系统异常和通常被称作IRQ的多个中断。根据个体设计的不同,Cortex-M3微控制器中断输人的数量也有所不同。外设产生的中断,除了系统节拍定时器,也被连接至中断输入信号上。中断输入的数量一般为16或 32,不过,有些微控制器的中断输入可能会更多(或更少)。

除了中断输入之外,处理器还有一个不可屏械中断(NMI)输入信号,NMI的实际使用情况取决于微控制器或片上系统(SoC)的设计。多数情况下,NMI可以连接至看门狗时钟,或者电压监控模块,这样在电压降到一定程度时处理器会收到警告。NMI异常随时可以激活,甚至是在内核刚刚退出复位后。

Cortex-M3支持的异常如表3.4所示。其中多个系统异常为错误处理异常,它们可由许多错误条件触发。NVIC也提供了多个错误状态寄存器,这样异常处理可以根据这些寄存器确定异常的原因。

如果要了解Cortex-M.3异常处理的细节,可以参考第7~9章的内容。

image.png

3.5 向量表

当Cortex-M3的异常发生并被处理器接受时,对应的异常处理就会执行。为了确定异常处理的起始地址,处理器使用了一种向量表机制。向量表是系统存储器中的字数据数组,每个元素代表了一种异常类型的起始地址。向量表的位置是可以重置的,该位置由NVIC中的重定位寄存器决定(见表3.5)。复位后,该重定位寄存器被置为0,因此,向量表在复位后位于地址0x0处。

image.png

例如,若复位的异常类型为1,那么复位向量的地址为1×4(每个字为4字节),也就是 0x00000004,NM1向量(类型2)位于2×4=0x00000008位置。地址0x00000000用于存放 MSP的初始值。

每个异常类型的LSB表示异常是否允许在Thumb状态中执行,由于Cortex-M3只支持Thumb指令,所有的异常向量的LSB都应该置1。

3.6 栈存储操作

对于Cortex-M3,栈的PUSH和POP除了可以被普通软件控制外,还可在进入或退出异常/中断处理时自动执行。本节中,我们来看一下软件栈操作(异常处理期间的栈操作在第9章中介绍)。

3.6.1 栈的基本操作

般来说,栈操作也就是存储器的写或读操作,只是地址被指定为SP。寄存器中的数据由PUSH操作存人栈存储中,而且稍后可以由POP操作恢复到寄存器中。在PUSH和 POP期间,SP的内容自动调整,因此,多次PUSH不会清除之前的压栈数据。

栈的功能为将寄存器内容存到存储器中,以便处理任务结束后它们还可以被恢复。例如,对于每次存储(PUSH),都必须有对应的读(POP),而且POP操作的地址应该同PUSH操作的地址相匹配。使用PUSH/POP指令时,SP自动增加/减小。

当程序控制返回到主程序时,R0~R2的内容同之前的一致,应该注意PUSH和POP的顺序:POP应是PUSH的反顺序。

由于PUSH和POP指令允许多次存储和加载,因此这些操作可以简化。在这种情况下,处理器会将寄存器POP的顺序自动反过来(见图3.12)。

image.png

RETURN可以同POP操作合并在一起,要实现这个目的,可以将LR存入栈中,并且在子例程结束时将其送回PC(见图3.13)。

image.png

3.6.2 Cortex-M3 栈的应用

Cortex-M3使用了一种满递减的栈操作模型,SP指向压入栈存储的最后一个数据,SP在新的PUSH操作前减小。图3.14为指令PUSH{R0}执行的例子。

image.png

对于POP操作,数据被从SP指向的位置中读出,然后SP增加。存储器位置的数据不会变化,但下次PUSH操作发生时则会被覆盖(见图3.15)。

由于每次PUSH/POP操作传输4字节的数据(每个寄存器包含1个字,也就是4字节),SP每次会增加/减小4字节,如果多于1个寄存器需要压栈或出栈则是4的倍数。

在Cortex-M3中,R13被定义为SP。当中断发生时,多个寄存器会自动压栈,在这个过程中,R13会被用作SP。类似地,在退出中断处理时,压栈的寄存器会自动地恢复/出栈,SP的值也会得到调整。

image.png

3.6.3 Cortex-M3 的双栈模型

之前已经提到Cortex-M3具有两个SP:MSP和PSP。实际使用哪个SP由控制寄存器的第1位控制(下面所说的CONTROL[1])。

当CONTROL[1]为0时,线程模式和处理模式都会使用MSP(见图3.16)。按照这种设计,主程序和异常处理共用相同的栈存储空间,这也是上电后的默认设置。

image.png

当CONTROL[1]为1时,线程模式使用PSP(见图3.17)。按照这种设计,主程序和异常处理可以使用独立的栈存储区域。这样用户程序的栈出现错误时,就不会破坏OS使用的栈了(假定用户程序只运行在线程模式,OS内核运行在处理模式)。

image.png

在这种情况下,应该注意的是,自动压栈和出栈机制将会使用PSP,不过异常处理中的栈操作会使用MSP。

也可以直接对PSP和MSP进行读/写操作,而无须考虑R13代表的含义。假定当前处于特权等级,你可以这样访问MSP和PSP的值:

image.png

一般来说,由于栈存储可能会用于存储局部变量,我们不建议在C函数中改变当前选定SP的值。要用汇编访问SP,可以使用MSR和MRS指令:

image.png

通过MRS指令读出PSP的值后,OS可以读出用户应用程序栈中的数据(如SVC操作前的寄存器内容)。另外,OS可以改变PSP指针数值,比如多任务系统上下文切换期间。

3.7 复位流程

在退出复位后,处理器会从存储器中读取两个字:

  1. 地址0x00000000:R13的初始值(SP)。
  2. 地址0x00000004:复位向量(程序执行的起始地址,LSB应该置1表示Thumb状态)。

image.png

这点同传统的ARM处理器不同,之前的ARM处理器从0x0地址开始执行程序,另外,之前的ARM设备中向量表为指令(你必须在此处放入一个跳转指令,异常处理则可以放在另外一个位置)。

对于Cortex-M3,MSP的初始值位于存储器映射的开始处,后面紧接着的是向量表,也就是向量的地址值(在程序执行过程中,向量表稍后可以被重新分配到另外一个地址)。另外,向量表的内容为地址值,而非跳转指令。向量表中的第一个向量(异常类型1)为复位向量,这是在处理器复位后读取的第二块数据。

由于Cortex-M3的栈操作为满递减的(存储前SP减小),SP的初始值应该置为栈顶后的第一个存储器地址。例如,若栈存储区域的范周为0x20007C00到0x20007FFF(1KB),栈的初始值应该置为0x20008000。

向量表在SP的初始值之后,第一个向量为复位向量。应该注意的是,在Cortex-M3中,向量表中的向量地址的最低位应置1,以表明它们为Thumb代码。由于这个原因,前面例子的复位向量为0x101,而启动代码是从0x100地址开始的(见图3.19)。取出复位向量后,Cortex-M3可以从复位向量地址处执行程序,并且开始正常操作。SP需要被初始化,这是因为复位后就可能会发生一些异常(如NMI),这些异常可能是需要栈存储的。

image.png

不同的开发工具在指定SP的初始值和复位向量时的方式可能不同,若要了解这方面更多的信息,最好参考开发工具提供的工程实例。第10章和第20章提供了ARM工具的一些例子,GNU工具链的例子则在第19章。

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

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

相关文章

使用FPGA实现串-并型乘法器

介绍 其实我们知道&#xff0c;用FPGA实现乘法器并不是一件很简单的事&#xff0c;而且在FPGA中也有乘法器的IP核可以直接调用&#xff0c;我这里完全就是为了熟悉一些FPGA的语法然后写了这样一个电路。 串-并型乘法器模块 从字面上看&#xff0c;串-并乘法器就是其中一个乘数…

Nodejs process.nextTick() 使用详解

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

OpenCV 为轮廓创建边界框和圆(62)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV检测凸包(61) 下一篇 :OpenCV如何为等值线创建边界旋转框和椭圆(62) ​ 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 cv::boundingRect使用 OpenCV 函数 cv::mi…

数据库(MySQL)—— 事务

数据库&#xff08;MySQL&#xff09;—— 事务 什么是事务事务操作未控制事务测试异常情况 控制事务一查看/设置事务提交方式&#xff1a;提交事务回滚事务 控制事务二开启事务提交事务回滚事务 并发事务问题脏读&#xff08;Dirty Read&#xff09;不可重复读&#xff08;Non…

数据结构练习题---环形链表详解

链表成环&#xff0c;在力扣中有这样的两道题目 https://leetcode.cn/problems/linked-list-cycle/ https://leetcode.cn/problems/linked-list-cycle-ii/description/ 这道题的经典解法是利用快慢指针&#xff0c;如果链表是一个环形链表&#xff0c;那么快指针(fast)和慢指…

关于MS-DOS时代的回忆

目录 一、MS-DOS是什么&#xff1f; 二、MS-DOS的主要功能有哪些&#xff1f; 三、MS-DOS的怎么运行的&#xff1f; 四、微软开源MS-DOS源代码 五、高手与漂亮女同学 一、MS-DOS是什么&#xff1f; MS-DOS&#xff08;Microsoft Disk Operating System&#xff09;是微软公…

工作问题记录React(持续更新中)

一、backdrop-filter:blur(20px); 毛玻璃效果&#xff0c;在安卓机上有兼容问题&#xff0c;添加兼容前缀也无效&#xff1b; 解决方案&#xff1a;让设计师调整渐变&#xff0c;不要使用该属性! 复制代码 background: radial-gradient(33% 33% at 100% 5%, #e9e5e5 0%, rgba…

C++类定义时成员变量初始化

在C11中允许在类定义时对成员变量初始化。 class A { public:A() { }void show(){cout << "m_a " << m_a << endl;cout << "m_b " << m_b << endl;} private:int m_a 10;//类定义时初始化int m_b; //没有初始化…

Microsoft 365 for Mac(Office 365)v16.84正式激活版

office 365 for mac包括Word、Excel、PowerPoint、Outlook、OneNote、OneDrive和Teams的更新。Office提供了跨应用程序的功能&#xff0c;帮助用户在更短的时间内创建令人惊叹的内容&#xff0c;您可以在这里创作、沟通、协作并完成重要工作。 Microsoft 365 for Mac(Office 36…

Delta lake with Java--liquid clustering

网上说liquid clustering还是实验阶段&#xff0c;python和scala有对应的函数&#xff0c;java没有&#xff0c;只能用sql语句来建表&#xff0c;尝试了两天&#xff0c;遇到很奇怪的情况&#xff0c;先上代码&#xff1a; import io.delta.tables.DeltaTable; import org.apa…

HTML_CSS学习:浮动

一、浮动简介 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>浮动_简介</title><style>div{width: 600px;height: 400px;background-color: #1c80d9;}img{float:…

智慧旅游引领旅游行业创新发展:借助智能科技的力量,实现旅游资源的优化配置和高效利用,推动旅游行业的转型升级和可持续发展

目录 一、引言 二、智慧旅游的定义与特点 1、信息化程度高 2、智能化服务丰富 3、互动性强 4、个性化服务突出 5、可持续性发展 三、智慧旅游在旅游行业创新发展中的作用 &#xff08;一&#xff09;优化旅游资源配置 &#xff08;二&#xff09;提升旅游服务质量 &…

VMware虚拟机下载安装教程【超详细】

推荐大佬文章&#xff1a;VMware下载安装教程(超详细)-CSDN博客 目录 一、VMware下载 二、VMware安装 一、VMware下载 1、进入VMware官网 2、点击“Products”&#xff0c;向下滑动 --> 选择“Workstation Pro” 3、向下滑动&#xff0c;找到并选择“Download VMware Wo…

智慧文旅展现文化新风貌,科技助力旅行品质升级:借助智慧技术,文旅产业焕发新生机,为旅行者带来更高品质的文化体验之旅

一、引言 在数字化、智能化的浪潮下&#xff0c;文旅产业正迎来前所未有的发展机遇。智慧文旅作为文旅产业与信息技术深度融合的产物&#xff0c;不仅为旅行者带来了全新的文化体验&#xff0c;也为文旅产业注入了新的活力。本文旨在探讨智慧文旅如何借助智慧技术展现文化新风…

pyinstaller打包pytorch和transformers程序

记录使用pyinstaller打包含有pytorch和transformers库的程序时遇到的问题和解决方法。 环境和版本信息 操作系统&#xff1a;Windows 11 Python&#xff1a;3.10.12 pyinstaller&#xff1a;5.13.0 torch&#xff1a;2.2.2 transformers&#xff1a;4.40.1 打包过程和问…

LLaMA详细解读

LLaMA 是目前为止&#xff0c;效果最好的开源 LLM 之一。精读 LLaMA 的论文及代码&#xff0c;可以很好的了解 LLM 的内部原理。本文对 LLaMA 论文进行了介绍&#xff0c;同时附上了关键部分的代码&#xff0c;并对代码做了注释。 摘要 LLaMA是一个系列模型&#xff0c;模型参…

深入理解 Java 并发:AbstractQueuedSynchronizer 源码分析

序言 在多线程编程中&#xff0c;同步机制是保障线程安全和协调线程之间操作顺序的重要手段。AQS 作为 Java 中同步机制的基础框架&#xff0c;为开发者提供了一个灵活且高效的同步工具。本文将通过对 AQS 源码的分析&#xff0c;解读 AQS 的核心实现原理&#xff0c;并深入探…

使用FastGPT+OneAPI在本地使用Llama3

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01;他的重要特点就是工作流编排。 工作流编排&#xff1a;基于 Flow 模块的工作…

微信小程序 uniapp家庭食谱菜谱食材网上商城系统小程序ko137

随着生活节奏的不断加快&#xff0c;越来越多的人因为工作忙而没有时间自己出去订购喜欢的菜品。随着Internet的飞速发展&#xff0c;网络已经成为我们日常生活中必不可少的部分&#xff0c;越来越多的人也接受了电子商务这种快捷、方便的交易方式。网上订餐其独有的便捷性和直…

口才训练:如何用声音和语言展现自我魅力

口才训练&#xff1a;如何用声音和语言展现自我魅力 这里有一篇1270字左右的文章&#xff0c;主要介绍如何用声音和语言来展现自我魅力&#xff1a; 口才训练是提升个人魅力的重要途径之一。魅力不仅取决于外表&#xff0c;更重要的是声音和语言的运用。良好的语言表达能力可以…