TMS320F28377D库函数操作(CLA程序移植及使用)
TMS320F28377D的CLA官方程序移植及使用
目录
0.写在前面
CLA的整个移植过程非常复杂,如果对于初学者可以从下往上看,先能移植起来再看原理
好多人都在要这份工程,我的工程都开源在gitee上了,链接在下面,如果需要可以自取。如果链接失效等问题可以评论区里告诉我,加油。
TMS320F28377D_AloneCPU_CodeLearn: TMS320F2877D单核程序开发 (gitee.com)
1.CLA介绍
CLA是什么呢?网上有很多说法,什么什么规律加速器,一堆名词着实头疼。其实很简单,在使用DSP的时候,总会有大量的计算,从简单的加减乘除,到正弦,到快速傅里叶,滤波器等都会要计算。此时,如果用CPU就不能操控其他外设了,在这种情况下就可以用CLA了。CLA你可以理解成DSP中专门用于计算的模块,正因如此,CLA不能初始化模块,配置模块,相反在计算是CLA的专场。如果读者用过cortex-M4内核的芯片就知道M4内核的芯片有对DSP库的支持,在DSP里CLA就如同MCU中DSP的作用,是专门用于计算的模块。
2.CLA使用前提
首先在开始前你要对TI的CMD的文件,如果读者是首次接触或是像我一样是STM32开发者转DSP的话,要有一个准备去写CMD文件,那么什么是CMD文件呢?假设芯片内的存储是一个仓库,那么你就是仓库管理员,你需要对仓库的每一部分都很熟悉,哪些地方是可以堆放“危险品”的,哪些地方可以堆放“长期滞留”品的,在STM32中几乎很少会考虑到这些内容,但是在使用DSP的东西是难以避免的。
上图是F28377D的内部存储器映射
可以看到有些区域是CLA可以访问,有些区域是DMA访问的所以在这种情况下你要对这些内存区域熟悉,并能合理的管理每一块区域。通过编写CMD文件合理地管理每一块区域。在CLA的使用中随时都需要你关注内存的情况。
3. 初始化程序
/*
* CLA_init.c
*
* Created on: 2023年5月1日
* Author: 18752
*/
#include "CLA_init.h"
#pragma DATA_SECTION(fVal,"CpuToCla1MsgRAM");
float fVal;
#pragma DATA_SECTION(fResult,"Cla1ToCpuMsgRAM");
float fResult;
#pragma DATA_SECTION(IOBuffer,"IOBuffer")
float IOBuffer[(256+1)*2] = {
#include "ffttest.h"
};
//
// CLA_runTest - Execute CLA task tests for specified vectors
//
void CLA_runTest(unsigned char RTest)
{
switch(RTest)
{
case 1: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_1); break;
case 2: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_2); break;
}
WAITSTEP;
}
void CLA_init()
{
EALLOW;
CLA_DSP_initEpie();
CLA_DSP_configClaMemory();
CLA_DSP_initCpu1Cla1();
EDIS;
}
void CLA_DSP_initEpie()
{
Interrupt_initModule();
Interrupt_initVectorTable();
}
void CLA_DSP_configClaMemory(void)
{
extern uint32_t Cla1ProgRunStart, Cla1ProgLoadStart, Cla1ProgLoadSize;
extern uint32_t CLA1fftTablesRunStart, CLA1fftTablesLoadStart, CLA1fftTablesLoadSize;
EALLOW;
#ifdef _FLASH
// Copy over code and tables from FLASH to RAM
memcpy((uint32_t *)&Cla1ProgRunStart, (uint32_t *)&Cla1ProgLoadStart,
(uint32_t)&Cla1ProgLoadSize);
memcpy((uint32_t *)&CLA1fftTablesRunStart, (uint32_t *)&CLA1fftTablesLoadStart,
(uint32_t)&CLA1fftTablesLoadSize);
#endif //_FLASH
// Initialize and wait for CLA1ToCPUMsgRAM
MemCfg_initSections(MEMCFG_SECT_MSGCLA1TOCPU);
while (!MemCfg_getInitStatus(MEMCFG_SECT_MSGCLA1TOCPU)){};
// Initialize and wait for CPUToCLA1MsgRAM
MemCfg_initSections(MEMCFG_SECT_MSGCPUTOCLA1);
while (!MemCfg_getInitStatus(MEMCFG_SECT_MSGCPUTOCLA1)){};
// Select LS0-LS1RAM to be the programming space for the CLA
// First configure the CLA to be the master for LS0 and then
// set the space to be a program block
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS0,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS0,MEMCFG_CLA_MEM_PROGRAM);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS1,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS1,MEMCFG_CLA_MEM_PROGRAM);
//Next configure LS2-LS5RAM as data spaces for the CLA
// First configure the CLA to be the master for LSx and then
// set the spaces to be code blocks
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS2,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS2, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS3,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS3, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS4,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS4, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS5,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS5, MEMCFG_CLA_MEM_DATA);
}
void CLA_DSP_initCpu1Cla1(void)
{
// Compute all CLA task vectors
// On Type-1 CLAs the MVECT registers accept full 16-bit task addresses as
// opposed to offsets used on older Type-0 CLAs
//
// Suppressing #770-D conversion from pointer to smaller integer
// The CLA address range is 16 bits so the addresses passed to the MVECT
// registers will be in the lower 64KW address space. Turn the warning
// back on after the MVECTs are assigned addresses
//
#pragma diag_suppress=770
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_1,(uint16_t)&Cla1Task1);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_2,(uint16_t)&Cla1Task2);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_3,(uint16_t)&Cla1Task3);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_4,(uint16_t)&Cla1Task4);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_5,(uint16_t)&Cla1Task5);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_6,(uint16_t)&Cla1Task6);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_7,(uint16_t)&Cla1Task7);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_8,(uint16_t)&Cla1Task8);
#pragma diag_warning=770
// Enable IACK instruction to start a task on CLA in software
// for all 8 CLA tasks
CLA_enableIACK(CLA1_BASE);
CLA_enableTasks(CLA1_BASE, CLA_TASKFLAG_ALL);
// Configure the vectors for the end-of-task interrupt for all
// 8 tasks
Interrupt_register(INT_CLA1_1, &cla1Isr1);
Interrupt_register(INT_CLA1_2, &cla1Isr2);
Interrupt_register(INT_CLA1_3, &cla1Isr3);
Interrupt_register(INT_CLA1_4, &cla1Isr4);
Interrupt_register(INT_CLA1_5, &cla1Isr5);
Interrupt_register(INT_CLA1_6, &cla1Isr6);
Interrupt_register(INT_CLA1_7, &cla1Isr7);
Interrupt_register(INT_CLA1_8, &cla1Isr8);
}
这是CLA的存储分配,没错程序里也要有。这是初始化部分,它管理着你内存是如何分配的,没有这部分CLA无法完成初始化。
void CLA_DSP_initEpie()
{
Interrupt_initModule();
Interrupt_initVectorTable();
}
void CLA_DSP_initCpu1Cla1(void)
{
// Compute all CLA task vectors
// On Type-1 CLAs the MVECT registers accept full 16-bit task addresses as
// opposed to offsets used on older Type-0 CLAs
//
// Suppressing #770-D conversion from pointer to smaller integer
// The CLA address range is 16 bits so the addresses passed to the MVECT
// registers will be in the lower 64KW address space. Turn the warning
// back on after the MVECTs are assigned addresses
//
#pragma diag_suppress=770
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_1,(uint16_t)&Cla1Task1);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_2,(uint16_t)&Cla1Task2);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_3,(uint16_t)&Cla1Task3);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_4,(uint16_t)&Cla1Task4);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_5,(uint16_t)&Cla1Task5);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_6,(uint16_t)&Cla1Task6);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_7,(uint16_t)&Cla1Task7);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_8,(uint16_t)&Cla1Task8);
#pragma diag_warning=770
// Enable IACK instruction to start a task on CLA in software
// for all 8 CLA tasks
CLA_enableIACK(CLA1_BASE);
CLA_enableTasks(CLA1_BASE, CLA_TASKFLAG_ALL);
// Configure the vectors for the end-of-task interrupt for all
// 8 tasks
Interrupt_register(INT_CLA1_1, &cla1Isr1);
Interrupt_register(INT_CLA1_2, &cla1Isr2);
Interrupt_register(INT_CLA1_3, &cla1Isr3);
Interrupt_register(INT_CLA1_4, &cla1Isr4);
Interrupt_register(INT_CLA1_5, &cla1Isr5);
Interrupt_register(INT_CLA1_6, &cla1Isr6);
Interrupt_register(INT_CLA1_7, &cla1Isr7);
Interrupt_register(INT_CLA1_8, &cla1Isr8);
}
这是官方的程序,是对CLA中断之类的初始化
void CLA_init()
{
EALLOW;
CLA_DSP_initEpie();
CLA_DSP_configClaMemory();
CLA_DSP_initCpu1Cla1();
EDIS;
}
总初始化
void CLA_runTest(unsigned char RTest)
{
switch(RTest)
{
case 1: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_1); break;
case 2: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_2); break;
}
WAITSTEP;
}
这是运行CLA程序,有点类似ADC软件触发一样
上述部分在官方的例程中都有,基本上只要无脑搬基本也没什么问题。
4.内存管理
关于CLA的内存分配问题上,我们主要关注点是LSx RAM内存区域,因为这个区域是CLA运行区域。
可以看到从LS0-LS5的区域CLA是可以存取的所有的CLA程序,运行中所产生的内容都会在这部分区域。除此之外还有一部分就是MSGRAM1和2就是第四行和第五行的内容,这部分内容是CPU与CLA的通信的“桥梁”,通过两个区域,CPU的数据可以转移到CLA内,同时CLA的内容也可以转移到CPU内。
4.1 RAM运行
CLA_SCRATCHPAD_SIZE = 0x100;
--undef_sym=__cla_scratchpad_end
--undef_sym=__cla_scratchpad_start
MEMORY
{
//一般用于存放代码
PAGE 0 :
BEGIN : origin = 0x000000, length = 0x000002
RAMGS0 : origin = 0x00C000, length = 0x001000
RAMGS1 : origin = 0x00D000, length = 0x001000
RAMGS2 : origin = 0x00E000, length = 0x001000
RAMGS3 : origin = 0x00F000, length = 0x001000
RAMGS4 : origin = 0x010000, length = 0x001000
RAMGS5 : origin = 0x011000, length = 0x001000
RESET : origin = 0x3FFFC0, length = 0x000002
IQTABLES : origin = 0x3FE000, length = 0x000B50 /* IQ Math Tables in Boot ROM */
IQTABLES2 : origin = 0x3FEB50, length = 0x00008C
IQTABLES3 : origin = 0x3FEBDC, length = 0x0000AA
FLASHA : origin = 0x080002, length = 0x001FFE /* on-chip Flash */
FLASHB : origin = 0x082000, length = 0x002000 /* on-chip Flash */
FLASHC : origin = 0x084000, length = 0x002000 /* on-chip Flash */
FLASHD : origin = 0x086000, length = 0x002000 /* on-chip Flash */
FLASHE : origin = 0x088000, length = 0x008000 /* on-chip Flash */
FLASHF : origin = 0x090000, length = 0x008000 /* on-chip Flash */
FLASHG : origin = 0x098000, length = 0x008000 /* on-chip Flash */
//一般用于存放数据
PAGE 1 :
BOOT_RSVD : origin = 0x000002, length = 0x00004E /* Part of M0, BOOT rom will use this for stack */
RAMM0 : origin = 0x000050, length = 0x0003B0
RAMM1 : origin = 0x000400, length = 0x000400
RAMD0 : origin = 0x00B000, length = 0x000800
RAMD1 : origin = 0x00B800, length = 0x000800
RAMGS6 : origin = 0x012000, length = 0x001000
RAMGS7 : origin = 0x013000, length = 0x001000
RAMGS8 : origin = 0x014000, length = 0x001000
RAMGS9 : origin = 0x015000, length = 0x001000
RAMGS10 : origin = 0x016000, length = 0x001000
RAMGS11 : origin = 0x017000, length = 0x001000
RAMGS12 : origin = 0x018000, length = 0x001000
RAMGS13 : origin = 0x019000, length = 0x001000
RAMGS14 : origin = 0x01A000, length = 0x001000
RAMGS15 : origin = 0x01B000, length = 0x001000
RAMLS0_1 : origin = 0x008000, length = 0x002000
RAMLS2_3 : origin = 0x00A000, length = 0x000A00
RAMLS4_5 : origin = 0x00AA00, length = 0x000600
CLA1_MSGRAMLOW : origin = 0x001480, length = 0x000080
CLA1_MSGRAMHIGH : origin = 0x001500, length = 0x000080
CPU2TOCPU1RAM : origin = 0x03F800, length = 0x000400
CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400
FLASHH : origin = 0x0A0000, length = 0x008000 /* on-chip Flash */
FLASHI : origin = 0x0A8000, length = 0x008000 /* on-chip Flash */
FLASHJ : origin = 0x0B0000, length = 0x008000 /* on-chip Flash */
FLASHK : origin = 0x0B8000, length = 0x002000 /* on-chip Flash */
FLASHL : origin = 0x0BA000, length = 0x002000 /* on-chip Flash */
FLASHM : origin = 0x0BC000, length = 0x002000 /* on-chip Flash */
FLASHN : origin = 0x0BE000, length = 0x002000 /* on-chip Flash */
}
SECTIONS
{
codestart : > BEGIN, PAGE = 0
//可存储在flash的字段
.text :>> RAMGS0 | RAMGS1 | RAMGS2, PAGE = 0 //程序段
.cinit : > RAMGS4, PAGE = 0 //初始化数据
.const : > RAMGS4, PAGE = 0 //在EABI mode下与cinit一致,初始化段上电后会复制到bss
.bss : > RAMGS4, PAGE = 0 //全局变量和静态变量
.bss:output : > RAMGS4, PAGE = 0
//重要字段
ramfuncs : > RAMM0, PAGE = 1
.TI.ramfunc : > RAMM0, PAGE = 1
.switch : > RAMM0, PAGE = 1 //switch字段
.init_array : > RAMM0, PAGE = 1 //启动时调用的 C++ 构造函数的表
.stack : > RAMM1, PAGE = 1 //堆栈,最低至少需要64k
.data : > RAMGS7, PAGE = 1 //程序运行中所产生的数据
//非重要内存字段
.econst : > RAMGS11, PAGE = 1
.ebss : > RAMGS11, PAGE = 1 //为使用大寄存器模式时的全局变量和静态变量预留的空间,在程序上电时
//cinit空间中的数据复制出来并存储在.ebss中
.pinit : > RAMGS11, PAGE = 1 //启动时要调用的构造函数表
.cio : > RAMGS11, PAGE = 1 //printf等输入输出函数使用的缓冲区所在的段
.sysmem : > RAMGS11, PAGE = 1 //maclloc所用的段
//CLA字段
IOBuffer : > RAMLS2_3, PAGE = 1
Cla1Prog : > RAMLS0_1, PAGE = 1
Cla1Prog:cla_dsp_fft : > RAMLS0_1, HIGH PAGE = 1
ramfuncs : LOAD = FLASHL,
RUN = RAMD0,
RUN_START(RamfuncsRunStart),
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
PAGE = 1
CLA1fftTables : LOAD = FLASHM,
RUN = RAMLS4_5,
RUN_START(CLA1fftTablesRunStart),
LOAD_START(CLA1fftTablesLoadStart),
LOAD_SIZE(CLA1fftTablesLoadSize),
PAGE = 1
Cla1Prog : LOAD = FLASHM,
RUN = RAMLS0_1,
RUN_START(Cla1ProgRunStart),
LOAD_START(Cla1ProgLoadStart),
LOAD_SIZE(Cla1ProgLoadSize),
PAGE = 1
Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1
CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1
/* CLA C compiler sections */
//
// Must be allocated to memory the CLA has write access to
//
// CLAscratch is the legacy code model scratch pad. use
// .scratchpad in the new model
CLAscratch :
{ *.obj(CLAscratch)
. += CLA_SCRATCHPAD_SIZE;
*.obj(CLAscratch_end) }
> RAMLS4_5, PAGE = 1
.scratchpad : > RAMLS4_5, PAGE = 1
.bss_cla : > RAMLS4_5, PAGE = 1
.const_cla : > RAMLS4_5, PAGE = 1
//自定义字段
ramgs0 : > RAMGS14, PAGE = 1
MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM PAGE = 1
MSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM PAGE = 1
.reset : > RESET, PAGE = 0, TYPE = DSECT //未用到
}
4.2 FLASH运行
CLA_SCRATCHPAD_SIZE = 0x100;
MEMORY
{
PAGE 0 :
BEGIN : origin = 0x080000, length = 0x000002
RAMGS0 : origin = 0x00C000, length = 0x001000
RAMGS1 : origin = 0x00D000, length = 0x001000
RAMGS2 : origin = 0x00E000, length = 0x001000
FLASHA : origin = 0x080002, length = 0x001FFE /* on-chip Flash */
FLASHB : origin = 0x082000, length = 0x002000 /* on-chip Flash */
FLASHC : origin = 0x084000, length = 0x002000 /* on-chip Flash */
FLASHD : origin = 0x086000, length = 0x002000 /* on-chip Flash */
FLASHE : origin = 0x088000, length = 0x008000 /* on-chip Flash */
FLASHF : origin = 0x090000, length = 0x008000 /* on-chip Flash */
FLASHG : origin = 0x098000, length = 0x008000 /* on-chip Flash */
FLASHH : origin = 0x0A0000, length = 0x008000 /* on-chip Flash */
FLASHI : origin = 0x0A8000, length = 0x008000 /* on-chip Flash */
RESET : origin = 0x3FFFC0, length = 0x000002
PAGE 1 : /* Data Memory */
/* Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation */
BOOT_RSVD : origin = 0x000002, length = 0x00004E /* Part of M0, BOOT rom will use this for stack */
RAMM0 : origin = 0x000050, length = 0x0003B0
RAMM1 : origin = 0x000400, length = 0x000400
RAMD0 : origin = 0x00B000, length = 0x000800
RAMD1 : origin = 0x00B800, length = 0x000800
RAMGS3 : origin = 0x00F000, length = 0x001000
RAMGS4 : origin = 0x010000, length = 0x001000
RAMGS5 : origin = 0x011000, length = 0x001000
RAMGS6 : origin = 0x012000, length = 0x001000
RAMGS7 : origin = 0x013000, length = 0x001000
RAMGS8 : origin = 0x014000, length = 0x001000
RAMGS9 : origin = 0x015000, length = 0x001000
RAMGS10 : origin = 0x016000, length = 0x001000
RAMGS11 : origin = 0x017000, length = 0x001000
RAMGS12 : origin = 0x018000, length = 0x001000
RAMGS13 : origin = 0x019000, length = 0x001000
RAMGS14 : origin = 0x01A000, length = 0x001000
RAMGS15 : origin = 0x01B000, length = 0x001000
RAMLS0_1 : origin = 0x008000, length = 0x002000
RAMLS2_3 : origin = 0x00A000, length = 0x000A00
RAMLS4_5 : origin = 0x00AA00, length = 0x000600
FLASHJ : origin = 0x0B0000, length = 0x008000 /* on-chip Flash */
FLASHK : origin = 0x0B8000, length = 0x002000 /* on-chip Flash */
FLASHL : origin = 0x0BA000, length = 0x002000 /* on-chip Flash */
FLASHM : origin = 0x0BC000, length = 0x002000 /* on-chip Flash */
FLASHN : origin = 0x0BE000, length = 0x001FF0 /* on-chip Flash */
CPU2TOCPU1RAM : origin = 0x03F800, length = 0x000400
CPU1TOCPU2RAM : origin = 0x03FC00, length = 0x000400
CLA1_MSGRAMLOW : origin = 0x001480, length = 0x000080
CLA1_MSGRAMHIGH : origin = 0x001500, length = 0x000080
}
SECTIONS
{
codestart : > BEGIN PAGE = 0, ALIGN(8)
.text : >>FLASHB | FLASHC | FLASHD | FLASHE PAGE = 0, ALIGN(8)
.cinit : > FLASHG PAGE = 0, ALIGN(8)
.const : > FLASHG PAGE = 0, ALIGN(8)
.switch : > FLASHH PAGE = 0, ALIGN(8)
.init_array : > FLASHH PAGE = 0, ALIGN(8)
.stack : > RAMM1 PAGE = 1
.bss : > RAMGS14, PAGE = 1
.bss:output : > RAMGS14, PAGE = 1
.bss:cio : > RAMGS14, PAGE = 1
.data : > RAMGS14, PAGE = 1
.sysmem : > RAMGS14, PAGE = 1
.TI.ramfunc : {} LOAD = FLASHJ,
RUN = RAMGS15,
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
LOAD_END(RamfuncsLoadEnd),
RUN_START(RamfuncsRunStart),
RUN_SIZE(RamfuncsRunSize),
RUN_END(RamfuncsRunEnd),
PAGE = 1, ALIGN(8)
Cla1Prog:cla_dsp_fft : > RAMLS0_1, HIGH PAGE = 1
CLA1fftTables : LOAD = FLASHB,
RUN = RAMLS4_5,
RUN_START(CLA1fftTablesRunStart),
LOAD_START(CLA1fftTablesLoadStart),
LOAD_SIZE(CLA1fftTablesLoadSize),
PAGE = 1
Cla1Prog : LOAD = FLASHK,
RUN = RAMLS0_1,
RUN_START(Cla1ProgRunStart),
LOAD_START(Cla1ProgLoadStart),
LOAD_SIZE(Cla1ProgLoadSize),
PAGE = 1
CLAscratch :
{ *.obj(CLAscratch)
. += CLA_SCRATCHPAD_SIZE;
*.obj(CLAscratch_end) } > RAMLS4_5, PAGE = 1
Cla1ToCpuMsgRAM : > CLA1_MSGRAMLOW, PAGE = 1
CpuToCla1MsgRAM : > CLA1_MSGRAMHIGH, PAGE = 1
.scratchpad : > RAMLS4_5, PAGE = 1
.bss_cla : > RAMLS4_5, PAGE = 1
.const_cla : > RAMLS4_5, PAGE = 1
IOBuffer : > RAMLS2_3, PAGE = 1
ramgs0 : > RAMGS13, PAGE = 1
Filter_RegsFile : > RAMGS15, PAGE = 1
Filter1_RegsFile : > RAMGS15, PAGE = 1, fill=0x1111
Filter2_RegsFile : > RAMGS15, PAGE = 1, fill=0x2222
Filter3_RegsFile : > RAMGS15, PAGE = 1, fill=0x3333
Filter4_RegsFile : > RAMGS15, PAGE = 1, fill=0x4444
Difference_RegsFile : > RAMGS15, PAGE = 1, fill=0x3333
MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM PAGE = 1
MSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM PAGE = 1
GROUP : > CPU1TOCPU2RAM, PAGE = 1
{
PUTBUFFER
PUTWRITEIDX
GETREADIDX
}
GROUP : > CPU2TOCPU1RAM, PAGE = 1
{
GETBUFFER : TYPE = DSECT
GETWRITEIDX : TYPE = DSECT
PUTREADIDX : TYPE = DSECT
}
.reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */
}
上述程序我就不解释了,如果需要我可以再更新,大家可以留言
5. 运行程序
初始化后,我们如何使用CLA呢?在TI的管理中有一个文件后缀为 xxx.CLA,我们在里面写CLA的运行程序,但是它不同于其他C文件,因为它不允许定义变量,不允许被include,只能写函数和include其他文件。
//
// Included Files
//
#include "CLA_share.h"
#include "cla_cfft.h"
#include "CLAmath.h"
extern float fVal; //Holds the input argument to the task
extern float fResult; //The arsine of the input argument
__interrupt void Cla1Task1 ( void )
{
__mdebugstop();
CLA_CFFT_run256Pt();
fResult=
CLAsin(4.2);
}
interrupt void Cla1Task2 ( void )
{
fResult=
CLAsin(0.5)*4096;
}
interrupt void Cla1Task3 ( void )
{
}
interrupt void Cla1Task4 ( void )
{
}
interrupt void Cla1Task5 ( void )
{
}
interrupt void Cla1Task6 ( void )
{
}
interrupt void Cla1Task7 ( void )
{
}
interrupt void Cla1Task8 ( void )
{
}
这里我就用Task1来介绍了,大家可以先将CLA_CFFT_run256Pt();注释,这是256点的FFT程序。我们先使用CLAsin来做。其作用与math中的sin一致给一个数程序算出sin值,它是用弧度值来计算。
除了上述的CLA文件还有配套的C文件非常重要。所有的中断,
/*
* CLA_interrupt.c
*
* Created on: 2023年5月1日
* Author: 18752
*/
#include "CLA_interrupt.h"
//
// cla1Isr1 - CLA1 ISR 1
//
__interrupt void cla1Isr1 ()
{
//
// Acknowledge the end-of-task interrupt for task 1
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
//
// Uncomment to halt debugger and stop here
//
// asm(" ESTOP0");
}
//
// cla1Isr2 - CLA1 ISR 2
//
__interrupt void cla1Isr2 ()
{
asm(" ESTOP0");
}
//
// cla1Isr3 - CLA1 ISR 3
//
__interrupt void cla1Isr3 ()
{
asm(" ESTOP0");
}
//
// cla1Isr4 - CLA1 ISR 4
//
__interrupt void cla1Isr4 ()
{
asm(" ESTOP0");
}
//
// cla1Isr5 - CLA1 ISR 5
//
__interrupt void cla1Isr5 ()
{
asm(" ESTOP0");
}
//
// cla1Isr6 - CLA1 ISR 6
//
__interrupt void cla1Isr6 ()
{
asm(" ESTOP0");
}
//
// cla1Isr7 - CLA1 ISR 7
//
__interrupt void cla1Isr7 ()
{
asm(" ESTOP0");
}
//
// cla1Isr8 - CLA1 ISR 8
//
__interrupt void cla1Isr8 ()
{
//
// Acknowledge the end-of-task interrupt for task 8
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
//
// Uncomment to halt debugger and stop here
//
// asm(" ESTOP0");
}
这是CLA的中断文件,我就过多介绍了,抄就完了。
在上述内容之外你还需要找一个C文件定义你的变量,如果想让cla使用则必须先对区域定义,相信大家看到就知道是怎么用的了。
#pragma DATA_SECTION(fVal,"CpuToCla1MsgRAM");
float fVal;
#pragma DATA_SECTION(fResult,"Cla1ToCpuMsgRAM");
float fResult;
CPUtoCLA即CPU的变量放到CLA中,另一个就是CLAtoCPU了。
5.库文件
对于CLA还要依赖的lib文件,其路径是两个。
C2000Ware_4_03_00_00\libraries\boot_rom\f2837xd\rev0\rom_symbol_libs
C2000Ware_4_03_00_00\libraries\math\CLAmath\c28\lib
如果你使用的是elf文件就和我一样配置,如果是legacy可以看文件的后缀开启你用的文件
6.最后移植完成后的文件
下图是文件结构
CLA.init
/*
* CLA_init.c
*
* Created on: 2023年5月1日
* Author: 18752
*/
#include "CLA_init.h"
#pragma DATA_SECTION(fVal,"CpuToCla1MsgRAM");
float fVal;
#pragma DATA_SECTION(fResult,"Cla1ToCpuMsgRAM");
float fResult;
#pragma DATA_SECTION(IOBuffer,"IOBuffer")
float IOBuffer[(256+1)*2] = {
#include "ffttest.h"
};
//
// CLA_runTest - Execute CLA task tests for specified vectors
//
void CLA_runTest(unsigned char RTest)
{
switch(RTest)
{
case 1: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_1); break;
case 2: CLA_forceTasks(CLA1_BASE,CLA_TASKFLAG_2); break;
}
WAITSTEP;
}
void CLA_init()
{
EALLOW;
CLA_DSP_initEpie();
CLA_DSP_configClaMemory();
CLA_DSP_initCpu1Cla1();
EDIS;
}
void CLA_DSP_initEpie()
{
Interrupt_initModule();
Interrupt_initVectorTable();
}
void CLA_DSP_configClaMemory(void)
{
extern uint32_t Cla1ProgRunStart, Cla1ProgLoadStart, Cla1ProgLoadSize;
extern uint32_t CLA1fftTablesRunStart, CLA1fftTablesLoadStart, CLA1fftTablesLoadSize;
EALLOW;
#ifdef _FLASH
// Copy over code and tables from FLASH to RAM
memcpy((uint32_t *)&Cla1ProgRunStart, (uint32_t *)&Cla1ProgLoadStart,
(uint32_t)&Cla1ProgLoadSize);
memcpy((uint32_t *)&CLA1fftTablesRunStart, (uint32_t *)&CLA1fftTablesLoadStart,
(uint32_t)&CLA1fftTablesLoadSize);
#endif //_FLASH
// Initialize and wait for CLA1ToCPUMsgRAM
MemCfg_initSections(MEMCFG_SECT_MSGCLA1TOCPU);
while (!MemCfg_getInitStatus(MEMCFG_SECT_MSGCLA1TOCPU)){};
// Initialize and wait for CPUToCLA1MsgRAM
MemCfg_initSections(MEMCFG_SECT_MSGCPUTOCLA1);
while (!MemCfg_getInitStatus(MEMCFG_SECT_MSGCPUTOCLA1)){};
// Select LS0-LS1RAM to be the programming space for the CLA
// First configure the CLA to be the master for LS0 and then
// set the space to be a program block
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS0,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS0,MEMCFG_CLA_MEM_PROGRAM);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS1,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS1,MEMCFG_CLA_MEM_PROGRAM);
//Next configure LS2-LS5RAM as data spaces for the CLA
// First configure the CLA to be the master for LSx and then
// set the spaces to be code blocks
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS2,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS2, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS3,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS3, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS4,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS4, MEMCFG_CLA_MEM_DATA);
MemCfg_setLSRAMMasterSel(MEMCFG_SECT_LS5,MEMCFG_LSRAMMASTER_CPU_CLA1);
MemCfg_setCLAMemType(MEMCFG_SECT_LS5, MEMCFG_CLA_MEM_DATA);
}
void CLA_DSP_initCpu1Cla1(void)
{
// Compute all CLA task vectors
// On Type-1 CLAs the MVECT registers accept full 16-bit task addresses as
// opposed to offsets used on older Type-0 CLAs
//
// Suppressing #770-D conversion from pointer to smaller integer
// The CLA address range is 16 bits so the addresses passed to the MVECT
// registers will be in the lower 64KW address space. Turn the warning
// back on after the MVECTs are assigned addresses
//
#pragma diag_suppress=770
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_1,(uint16_t)&Cla1Task1);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_2,(uint16_t)&Cla1Task2);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_3,(uint16_t)&Cla1Task3);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_4,(uint16_t)&Cla1Task4);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_5,(uint16_t)&Cla1Task5);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_6,(uint16_t)&Cla1Task6);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_7,(uint16_t)&Cla1Task7);
CLA_mapTaskVector(CLA1_BASE,CLA_MVECT_8,(uint16_t)&Cla1Task8);
#pragma diag_warning=770
// Enable IACK instruction to start a task on CLA in software
// for all 8 CLA tasks
CLA_enableIACK(CLA1_BASE);
CLA_enableTasks(CLA1_BASE, CLA_TASKFLAG_ALL);
// Configure the vectors for the end-of-task interrupt for all
// 8 tasks
Interrupt_register(INT_CLA1_1, &cla1Isr1);
Interrupt_register(INT_CLA1_2, &cla1Isr2);
Interrupt_register(INT_CLA1_3, &cla1Isr3);
Interrupt_register(INT_CLA1_4, &cla1Isr4);
Interrupt_register(INT_CLA1_5, &cla1Isr5);
Interrupt_register(INT_CLA1_6, &cla1Isr6);
Interrupt_register(INT_CLA1_7, &cla1Isr7);
Interrupt_register(INT_CLA1_8, &cla1Isr8);
}
CLA_init.h
/*
* CLA_init.h
*
* Created on: 2023年5月1日
* Author: 18752
*/
#ifndef CLA_CLA_INIT_H_
#define CLA_CLA_INIT_H_
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#define FFTLENGTH 256
//*****************************************************************************
//
// CLA Configurations
//
//*****************************************************************************
#define myCLA0_BASE CLA1_BASE
//
// The following are symbols defined in the CLA assembly code
// Including them in the shared header file makes them global
// and the main CPU can make use of them.
//
__attribute__((interrupt)) void Cla1Task1();
__attribute__((interrupt)) void Cla1Task2();
__attribute__((interrupt)) void Cla1Task3();
__attribute__((interrupt)) void Cla1Task4();
__attribute__((interrupt)) void Cla1Task5();
__attribute__((interrupt)) void Cla1Task6();
__attribute__((interrupt)) void Cla1Task7();
__attribute__((interrupt)) void Cla1Task8();
void myCLA0_init();
//*****************************************************************************
//
// INTERRUPT Configurations
//
//*****************************************************************************
// Interrupt Settings for INT_myCLA01
#define INT_myCLA01 INT_CLA1_1
#define INT_myCLA01_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr1(void);
// Interrupt Settings for INT_myCLA02
#define INT_myCLA02 INT_CLA1_2
#define INT_myCLA02_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr2(void);
// Interrupt Settings for INT_myCLA03
#define INT_myCLA03 INT_CLA1_3
#define INT_myCLA03_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr3(void);
// Interrupt Settings for INT_myCLA04
#define INT_myCLA04 INT_CLA1_4
#define INT_myCLA04_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr4(void);
// Interrupt Settings for INT_myCLA05
#define INT_myCLA05 INT_CLA1_5
#define INT_myCLA05_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr5(void);
// Interrupt Settings for INT_myCLA06
#define INT_myCLA06 INT_CLA1_6
#define INT_myCLA06_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr6(void);
// Interrupt Settings for INT_myCLA07
#define INT_myCLA07 INT_CLA1_7
#define INT_myCLA07_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr7(void);
// Interrupt Settings for INT_myCLA08
#define INT_myCLA08 INT_CLA1_8
#define INT_myCLA08_INTERRUPT_ACK_GROUP INTERRUPT_ACK_GROUP11
extern __interrupt void cla1Isr8(void);
//*****************************************************************************
//
// MEMCFG Configurations
//
//*****************************************************************************
void CLA_init();
// \brief Initialize system clocks
//
void CLA_DSP_initSystemClocks(void);
// \brief Initialize Enhanced PIE
//
void CLA_DSP_initEpie(void);
// \brief Configure CLA memory space
//
void CLA_DSP_configClaMemory(void);
// \brief Intialize the MVECT registers for the CLA
//
void CLA_DSP_initCpu1Cla1(void);
void CLA_runTest(unsigned char RTest);
#define WAITSTEP asm(" RPT #255 || NOP")
#endif /* CLA_CLA_INIT_H_ */
CLA_initerrupt.c
/*
* CLA_interrupt.c
*
* Created on: 2023年5月1日
* Author: 18752
*/
#include "CLA_interrupt.h"
//
// cla1Isr1 - CLA1 ISR 1
//
__interrupt void cla1Isr1 ()
{
//
// Acknowledge the end-of-task interrupt for task 1
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
//
// Uncomment to halt debugger and stop here
//
// asm(" ESTOP0");
}
//
// cla1Isr2 - CLA1 ISR 2
//
__interrupt void cla1Isr2 ()
{
asm(" ESTOP0");
}
//
// cla1Isr3 - CLA1 ISR 3
//
__interrupt void cla1Isr3 ()
{
asm(" ESTOP0");
}
//
// cla1Isr4 - CLA1 ISR 4
//
__interrupt void cla1Isr4 ()
{
asm(" ESTOP0");
}
//
// cla1Isr5 - CLA1 ISR 5
//
__interrupt void cla1Isr5 ()
{
asm(" ESTOP0");
}
//
// cla1Isr6 - CLA1 ISR 6
//
__interrupt void cla1Isr6 ()
{
asm(" ESTOP0");
}
//
// cla1Isr7 - CLA1 ISR 7
//
__interrupt void cla1Isr7 ()
{
asm(" ESTOP0");
}
//
// cla1Isr8 - CLA1 ISR 8
//
__interrupt void cla1Isr8 ()
{
//
// Acknowledge the end-of-task interrupt for task 8
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP11);
//
// Uncomment to halt debugger and stop here
//
// asm(" ESTOP0");
}
CLA_initerrupt.h
/*
* CLA_interrupt.h
*
* Created on: 2023年5月1日
* Author: 18752
*/
#ifndef CLA_CLA_INTERRUPT_H_
#define CLA_CLA_INTERRUPT_H_
#include "interrupt.h"
#endif /* CLA_CLA_INTERRUPT_H_ */
CLA_share.h
/*
* CLA_share.h
*
* Created on: 2023年5月1日
* Author: 18752
*/
#ifndef CLA_CLA_SHARE_H_
#define CLA_CLA_SHARE_H_
#include <stdint.h>
//
// Defines
//
#define PI 3.141592653589
extern float fVal;
extern float fResult;
__interrupt void Cla1Task1();
__interrupt void Cla1Task2();
__interrupt void Cla1Task3();
__interrupt void Cla1Task4();
__interrupt void Cla1Task5();
__interrupt void Cla1Task6();
__interrupt void Cla1Task7();
__interrupt void Cla1Task8();
#endif /* CLA_CLA_SHARE_H_ */
MyCLA.cla
//
// Included Files
//
#include "CLA_share.h"
#include "cla_cfft.h"
#include "CLAmath.h"
extern float fVal; //Holds the input argument to the task
extern float fResult; //The arsine of the input argument
__interrupt void Cla1Task1 ( void )
{
__mdebugstop();
CLA_CFFT_run256Pt();
fResult=
CLAsin(4.2);
}
interrupt void Cla1Task2 ( void )
{
fResult=
CLAsin(0.5)*4096;
}
interrupt void Cla1Task3 ( void )
{
}
interrupt void Cla1Task4 ( void )
{
}
interrupt void Cla1Task5 ( void )
{
}
interrupt void Cla1Task6 ( void )
{
}
interrupt void Cla1Task7 ( void )
{
}
interrupt void Cla1Task8 ( void )
{
}
7. 最后效果
可以看到cla初始化后fresult是0
cla运行完成后是0.707与计算器算的是一样的
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)