|
本帖最后由 yangc9 于 2018-5-27 16:30 编辑 STM32的bitband(位带)是个好东西.但是F0不支持.没关系,想办法给他模拟出来. 在F1中,可以这样使用IO口: __no_init vu32 PA[16] @ 0x42210180; __no_init vu32 PB[16] @ 0x42218180; ....... #define LED1 PA[1] #define LED2 PB[2] ........ LED1 = 0; // 亮灯 LED2 = 1; // 灭灯 ........ 把以上代码复制到F0的工程中,运行. 不出所料,进HardFault了.因为此段地址是保留的. 进HardFault时R1~3,R12,LR,PC,xPSR自动压栈. 低地址 R0 R1 R2 R3 R12 LR PC xPSR 高地址 PC的值为0x08000064,指向flash,里面的内容为0x6048,这是一条指令STR R0, [R1, #0x4] 知道了指令,就可以解读此条指令,并根据寄存器内容将指令转化为BRR和BSRR的动作. F0的写外设的指令是STR: STR Rt, [Rn {,#imm}] STR Rt, [SP {,#imm}] // 此条不用考虑, SP不可能指向外设区 STR Rt, [Rn, Rm] SP不可能指向外设区,不考虑PUSH指令 STMxx似乎也不用来操作外设区. 只需要解2种STR就可以了. 上代码: __task void HardFault_Handler(int uu1, int uu2, int uu3, int uu4, int R4, int R5, int R6, int R7, int HFLR, int R0, int R1, int R2, int R3, int R12, int LR, int16* volatile PC, int xPSR) { asm ("PUSH {R3-R7}"); uint16_t ins = *PC; int Rt, Addr; // STR Rt, [Rn {,#imm}] // imm <= 124 // 0x6000 | Rt | Rn << 3 | imm << 4 if ((ins & 0xF800) == 0x6000) { Rt = ins & 7; int Rn = ins >> 3 & 7; int imm = ins >> 4 & 124; if (Rn <= 3) Addr = *(&R0 + Rn) + imm; else Addr = *(&R4 + Rn - 4) + imm; } else if ((ins & 0xFE00) == 0x5000) { Rt = ins & 7; int Rn = ins >> 3 & 7; int Rm = ins >> 6 & 7; if (Rn <= 3) Addr = *(&R0 + Rn); else Addr = *(&R4 + Rn - 4); if (Rm <= 3) Addr += *(&R0 + Rm); else Addr += *(&R4 + Rm - 4); } if (Addr >= 0x42000000 && Addr < 0x44000000) { int port = (Addr >> 15 & 7) - 2; int pin = Addr >> 2 & 15; int RtVal; if (Rt <= 3) RtVal = *(&R0 + Rt); else RtVal = *(&R4 + Rt - 4); *(&GPIOA_BSRR + port * 0x100) = (RtVal & 1 | 0x10000) << pin; PC++; } asm ("POP {R3-R7}"); } 更新:解决R4-R7的bug. 美女说: 回帖送金币哦!
|
牛逼!!!![]() ![]() |
| 还好同事不在! |
微信公众号
手机版