DSP芯片C6678的SRIO及其中断跳转的配置

news/2025/2/25 7:34:48

C6678SRIO读写测试+门铃中断跳转测试

  • SRIO简述
  • 代码前言
  • SRIO配置
    • 原始代码
    • 1.使能电源
    • 2.初始化SRIO
      • 回环修改
    • 3.SRIO测试
  • Doorbell门铃中断
    • 1.初始化中断函数
    • 2.中断向量表建立
    • 3.中断向量表的链接

本博客基于创龙“678ZH产品线”的SRIO代码,部分参考于网友们的博客,参考文档将在结尾列出

SRIO_2">SRIO简述

一句话:高速串行通信协议
有多高速:最高25Gbps≈3G的文件一秒传输完成
什么串行:四组口,可任意配置为用一组还是多用几组(每组最快6.25Gbps)

适合场景:任何高速数据交换场景,但其实小编只在FPGA与DSP之间应用。
例如:FPGA将图像数据传送到DSP,然后DSP经过识别处理后呈现给出结果。

另外小编觉得最神奇的是SRIO是可以直接将数据放入指定位置的,例如FPGA如果需要将数据给到DSP处理,FPGA可以直接设置放入指定的DDR地址,或者其他高速缓存地址,这是小编认为SRIO最好玩的地方。

代码前言

当说明文档太多而不知道看哪些的时候,最好的方法就是直接上代码(尤其是对于这种已经十几年前的芯片)。
笔者当前一共看过了3套C6678SRIO相关代码,从难到简单的排序是这样的
难:pdk_c667x_2_0_16\packages\MyExampleProjects
中:C6678\STK_C6678\SRIO
易:678ZH产品线\7.案例源码\SRIO的ZYNQ+DSP核间通讯\srio_initiator

TI官方提供的例子是最难的,其次就是TI论坛上基于keystone的例子,然后就是创龙提供的简化版的例子。小编是先看了keystone的例子,必须要对照文档一步步看,因为涉及到的功能很多。然后再看的创龙,创龙的例子太简单了,只有发送和读取,非常适合刚入DSP门的同学学习。
下面SRIO的初始测试就是基于创龙的代码(创龙代码都是使用了TI官方的CSL库进行配置的,用户需要自行用include options来包含(eclipse系列用户应该容易理解),我用的是“pdk_C6678_1_1_2_6\packages\ti\csl”)。

以下创龙demo的例子大家可以去其官网上进行下载哦。

SRIO_21">SRIO配置

创龙的代码是直接与FPGA交互,但是稍微一改就可以变成回环测试,非常适合于FPGA端还没有调好的场景。

原始代码

创龙非常贴心的将代码全部放到了main一个文档里面,异常的简洁明了。
我们先来整体看一下

int main(void)
{
    int8_t   ret;
    uint32_t core_num;

    /* enable SRIO PSC */
    ret = enable_srio();
    if(ret != 0) {
        printf("srio psc initialization failed ! \r\n");
        return -1;
    }

    /* configure and enable SRIO subsystem */
    ret = srio_device_init();
    if(ret != 0) {
        printf("srio system initialization failed ! \r\n");
        return -1;
    }

    /* read the DSP Core Number */
    core_num = CSL_chipReadReg(CSL_CHIP_DNUM);

    /* srio transmit test: srio write(NWRITE) --> srio read(NREAD) */
    ret = srio_test(core_num, TARGET_ADDRESS, TARGET_SIZE, Srio_Ftype_WRITE);
    if(ret != 0) {
        printf("srio test occur error! \r\n");
        return -1;
    }

    printf("SRIO test %d cycles, " \
        "errcnt: %d, total size %d KB, ", \
        LOOP_TIMES, err_count, TARGET_SIZE * LOOP_TIMES / 1024);
    printf("write type: NWRITE, avg write rate: %.2f Gbps, ", \
        w_rate_total / LOOP_TIMES);
    printf("read type: NREAD, avg read rate: %.2f Gbps\r\n\n\n", \
        r_rate_total / LOOP_TIMES);

    /* clear var to zero */
    w_rate_total = 0.0;
    r_rate_total = 0.0;
    err_count = 0;

    /* srio transmit test: srio write(SWRITE) --> srio read(NREAD) */
    ret = srio_test(core_num, TARGET_ADDRESS, TARGET_SIZE, Srio_Ftype_SWRITE);
    if(ret != 0) {
        printf("srio test occur error! \r\n");
        return -1;
    }

    printf("SRIO test %d cycles, " \
        "errcnt: %d, total size %d KB, ", \
        LOOP_TIMES, err_count, TARGET_SIZE * LOOP_TIMES / 1024);
    printf("write type: SWRITE, avg write rate: %.2f Gbps, ", \
        w_rate_total / LOOP_TIMES);
    printf("read type: NREAD, avg read rate: %.2f Gbps\r\n\n\n", \
        r_rate_total / LOOP_TIMES);

    return 0;
}

以上代码,使能SRIO电源管理、初始化SRIOSRIO测试,一共三步,就能跑起来测试。

1.使能电源

电源设置非常固定,只要将TI官方csl库包进来然后使用即可。

static int32_t enable_srio (void)
{
    /* SRIO power domain is turned OFF by default. It needs to be turned on before doing any
     * SRIO device register access. This not required for the simulator
     */
    /* Set SRIO Power domain to ON */
    CSL_PSC_enablePowerDomain(CSL_PSC_PD_SRIO);

    /* Enable the clocks too for SRIO */
    CSL_PSC_setModuleNextState(CSL_PSC_LPSC_SRIO, PSC_MODSTATE_ENABLE);

    /* Start the state transition */
    CSL_PSC_startStateTransition(CSL_PSC_PD_SRIO);

    /* Wait until the state transition process is completed. */
    while(!CSL_PSC_isStateTransitionDone(CSL_PSC_PD_SRIO));

    /* Return SRIO PSC status */
    if((CSL_PSC_getPowerDomainState(CSL_PSC_PD_SRIO) != PSC_PDSTATE_ON) ||
        (CSL_PSC_getModuleState(CSL_PSC_LPSC_SRIO) != PSC_MODSTATE_ENABLE)) {
        /* SRIO Power on failed. Return error */
        return -1;
    }

    /* SRIO ON. Ready for use */
    return 0;
}

SRIO_120">2.初始化SRIO

链接: 各部寄存器参数说明
初始化SRIO是用来选择使用几组接口、选择多大速率的一些基本操作
还有最后确认是否建立好了SRIO连接(如果FPGA没写好,那就只能用回环模式通过,否则就会报连接错误)

在这一部分,用户可以将其设置为回环测试,只用修改一个小小的地方即可

static int32_t srio_device_init (void)
{
    uint32_t             i, wait_time;
    uint32_t             status;

    /* Get the CSL SRIO Handle. */
    hSrio = CSL_SRIO_Open(0);
    if(hSrio == NULL)
        return -1;

    /* Code to disable SRIO reset isolation */
    if(CSL_PSC_isModuleResetIsolationEnabled(CSL_PSC_LPSC_SRIO))
        CSL_PSC_disableModuleResetIsolation(CSL_PSC_LPSC_SRIO);

    /* Disable the SRIO Global block */
    CSL_SRIO_GlobalDisable(hSrio);

    /* Disable each of the individual SRIO blocks. */
    for(i = 0; i <= 9; i++)
        CSL_SRIO_DisableBlock(hSrio, i);

    /* BOOT_COMPLETE = 0:  write enabled */
    CSL_SRIO_SetBootComplete(hSrio, 0);

    /* Now enable the SRIO block and all the individual blocks also. */
    CSL_SRIO_GlobalEnable(hSrio);
    for(i = 0; i <= 9; i++)
        CSL_SRIO_EnableBlock(hSrio, i);

    /* Configure SRIO ports mode. */
    for(i = 0; i <= 3; i++)
        // CSL_SRIO_SetNormalMode(hSrio, i);
        CSL_SRIO_SetLoopbackMode(hSrio, i);

    /* Enable Automatic Priority Promotion of response packets. */
    CSL_SRIO_EnableAutomaticPriorityPromotion(hSrio);

    /*
        * Set the SRIO Prescalar select to operate in the range
        * PERSCALER_SELECT = 0: 44.7 ~ 89.5 MHz
        */
    CSL_SRIO_SetPrescalarSelect(hSrio, 0);

    /* Unlock the Boot Configuration Kicker */
    CSL_BootCfgUnlockKicker();

    /*
        * MPY = 0x50: 10x
        * ENPLL = 1: PLL Enable
        * srio_serdes_clock = RefClk(250MHz) * MPY = 2.5GHz
        */
    CSL_BootCfgSetSRIOSERDESConfigPLL(0x51);

    /*
        * Configure the SRIO SERDES Receive Configuration
        * ENOC     = 1: Enable offset compensation
        * EQ       = 1: Fully adaptive equalization
        * CDR      = 5: First order with fast lock
        * ALIGN    = 1: Comma alignment enabled
        * TERM     = 1: Input termination, the only valid value for this field is 0x1
        * RATE     = 1: Data Rate = 2 * srio_serdes_clock = 5Gbps
        * BUSWIDTH = 1: Bus width, indicate a 20-bit wide parallel bus to the clock
        * ENRX     = 1: Enable this receiver
        */
    for(i = 0; i <= 3; i++)
        CSL_BootCfgSetSRIOSERDESRxConfig(i, 0x00468495);

    /*
        * Configure the SRIO SERDES Transmit Configuration
        * MSYNC    = 1:  Enables the channel as the master lane
        * FIRUPT   = 1:  Transmitter pre and post cursor FIR filter update
        * TWPST1   = 18: Adjacent post cursor Tap weight
        * TWPRE    = 1:  Precursor Tap weight
        * SWING    = 16: Output swing
        * RATE     = 1:  Data Rate = 2 * srio_serdes_clock = 5Gbps
        * BUSWIDTH = 1:  Bus width, indicate a 20-bit wide parallel bus to the clock
        * ENRX     = 1:  Enable this receiver
        */
    for(i = 0; i <= 3; i++)
        CSL_BootCfgSetSRIOSERDESTxConfig(i, 0x001C8F95);

    /* Loop around till the SERDES PLL is not locked. */
    while(1) {
        /* Get the SRIO SERDES Status */
        CSL_BootCfgGetSRIOSERDESStatus(&status);
        if(status & 0x1)
            break;
    }

    /* Lock the Boot Configuration Kicker */
    CSL_BootCfgLockKicker();

    /* Clear the LSU pending interrupts. */
    CSL_SRIO_ClearLSUPendingInterrupt(hSrio, 0xFFFFFFFF, 0xFFFFFFFF);

    /* Set the 16 bit and 8 bit identifier for the SRIO Device */
    CSL_SRIO_SetDeviceIDCSR(hSrio, CSR_LOCAL_DEVICEID_8BIT, CSR_LOCAL_DEVICEID_16BIT);

    /* Configure the Base Routing Register */
    CSL_SRIO_SetTLMPortBaseRoutingInfo(hSrio, 0, 1, 1, 0, 0);
    CSL_SRIO_SetTLMPortBaseRoutingPatternMatch(hSrio, 0, 1, REMOTE_DEVICEID1_8BIT, 0xFF);

    /* Configure the PLM for all the ports */
    for (i = 0; i <= 3; i++) {
        /* TODO: We need to ensure that the Port 0 is configured to support both
            * the 2x and 4x modes. The Port Width field is read only. So here we simply
            * ensure that the Input and Output ports are enabled */
        CSL_SRIO_EnableInputPort(hSrio, i);
        CSL_SRIO_EnableOutputPort(hSrio, i);

        /*
            * Discovery timer is specified to be 28 msec +/- 4 msec
            * Discovery timer = RefClk(250MHz) period * PRESCALAR_SRV_CLK * 52429 * DISCOVERY_TIMER
            *                 = (1 / 250Mhz) * (250 / 10) * 52429 * 5 = 26.2ms
            */
        CSL_SRIO_SetPLMPortDiscoveryTimer(hSrio, i, 0x5);
    }

    /* Set the Port link timeout CSR */
    CSL_SRIO_SetPortLinkTimeoutCSR(hSrio, 0x000FFF);
    CSL_SRIO_SetPortResponseTimeoutCSR(hSrio, 0xFF0FFF);

    /* Set the Port General CSR: Only executing as Master Enable */
    CSL_SRIO_SetPortGeneralCSR(hSrio, 0, 1, 0);

    /* Clear the sticky register bits */
    CSL_SRIO_SetLLMResetControl(hSrio, 1);

    /* Set the Data Streaming MTU */
    CSL_SRIO_SetDataStreamingMTU(hSrio, 64);

    /* Configure the path mode 4 for the ports */
    CSL_SRIO_SetPLMPortPathControlMode(hSrio, 0, 4);

    /*
        * Set the LLM Port IP Prescalar
        * PRESCALAR_SRV_CLK = RefClk(250MHz) / 10
        */
    CSL_SRIO_SetLLMPortIPPrescalar(hSrio, 0x19);

    /* Enable the peripheral */
    CSL_SRIO_EnablePeripheral(hSrio);

    /* Configuration has been completed */
    /* BOOT_COMPLETE = 1:  write to read only registers disabled */
    CSL_SRIO_SetBootComplete(hSrio, 1);

    /* This code checks if the ports are operational or not */
    wait_time = 100;
    while(wait_time) {
        if(CSL_SRIO_IsPortOk(hSrio, 0) == TRUE) {
            break;
        } else {
            wait_time --;
            /* Delay 1 ms */
            cpu_delaycycles(1000000);
        }
    }

    if(wait_time == 0) {
        printf("srio system initialization time out!\r\n");
        return -1;
    }

    /* Initialization has been completed */
    return 0;
}

波特率的计算方式如下:
参考时钟(板卡外部时钟)*倍频得出一个时钟A
时钟A经过RATE的选择,变成实际的通讯时钟
例如:外部时钟为250Mhz,经过10倍频=2.5Ghz,再经过RATE选择half模式就变成了5Gbps。

下图展示了倍频设置,对应代码中的CSL_BootCfgSetSRIOSERDESConfigPLL(0x51);
在这里插入图片描述

下图代表了RATE对应关系,对应代码中的
CSL_BootCfgSetSRIOSERDESRxConfig(i, 0x00468495);和
CSL_BootCfgSetSRIOSERDESTxConfig(i, 0x001C8F95);在这里插入图片描述
还有一些其他需要计算的参数,按照代码中注释计算即可,但是注意要将250Mhz的参考时钟(外部时钟)改为自己板卡上的时钟再进行计算。

回环修改

将CSL_SRIO_SetNormalMode(hSrio, i);改为
CSL_SRIO_SetLoopbackMode(hSrio, i);

SRIO_312">3.SRIO测试

在此demo中,SRIO会先将数据发送,然后再回读进行比较。
发送使用的是nwrite——即无响应写入
回读使用的是nread——即无响应读取

这部分代码需要用户对SRIO有一定的了解,会涉及到目的地址与本地地址。在这小编就不做说明了哈。

static int8_t srio_test(uint8_t LSU_Number, uint32_t target_addr,
        uint32_t transfer_size, Srio_Ftype w_format_type)
{
    SRIO_LSU_TRANSFER   tparams;
    uint32_t  main_pll_freq;
    int32_t   status = 0;
    uint32_t  i = 0, j = 0, timeout = 0;
    uint8_t   uiCompletionCode = 0, context = 0;
    uint8_t   contextBit = 0, transactionID = 0;
    uint32_t  transStart = 0, transCost = 0;
    float     w_rate = 0, r_rate = 0;
    uint32_t  w_time = 0, r_time = 0;
    uint8_t   *w_buff, *r_buff;
    uint8_t   *w_buff_global, *r_buff_global, *t_buff_global;
    uint32_t  *srio_trans_src, *srio_trans_dst;

    /* initialize variables */
    TSCL = 0;
    TSCH = 0;

    /* Get the cpu freq */
    main_pll_freq = platform_get_main_pll_freq();

    /* malloc buffer */
    w_buff = malloc(transfer_size);
    if(w_buff == NULL) {
        status = -1;

        printf("Failed to alloc meory !\r\n");

        goto err_alloc_wbuff;
    }

    r_buff = malloc(transfer_size);
    if(r_buff == NULL) {
        status = -1;

        printf("Failed to alloc meory !\r\n");

        goto err_alloc_rbuff;
    }

    /* convert the buffer address to global address */
    w_buff_global = (uint8_t *)Convert_CoreLocal2GlobalAddr((uint32_t)w_buff);
    r_buff_global = (uint8_t *)Convert_CoreLocal2GlobalAddr((uint32_t)r_buff);
    t_buff_global = (uint8_t *)target_addr;

    /* initialize the test data for buffer */
    for(i = 0; i < transfer_size; i++) {
        srand(i);
        w_buff[i] = rand() % 0xFF;;
        r_buff[i] = 0;
    }

    /* Loop times */
    for(j = 0; j < LOOP_TIMES; j++) {
        /* wait loopback complete time set as 10ms, base on cpu freq as 1000MHz */
        timeout = 10000000;

        /* 1.1 caculate the read and write buffer for srio transfer address */
        srio_trans_src = (uint32_t *)w_buff_global;
        srio_trans_dst = (uint32_t *)t_buff_global;

        /* 1.2 set transfer parameters, srio nwrite test, w_buff -> devmem_buff */
        memset((void *)&tparams, 0, sizeof(tparams));
        tparams.rapidIOLSB = (uint32_t)srio_trans_dst;
        tparams.dspAddress = (uint32_t)srio_trans_src;
        tparams.bytecount = transfer_size;
        if(w_format_type == Srio_Ftype_WRITE)
            tparams.ttype = Srio_Ttype_Write_NWRITE;
        tparams.ftype = w_format_type;
        tparams.dstID = REMOTE_DEVICEID1_8BIT;
        tparams.outPortID = SRIO_PORT;
        tparams.idSize = 0;

        /* wait lsu have available shadow register */
        while(1) {
            if (CSL_SRIO_IsLSUFull(hSrio, LSU_Number) == FALSE)
                break;
        }

        /* Get the LSU Context and Transaction Information. */
        CSL_SRIO_GetLSUContextTransaction(hSrio, LSU_Number,
                                           &contextBit, &transactionID);

        transStart = _itoll(TSCH, TSCL);

        /* start srio transfer */
        CSL_SRIO_SetLSUTransfer(hSrio, LSU_Number, &tparams);

        /* wait for a transfer completion interrupt occur */
        while(timeout) {
           CSL_SRIO_GetLSUCompletionCode(hSrio, LSU_Number, transactionID,
                                            &uiCompletionCode, &context);
           if(context == contextBit) {
               /* disable pending transactions */
               transactionID = 0xFF;
               contextBit = 0xFF;

               if(uiCompletionCode != 0) {
                    status = -1;

                    printf("SRIO transfer have error completed code %d\r\n", -(uiCompletionCode));

                    goto err_transfer;
               }

               break;
           } else {
                timeout--;
                /* delay 1 cpu cyle */
                asm (" nop");
           }
        }

        if(timeout == 0) {
            /* if transfer timeout occurs, return error status */
            status = -1;

            printf("SRIO transfer timeout\r\n");

            goto err_transfer;
        }

        /* Calculate srio transfer used time */
        transCost = _itoll(TSCH, TSCL) - transStart;
        w_time = transCost;

        /* Calculate srio transfer write rate */
        w_rate = (float)transfer_size * main_pll_freq / w_time / 1024 / 1024 / 1024 * 8;

        /* wait loopback complete time set as 10ms, base on cpu freq as 1000MHz */
        timeout = 10000000;

        /* 1.3 caculate the read and write buffer for srio transfer address */
        srio_trans_src = (uint32_t *)t_buff_global;
        srio_trans_dst = (uint32_t *)r_buff_global;

        /* 1.4 set transfer parameters, srio nread test, devmem_buff -> r_buff */
        memset((void *)&tparams, 0, sizeof(tparams));
        tparams.rapidIOLSB = (uint32_t)srio_trans_src;
        tparams.dspAddress = (uint32_t)srio_trans_dst;
        tparams.bytecount = transfer_size;
        tparams.ttype = Srio_Ttype_Request_NREAD;
        tparams.ftype = Srio_Ftype_REQUEST;
        tparams.dstID = REMOTE_DEVICEID1_8BIT;
        tparams.outPortID = SRIO_PORT;
        tparams.idSize = 0;

        /* wait LSU have available shadow register */
        while(1) {
            if (CSL_SRIO_IsLSUFull (hSrio, LSU_Number) == FALSE)
                break;
        }

        /* Get the LSU Context and Transaction Information. */
        CSL_SRIO_GetLSUContextTransaction(hSrio, LSU_Number,
                                           &contextBit, &transactionID);

        transStart = _itoll(TSCH, TSCL);

        /* start srio transfer */
        CSL_SRIO_SetLSUTransfer(hSrio, LSU_Number, &tparams);

        /* wait for a transfer completion interrupt occur */
        while(timeout) {
           CSL_SRIO_GetLSUCompletionCode(hSrio, LSU_Number, transactionID,
                                            &uiCompletionCode, &context);
           if(context == contextBit) {
               /* disable pending transactions */
               transactionID = 0xFF;
               contextBit = 0xFF;

               if(uiCompletionCode != 0) {
                    status = -1;

                    printf("SRIO transfer have error completed code %d\r\n", -(uiCompletionCode));

                    goto err_transfer;
               }

               break;
           } else {
                timeout--;
                /* delay 1 cpu cyle */
                asm (" nop");
           }
        }

        if(timeout == 0) {
            /* if transfer timeout occurs, return error status */
            status = -1;

            printf("SRIO transfer timeout\r\n");

            goto err_transfer;
        }

        /* Calculate srio transfer used time */
        transCost = _itoll(TSCH, TSCL) - transStart;
        r_time = transCost;

        /* Calculate srio transfer read rate */
        r_rate = (float)transfer_size * main_pll_freq / r_time / 1024 / 1024 / 1024 * 8;

        w_rate_total += w_rate;
        r_rate_total += r_rate;

        for(i = 0; i < transfer_size; i++) {
            if(w_buff_global[i] != r_buff_global[i]) {
                err_count++;
                if(err_count == 1) {
                    printf("Frist Err occurred src addr: 0x%x, dst addr: 0x%x\r\n", \
                                (uint32_t)&w_buff_global[i], (uint32_t)&r_buff_global[i]);
                    printf("dst val: 0x%x, ", r_buff_global[i]);
                    printf("expet val: 0x%x\r\n", w_buff_global[i]);
                }
            }
        }

        printf("=== loop times: %d | err_count: %d | ", j, err_count);
        if(w_format_type == Srio_Ftype_WRITE)
            printf("trans_size: %d Byte | NWRITE write times: %d ns(%.2f Gbps) | ", \
                transfer_size, w_time, w_rate);
        else if(w_format_type == Srio_Ftype_SWRITE)
            printf("trans_size: %d Byte | SWRITE write times: %d ns(%.2f Gbps) | ", \
                transfer_size, w_time, w_rate);
        printf("NREAD read times: %d ns(%.2f Gbps)\r\n", r_time, r_rate);
    }

err_transfer:
    free(r_buff);
err_alloc_rbuff:
    free(w_buff);
err_alloc_wbuff:

    return status;
}

Doorbell门铃中断

门铃中断基于keystone的demo进行修改,会涉及到三个地方
1.初始化中断函数
2.中断向量表建立
3.中断向量表的链接

1.初始化中断函数

中断部分函数是从keystone的SRIO例子中的SRIO_Test.c中摘抄出来的,原版的主要函数有
SRIO_Interrupts_Init();(初始化设置)
SRIO_Doorbell_ISR();(中断跳转函数)
KeyStone_SRIO_Interrupt_init(SRIO_Interrupt_Cfg * interrupt_cfg);(初始化应用)
以下为我这里修改的初始化,因为不需要message中断所以就只保留了doorbell的4中断。

void SRIO_Interrupts_Init(void)
{
	/*map SRIO doorbell interrupts to INT4.*/
	gpCGEM_regs->INTMUX1 = (CSL_GEM_INTDST_N_PLUS_16<<CSL_CGEM_INTMUX1_INTSEL4_SHIFT);

	//enable INT4
	CPU_interrupt_enable((1<<4));

	interrupt_cfg.interrupt_map = interrupt_map;
	interrupt_cfg.uiNumInterruptMap = 
		sizeof(interrupt_map)/sizeof(SRIO_Interrupt_Map);

	/*interrupt rate control is not used in this test*/
	interrupt_cfg.interrupt_rate= NULL;
    interrupt_cfg.uiNumInterruptRateCfg= 0;

	interrupt_cfg.doorbell_route_ctl= SRIO_DOORBELL_ROUTE_TO_DEDICATE_INT;

}

需要注意的是,中断初始化一定记到放到SRIO初始化后面,否则将会一直中断导致程序死掉。按下图放置
在这里插入图片描述
在这里插入图片描述

2.中断向量表建立

其实就是需要新建一个文件,小编直接从keystone里面复制粘贴了出来
在这里插入图片描述
下列代码是SRIO_vectors.asm的原始内容,由于小编不需要message中断,所以下列的.ref SRIO_Message_ISR需要去掉,然后VEC_ENTRY SRIO_Message_ISR ;interrupt 5改为VEC_DUMMY ;interrupt 5

;create interrupt vector table for C6000 DSP
;--------------------------------------------------------------
;This file can be modified to add Interrupt Service Routine(ISR) 
;for an interrupt, the steps are:
;1,reference to the externally defined ISR, for example
;	.ref EDMA_ISR
;2,modify the corresponding entry in the interrupt vector table.
;  For example, if interrupt 8 is used for EDMA, then you should
;  modify the entry number 8 like below:
;	VEC_ENTRY EDMA_ISR     	;interrupt 8 
;--------------------------------------------------------------
;Author: Brighton Feng
;Created on 2010-12-6
;--------------------------------------------------------------

;reference to the externally defined ISR
	.ref _c_int00
	.ref SRIO_Doorbell_ISR
	.ref SRIO_Message_ISR
	.ref Exception_service_routine
	.ref Nested_Exception_service_routine
	.ref exception_record

	.global vectors 

;--------------------------------------------------------------
	.sect ".text"
;create interrupt vector for NMI	
NMI_ISR:
	STW 	B1,*-B15[1]

	;save some key registers when exception happens
	MVKL  exception_record,B1
	MVKH  exception_record,B1

	STW 	B3, *+B1[0]
	STW 	A4, *+B1[1]
	STW 	B4, *+B1[2]
	STW 	B14, *+B1[3]
	STW 	B15, *+B1[4]
	
	;jump to exception service routine
	MVKL  	Exception_service_routine, B1
	MVKH  	Exception_service_routine, B1
	B 	B1

	LDW 	*-B15[1],B1
	NOP 	4

;--------------------------------------------------------------
;create interrupt vector for reset (interrupt 0)
VEC_RESET .macro addr
	MVKL  addr,B0
	MVKH  addr,B0
	B     B0
	MVC   PCE1,B0
	NOP   4
	.align 32
	.endm

;create interrupt vector for other used interrupts	
VEC_ENTRY .macro addr
	STW   B0,*--B15
	MVKL  addr,B0
	MVKH  addr,B0
	B     B0
	LDW   *B15++,B0
	NOP   4
	.align 32
	.endm

;create interrupt vector for unused interrupts	
VEC_DUMMY .macro
unused_int?:
	B    unused_int? ;dead loop for unused interrupts
	NOP  5
	.align 32
	.endm

	
;--------------------------------------------------------------
;interrupt vector table	
	.sect "vecs"
	.align 1024
	
vectors:
	VEC_RESET Nested_Exception_service_routine     		;Nested exception  
	VEC_ENTRY NMI_ISR	;NMI/Exception
	VEC_DUMMY   		;RSVD
	VEC_DUMMY   		;RSVD
	VEC_ENTRY SRIO_Doorbell_ISR   	;interrupt 4
	VEC_ENTRY SRIO_Message_ISR   	;interrupt 5
	VEC_DUMMY   		;interrupt 6
	VEC_DUMMY   		;interrupt 7
	VEC_DUMMY     		;interrupt 8 
	VEC_DUMMY   		;interrupt 9
	VEC_DUMMY   		;interrupt 10
	VEC_DUMMY   		;interrupt 11
	VEC_DUMMY   		;interrupt 12
	VEC_DUMMY   		;interrupt 13
	VEC_DUMMY   		;interrupt 14
	VEC_DUMMY   		;interrupt 15
	
	.end
	

3.中断向量表的链接

其实名字不一定叫这个,这块的主要作用就是把第二步的中断表给应用进去。
需要修改的文件为C66X.cmd,没错,是个cmd文件,用CCS建立项目的时候会自动生成。
如果没有这一步,那么生成的中断将会在0x00800000里循环卡死。
在这里插入图片描述
至此,中断完成,跑一下看看结果
在这里插入图片描述

完全没问题,DOORBELL被触发!

参考链接: 如何把中断服务程序加载到ISTP中
参考链接: DSP之SRIO通信之DSP端参数设置


http://www.niftyadmin.cn/n/5865179.html

相关文章

angular表格排序分页

说明: 使用angular实现表格&#xff0c;包括数据源&#xff0c;排序&#xff0c;分页 效果图&#xff1a; step1:C:\Users\Administrator\WebstormProjects\untitled4\src\app\setting\setting.component.ts import { Component, ViewChild, AfterViewInit } from angular/c…

一文讲解Redis中的数据一致性问题

一文讲解Redis中的数据一致性问题 在技术派实战项目中&#xff0c;我们采用的是先写 MySQL&#xff0c;再删除 Redis 的方式来保证缓存和数据库的数据一致性。 我举例说明一下。 对于第一次查询&#xff0c;请求 B 查询到的缓存数据是 10&#xff0c;但 MySQL 被请求 A 更新为…

WebXR教学 03 项目1 旋转彩色方块

一、项目结构 webgl-cube/ ├── index.html ├── main.js ├── package.json └── vite.config.js二、详细实现步骤 初始化项目 npm init -y npm install three vite --save-devindex.html <!DOCTYPE html> <html lang"en"> <head><…

Debain12.9安装大模型微调基础环境

Debain12.9安装大模型微调基础环境 硬件信息安装基础组件安装CUDA安装NVCC 硬件信息 操作系统&#xff1a;Debain 12.9/Ubuntu 24.04 CPU&#xff1a;i7-10750H 内存&#xff1a;32G 显卡&#xff1a;GTX 1650&#xff08;4G&#xff09; 硬盘&#xff1a;SSD&#xff08;1T&a…

基于同轴聚类点云去重的铆钉高度测量

基于同轴聚类点云去重的铆钉高度测量 一、引言二、解决方案三、实验效果四、实验部分代码 一、引言 本实验起源于工业检测领域一个普遍存在的需求——精确测量铆钉相对于料盘&#xff08;即基准平面&#xff09;的高度。 需求&#xff1a;如何准确测定铆钉至料盘表面的高度&am…

C++对象模型之C++额外成本

1.介绍 C与C最大的区别&#xff0c;无疑在于面向对象&#xff0c;面向对象编程给C带来了强大的特性和灵活性。但同时也带来了一定的运行时和编译时的开销。下面介绍C对象模型的额外成本及其来源。 2.C的额外成本 &#xff08;1&#xff09;虚函数和动态多态的成本 虚函数表&am…

硬件加速与技术创新双轮驱动:DeepSeek和ChatGPT性能进阶的未来蓝图

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络编程笔记&#xff1a; https://blog.cs…

UE地编材质世界对齐纹理旋转

帖子地址 https://forums.unrealengine.com/t/how-to-rotate-a-world-aligned-texture/32532/4世界对齐纹理本身不能改 自己创建了个函数 把世界对齐纹理的内容赋值粘贴 在纹理偏移里给值 不要局限0-1 给值给大一点