Cortex-M3 / M4硬故障处理程序 打印处理

Cortex-M3 / M4硬故障处理程序

https://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/

 

第5章   任务切换设计

http://blog.sina.com.cn/s/blog_98ee3a930102v7zv.html

 

STM32常见Hard+Fault的诊断

https://wenku.baidu.com/view/3c1146ddd5bbfd0a795673f3.html

 

__ASM void HardFault_Handler(void)
{
      TST lr, #4     // Test for MSP or PSP 测试EXC_RETURN的比特2
      ITE EQ         //如果为0,
      MRSEQ r0, MSP  //则使用的是主堆栈,故把MSP的值取出
      MRSNE r0, PSP  //否则, 使用的是进程堆栈,故把MSP的值取出
      IMPORT HardFault_Handler_C  //从栈中读取PC的值
      B HardFault_Handler_C  //从SVC指令中读取立即数放到R0
}

//HardFault_Handler

void HardFault_Handler_C (unsigned int * hardfault_args)
{
  unsigned int stacked_r0;
  unsigned int stacked_r1;
  unsigned int stacked_r2;
  unsigned int stacked_r3;
  unsigned int stacked_r12;
  unsigned int stacked_lr;
  unsigned int stacked_pc;
  unsigned int stacked_psr;
 
  stacked_r0 = ((unsigned long) hardfault_args[0]);
  stacked_r1 = ((unsigned long) hardfault_args[1]);
  stacked_r2 = ((unsigned long) hardfault_args[2]);
  stacked_r3 = ((unsigned long) hardfault_args[3]);
 
  stacked_r12 = ((unsigned long) hardfault_args[4]);
  stacked_lr = ((unsigned long) hardfault_args[5]);
  stacked_pc = ((unsigned long) hardfault_args[6]);
  stacked_psr = ((unsigned long) hardfault_args[7]);
 
  printf ("\n\n[Hard fault handler - all numbers in hex]\r\n");
  printf ("R0 = 0x%08X\r\n", stacked_r0);
  printf ("R1 = 0x%08X\r\n", stacked_r1);
  printf ("R2 = 0x%08X\r\n", stacked_r2);
  printf ("R3 = 0x%08X\r\n", stacked_r3);
  printf ("R12 = 0x%08X\r\n", stacked_r12);
  printf ("LR [R14] = 0x%08X  subroutine call return address\r\n", stacked_lr);
  printf ("PC [R15] = 0x%08X  program counter\r\n", stacked_pc);
  printf ("PSR = 0x%08X\r\n", stacked_psr);
  printf ("BFAR = 0x%X\r\n", (*((volatile unsigned long *)(0xE000ED38))));
  printf ("CFSR = 0x%X\r\n", (*((volatile unsigned long *)(0xE000ED28))));
  printf ("HFSR = 0x%X\r\n", (*((volatile unsigned long *)(0xE000ED2C))));
  printf ("DFSR = 0x%X\r\n", (*((volatile unsigned long *)(0xE000ED30))));
  printf ("AFSR = 0x%X\r\n", (*((volatile unsigned long *)(0xE000ED3C))));
  printf ("SCB_SHCSR = %X\r\n", SCB->SHCSR);
 
  while (1);
} 

10min滑动平均滤波算法

long i32VrmsSum;//电压
int i16Vrms;//电压
long i32CtIrms,i32CtIsum;//电流

s16 After_filter[2][100];

u8 L1Voltage10minIndex,L2Voltage10minIndex,L3Voltage10minIndex;
u16 L1Voltage10minSumBuf[10] = {2350,2350,2350,2350,2350,2350,2350,2350,2350,2350},L2Voltage10minSumBuf[10],L3Voltage10minSumBuf[10];
long L1Voltage10minSum = 23500,L2Voltage10minSum,L3Voltage10minSum;
long L1Voltage10minAvg = 2350,L2Voltage10minAvg,L3Voltage10minAvg;

u8 L1Voltage1minIndex,L2Voltage1minIndex,L3Voltage1minIndex;
u16 L1Voltage1minSumBuf[20] = {2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350,2350},L2Voltage1minSumBuf[20],L3Voltage1minSumBuf[20];
long L1Voltage1minSum = 47000,L2Voltage1minSum,L3Voltage1minSum;
long L1Voltage1minAvg = 2350,L2Voltage1minAvg,L3Voltage1minAvg;

void OVAV_10min_average(void)
{
	static u8 w3sTimerCnt = 0,w10minTimerCnt;
	if(++w3sTimerCnt >= 120)//3s
	{
		w3sTimerCnt = 0;
		
		if(L1Voltage1minIndex >= 20)
		{
			L1Voltage1minIndex = 0;
		}
		
		L1Voltage1minSum = L1Voltage1minSum - L1Voltage1minSumBuf[L1Voltage1minIndex];
		L1Voltage1minSumBuf[L1Voltage1minIndex] = Hold_Data_HoldingBuf->VoltageL1;
		L1Voltage1minSum += L1Voltage1minSumBuf[L1Voltage1minIndex];
		L1Voltage1minIndex++;
		L1Voltage1minAvg = L1Voltage1minSum/20;//1min avg
		
		if(++w10minTimerCnt > 20)//60s
		{
			w10minTimerCnt = 0;

			if(L1Voltage10minIndex >= 10)
			{
				L1Voltage10minIndex = 0;
			}
			L1Voltage10minSum = L1Voltage10minSum - L1Voltage10minSumBuf[L1Voltage10minIndex];
			L1Voltage10minSumBuf[L1Voltage10minIndex] = L1Voltage1minAvg;
			L1Voltage10minSum = L1Voltage10minSum + L1Voltage10minSumBuf[L1Voltage10minIndex];
			L1Voltage10minIndex++;
			L1Voltage10minAvg = L1Voltage10minSum/10;
			Hold_Data_HoldingBuf->OVAV_L1 = L1Voltage10minAvg;
		} 
	}
}
void filter(void)
{
	u8 count,i;
	i32CtIsum = 0;
	i32VrmsSum = 0;
	for(i = 0;i < 2;i++)
	{
		for (count = 0; count < 100; count++)
		{
			After_filter[i][count] = (s16)ADC_RCVTab[2 * count + i] - 2048; 
		}	
	}
	
	for (i = 0; i < 100; i++)
	{
		i32CtIsum += After_filter[0][i] * After_filter[0][i];
		//*! 2018-11-01 18:25:53 计算有效值
		i32VrmsSum += After_filter[1][i] * After_filter[1][i];  
	}			
}

STM32之汇编操作

    常用的指令说明。

指令名称  作用
EQU  给数字常量取一个符号名,相当于 C 语言中的 define
AREA  汇编一个新的代码段或者数据段
SPACE  分配内存空间
PRESERVE8  当前文件栈需按照 8 字节对齐
EXPORT  声明一个标号具有全局属性,可被外部的文件使用
DCD  以字为单位分配内存,要求 4 字节对齐,并要求初始化这些内存
PROC  定义子程序,与 ENDP 成对使用,表示子程序结束
WEAK  弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。要注意的是:这个不是 ARM
的指令,是编译器的,这里放在一起只是为了方便。
IMPORT  声明标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似
跳转到一个标号
ALIGN  编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即
数,缺省表示 4 字节对齐。要注意的是:这个不是 ARM 的指令,是
编译器的,这里放在一起只是为了方便。
END  到达文件的末尾,文件结束
IF,ELSE,ENDIF  汇编条件分支语句,跟 C 语言的 if else 类似
MRS  加载特殊功能寄存器的值到通用寄存器
MSR  存储通用寄存器的值到特殊功能寄存器
CBZ  比较,如果结果为 0 就转移
CBNZ  比较,如果结果非 0 就转移
LDR  从存储器中加载字到一个寄存器中
LDR[伪指令]  加载一个立即数或者一个地址值到一个寄存器。 举例: LDR Rd, = label,
如果 label 是立即数,那 Rd 等于立即数, 如果 label 是一个标识符,比如
指针,那存到 Rd 的就是 label 这个标识符的地址
LDRH  从存储器中加载半字到一个寄存器中
LDRB  从存储器中加载字节到一个寄存器中
STR  把一个寄存器按字存储到存储器中
STRH  把一个寄存器存器的低半字存储到存储器中
STRB  把一个寄存器的低字节存储到存储器中
LDMIA  加载多个字,并且在加载后自增基址寄存器
STMIA  存储多个字,并且在存储后自增基址寄存器
LDMFD  
ORR  按位或
BX  直接跳转到由寄存器给定的地址
BL  跳转到 标号对应的地址,并且把跳转前的下条指令地址保存到 LR
BLX  跳转到由寄存器 REG 给出的的地址,并根据 REG 的 LSB 切换处理器状
态 , 还 要 把 转 移 前 的 下 条 指 令 地 址 保 存 到 LR 。 ARM(LSB=0) ,
Thumb(LSB=1)。 CM3 只在 Thumb 中运行,就必须保证 reg 的 LSB=1,否则一个 fault 打过来

 

你可能感兴趣的:(stm32)