配音网站赚钱2022近期重大新闻事件10条
背景:我用的S32K3系列单片机,这芯片的RAM有ECC,就是说上电后如果你不写RAM,直接去读,就会触发ECC故障,然后进入hardfault.于是我就想实现Try Catch,想办法从Hardfault中跳出来。理论上支持CM系列,我只实现了Free RTOS的. 裸机也可以的。。包括STM32...实现代码:
核心汇编部分:
#if (configNumberOfExceptionStacks > 0)int xPortUpdateSignalCode(ExceptionContext_t *pxExceptionContext){// 根据寄存器判断是哪些错误码,然后返回对应的信号。这里简单返回总线错误return SIGBUS;}__attribute__((naked)) HardFault_Handler(void){__asm volatile("TST lr, #0x04 \n" // ; if(!EXC_RETURN[2])"ITE EQ \n""MRSEQ r0, msp \n" //; [2]=0 ==> Z=1, get fault context from handler.""MRSNE r0, psp \n" //; [2]=1 ==> Z=0, get fault context from thread."/*" tst lr, #0x10 \n" Is the task using the FPU context? If so, push high vfp registers. *//*" it eq \n"*//*" vstmdbeq r0!, {s16-s31} \n"*/"stmdb r0!, {r4-r11,lr} \n" "push {r0} \n""BL vExceptionHappened \n" // vExceptionHappened(r0); r0=异常长下文的栈结构体地址,r1=是否发生在中断"pop {r0} \n""ldmia r0!, {r4-r11,lr} \n" /* Pop the core registers. */"TST lr, #0x04 \n" // ; if(!EXC_RETURN[2])"ITE EQ \n""MSREQ msp, r0 \n" //; [2]=0 ==> Z=1, update stack pointer to MSP.""MSRNE psp, r0 \n" //; [2]=1 ==> Z=0, update stack pointer to PSP.""isb \n""bx lr\n");}
#else
void HardFault_Handler(void)
{while (1){}
}
#endif
FreeRTOS.h:
#if ( configNumberOfExceptionStacks >0 )
#include <setjmp.h>#define SIGHUP 1 /* hangup */
#define SIGINT 2 /* interrupt */
#define SIGQUIT 3 /* quit */
#define SIGILL 4 /* illegal instruction (not reset when caught) */
#define SIGTRAP 5 /* trace trap (not reset when caught) */
#define SIGIOT 6 /* IOT instruction */
#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */
#define SIGEMT 7 /* EMT instruction */
#define SIGFPE 8 /* floating point exception */
#define SIGKILL 9 /* kill (cannot be caught or ignored) */
#define SIGBUS 10 /* bus error */
#define SIGSEGV 11 /* segmentation violation */
#define SIGSYS 12 /* bad argument to system call */
#define SIGPIPE 13 /* write on a pipe with no one to read it */
#define SIGALRM 14 /* alarm clock */
#define SIGTERM 15 /* software termination signal from kill */ #define SIGURG 16 /* urgent condition on IO channel */
#define SIGSTOP 17 /* sendable stop signal not from tty */
#define SIGTSTP 18 /* stop signal from tty */
#define SIGCONT 19 /* continue a stopped process */
#define SIGCHLD 20 /* to parent on child stop or exit */
#define SIGCLD 20 /* System V name for SIGCHLD */
#define SIGTTIN 21 /* to readers pgrp upon background tty read */
#define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */
#define SIGIO 23 /* input/output possible signal */
#define SIGPOLL SIGIO /* System V name for SIGIO */
#define SIGWINCH 24 /* window changed */
#define SIGUSR1 25 /* user defined signal 1 */
#define SIGUSR2 26 /* user defined signal 2 */#endif
task.c修改:
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL; //原内核代码
PRIVILEGED_DATA UBaseType_t volatile xExceptionHappen = 0;//我加的#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )//原内核代码void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];#endif//我加的#if ( configNumberOfExceptionStacks > 0 )UBaseType_t uxJmpStacksCounter;jmp_buf JmpStacks[configNumberOfExceptionStacks];volatile ExceptionContext_t xExceptionContext;volatile int xThrowCode;#endif#if ( configGENERATE_RUN_TIME_STATS == 1 )configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */#endif
task.c:
#if (configNumberOfExceptionStacks >0)
inline jmp_buf *xGetJmpStackOfCurrentTask()
{TCB_t *self=(TCB_t *)xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);return self->JmpStacks[self->uxJmpStacksCounter];
}
inline void jmp_stack_push()
{TCB_t *self=(TCB_t *)xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);self->uxJmpStacksCounter++;
}inline jmp_buf* jmp_stack_pop()
{TCB_t *self=(TCB_t *)xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);return &self->JmpStacks[--self->uxJmpStacksCounter];
}void vInternalExceptionProcess ()
{taskENTER_CRITICAL();{xExceptionHappen--;}taskEXIT_CRITICAL();TCB_t *self=(TCB_t *)xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);UBaseType_t tempJmpStacksCounter=0;taskENTER_CRITICAL();{tempJmpStacksCounter=self->uxJmpStacksCounter;}taskEXIT_CRITICAL();if(tempJmpStacksCounter==0){extern void vExceptionProcess(TaskHandle_t pxCurrentTask,volatile ExceptionContext_t *pxExceptionContext);vExceptionProcess(self,&self->xExceptionContext);}else{_throw_(self->xThrowCode);//to do}while(1){vTaskDelay(1000);}
}
/**/
void vExceptionHappened(ExceptionContext_t *pxExceptionContext)
{ xExceptionHappen++;if(xExceptionHappen>1){while(1);//no use configASSERT}TCB_t *self=xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);extern int xPortUpdateSignalCode(ExceptionContext_t *pxExceptionContext);self->xThrowCode=xPortUpdateSignalCode(pxExceptionContext);memcpy((ExceptionContext_t *)&self->xExceptionContext,pxExceptionContext,sizeof(ExceptionContext_t));pxExceptionContext->exception_stack_frame.pc=(BaseType_t)vInternalExceptionProcess;
}
ExceptionContext_t* xGetExceptionContext(void)
{TCB_t *self=xTaskGetCurrentTaskHandle();configASSERT(self!=NULL);return &self->xExceptionContext;
}
#endif
task.h:
#if (configNumberOfExceptionStacks >0)void jmp_stack_push() PRIVILEGED_FUNCTION;
jmp_buf* jmp_stack_pop() PRIVILEGED_FUNCTION;
jmp_buf *xGetJmpStackOfCurrentTask() PRIVILEGED_FUNCTION;
#define _try_ \jmp_buf *__jmp_buf= xGetJmpStackOfCurrentTask(); \int __jmp_result = setjmp(*__jmp_buf); \if (!__jmp_result) jmp_stack_push(); \if (!__jmp_result)#define _catch_(x) \int x = __jmp_result; \if (!x) jmp_stack_pop(); \else#define _throw_(x) longjmp(*jmp_stack_pop(), x);void vExceptionHappened(ExceptionContext_t *pxExceptionContext);
ExceptionContext_t* xGetExceptionContext(void);
#else#define _try_
#define _catch_(x)
#define _throw_(x)#endif
portmacro.h: (我用S32K自带的LIBC库的Setjmp和longJmp反汇编没有保存浮点,所以我也没保存,实际你需要保存,我try块里用不到浮点,所以没保存,如果要保存自行修改结构体和hardfault汇编哦)
#if (configNumberOfExceptionStacks >0)#include "Mcal.h"
#include "core_cm7.h"
struct exception_stack_frame
{BaseType_t r0;BaseType_t r1;BaseType_t r2;BaseType_t r3;BaseType_t r12;BaseType_t lr;//这个LR是异常发生后,硬件自动入栈的LRBaseType_t pc;BaseType_t psr;
};
typedef struct stack_frame
{BaseType_t exc_return;//这个LR是进入异常函数后,LR的实时状态。/* r4 ~ r11 register */BaseType_t r4;BaseType_t r5;BaseType_t r6;BaseType_t r7;BaseType_t r8;BaseType_t r9;BaseType_t r10;BaseType_t r11;#if 0BaseType_t s16;BaseType_t s17;BaseType_t s18;BaseType_t s19;BaseType_t s20;BaseType_t s21;BaseType_t s22;BaseType_t s23;BaseType_t s24;BaseType_t s25;BaseType_t s26;BaseType_t s27;BaseType_t s28;BaseType_t s29;BaseType_t s30;BaseType_t s31;#endifstruct exception_stack_frame exception_stack_frame;
}ExceptionContext_t;#endif
调用:
_try_{uint32_t *addr = (uint32_t *)(&__BootAppComSramStart__);return *addr;}_catch_(x){return 0;}