TMS320C6748_NMI

目录

1.主函数流程

2.外设使能配置

3.GPIO管脚复用配置

4.DSP中断初始化

5.GPIO管脚初始化

6.中断服务函数


1.主函数流程

此程序的作用是实现不可屏蔽中断功能。NMI(NonMaskableInterrupt)——不可屏蔽中断(即CPU不能屏蔽),无论状态寄存器中IF位的状态如何,CPU收到有效的NMI必须进行响应。主函数如下:

int main(void)
{
  // 外设使能配置
  PSCInit();
  
  // GPIO 管脚复用配置
  GPIOBankPinMuxSet();
  
  // DSP 中断初始化
  InterruptInit();
  
  // GPIO 管脚初始化
  GPIOBankPinInit();
  
  // 主循环
  for(;;)
  {
  
  }
}

2.外设使能配置

    函数首先在PSC模块中使能外设,这里是GPIO模块。外设使能配置函数PSCInit如下:

void PSCInit(void)
{
  // 使能 GPIO 模块
  // 对相应外设模块的使能也可以在 BootLoader 中完成
  PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_GPIO, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
}

函数在PSC中使能HW_PSC_GPIO(#3)模块,该模块的Power Domain是ALWAYS_ON域(POWER DOMAIN 0),PSCModuleControl细节可参考这里:

C6748_UART_EDMA

                                                                                  (指南P163)

3.GPIO管脚复用配置

void GPIOBankPinMuxSet(void)
{
  // 配置相应的 GPIO 口功能为普通输入输出口
  // 核心板 LED
  GPIOBank6Pin12PinMuxSetup();
  GPIOBank6Pin13PinMuxSetup();
}

GPIOBank6Pin12PinMuxSetup函数和GPIOBank6Pin13PinMuxSetup函数将GPIO[12]和GPIO[13]这两个引脚设为普通输入输出口(即GPIO口)。这两个函数在demo\StarterWare\Application\Platform工程下的GPIO.c文件中,GPIOBank6Pin12PinMuxSetup函数如下:

void GPIOBank6Pin12PinMuxSetup(void)
{
  unsigned int savePinmux = 0;
  
  savePinmux = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(13)) &
  			 ~(SYSCFG_PINMUX13_PINMUX13_15_12));
  
  HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(13)) =
  	 (PINMUX13_GPIO6_12_ENABLE | savePinmux);
}

GPIOBank6Pin13PinMuxSetup函数如下:

void GPIOBank6Pin13PinMuxSetup(void)
{
  unsigned int savePinmux = 0;
  
  savePinmux = (HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(13)) &
  			 ~(SYSCFG_PINMUX13_PINMUX13_11_8));
  
  HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(13)) =
  	 (PINMUX13_GPIO6_13_ENABLE | savePinmux);
}

4.DSP中断初始化

    DSP中断初始化函数InterruptInit如下:

void InterruptInit(void)
{
  // 初始化 DSP 中断控制器
  IntDSPINTCInit();
  
  // 注册中断服务函数
  IntRegister(C674X_MASK_NMI, NMIIsr);
}

该函数中,首先初始化DSP中断控制器,IntDSPINTCInit函数细节见这篇博文:

C6748_SPI_FLASH

然后,程序将CPU不可屏蔽中断C674X_MASK_NMI(#1)的中断服务函数注册为NMIIsr函数。IntRegister函数参考这里:

C6748_EDMA_GPIO_中断学习笔记

NMI引脚低电平有效,当该引脚输入低电平时,将会发送不可屏蔽中断(NMEVT)。

(指南P27)

(Megamodule手册P167)

5.GPIO管脚初始化

    GPIO管脚初始化函数GPIOBankPinInit如下:

void GPIOBankPinInit(void)
{
  // 配置 LED 对应管脚为输出管脚
  // OMAPL138 及 DSP C6748 共有 144 个 GPIO
  // 以下为各组 GPIO BANK 起始管脚对应值
  // 范围 1-144
  // GPIO0[0] 1
  // GPIO1[0] 17
  // GPIO2[0] 33
  // GPIO3[0] 49
  // GPIO4[0] 65
  // GPIO5[0] 81
  // GPIO6[0] 97
  // GPIO7[0] 113
  // GPIO8[0] 129
  
  // 核心板 LED
  GPIODirModeSet(SOC_GPIO_0_REGS, 109, GPIO_DIR_OUTPUT);  // GPIO6[12]
  GPIODirModeSet(SOC_GPIO_0_REGS, 110, GPIO_DIR_OUTPUT);  // GPIO6[13]
}

该函数将GPIO6[12]脚和GPIO6[13]脚方向设为输出,GPIODirModeSet函数如下:

void GPIODirModeSet(unsigned int baseAdd, unsigned int pinNumber, 
                    unsigned int pinDir)

{
  unsigned int regNumber = 0;
  unsigned int pinOffset = 0;
  
  /*
  ** Each register contains settings for each pin of two banks. The 32 bits
  ** represent 16 pins each from the banks. Thus the register number must be
  ** calculated based on 32 pins boundary.
  */
  regNumber = (pinNumber - 1)/32;
  
  /*
  ** In every register the least significant bits starts with a GPIO number on
  ** a boundary of 32. Thus the pin offset must be calculated based on 32
  ** pins boundary. Ex: 'pinNumber' of 1 corresponds to bit 0 in 
  ** 'register_name01'.
  */
  pinOffset = (pinNumber - 1) % 32;
  
  if(GPIO_DIR_OUTPUT == pinDir)
  {
  	HWREG(baseAdd + GPIO_DIR(regNumber)) &= ~(1 << pinOffset);
  }
  else
  {
  	HWREG(baseAdd + GPIO_DIR(regNumber)) |= (1 << pinOffset);
  }
}

该函数设置GPIO_DIRn寄存器,从而配置GPIO引脚的输入输出方向。

6.中断服务函数

    中断服务函数如下:

#pragma NMI_INTERRUPT(NMIIsr)
void NMIIsr(void)
{
  GPIOPinWrite(SOC_GPIO_0_REGS, 109, Flag);
  // 翻转标志位
  Flag=!Flag;
  GPIOPinWrite(SOC_GPIO_0_REGS, 110, Flag);
}

其中,第一条语句为Pragma预处理指令,该指令使能直接用C代码处理不可屏蔽中断。

(CCS帮助文档)

在中断服务函数中,程序实现GPIO6[12]和GPIO6[13]两个引脚的输出翻转,GPIOPinWrite函数如下:

void GPIOPinWrite(unsigned int baseAdd, unsigned int pinNumber, 
                  unsigned int bitValue)
{
  unsigned int regNumber = 0;
  unsigned int pinOffset = 0;
  
  /*
  ** Each register contains settings for each pin of two banks. The 32 bits
  ** represent 16 pins each from the banks. Thus the register number must be
  ** calculated based on 32 pins boundary.
  */
  
  regNumber = (pinNumber - 1)/32;
  
  /*
  ** In every register the least significant bits starts with a GPIO number on
  ** a boundary of 32. Thus the pin offset must be calculated based on 32
  ** pins boundary. Ex: 'pinNumber' of 1 corresponds to bit 0 in 
  ** 'register_name01'.
  */
  
  pinOffset = (pinNumber - 1) % 32;
  
  if(GPIO_PIN_LOW == bitValue)
  {
  	HWREG(baseAdd + GPIO_CLR_DATA(regNumber)) = (1 << pinOffset);
  }
  else if(GPIO_PIN_HIGH == bitValue)
  {
  	HWREG(baseAdd + GPIO_SET_DATA(regNumber)) = (1 << pinOffset);
  }
}

函数根据要输出的电平是高还是低,往GPIO_CLR_DATA寄存器和GPIO_SET_DATA寄存器的相应位写1,如果输出的是低电平,则往GPIO_CLR_DATA寄存器的相应位写1;如果输出的是高电平,则往GPIO_SET_DATA寄存器的相应位写1。

(指南P853)

(指南P854)

(指南P855)

(指南P856)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值