Root Cause of Motor Over Run
|
The application is a disk loader in optical disk driver. This software module controls the motor operation according to the external interrupt from a position sensor. This module works fine independently, but the motor can not stop at the designated position occasionally after integration with other modules. br>
The engineer checked the code for the motor driver. This code is very simple, which writes port register with H/L values.
br>
volatile unsigned char *io_port = 0xFF00
void motor_on(void)
{
*io_port |= 0x04;
}
void motor_off(void)
{
*io_port &= 0xFB;
}
The engineer captured and stopped the code execution with a debugger, he found even the port register was written with a High, the external port kept as Low. Finally, he turned to a senior engineer (Mr. T) for help. Mr. T reviewed the assembly code of above C source. The single C operation is made up of four assembly instructions, which are shown as following:
*io_port &= 0xFB;
mov #0xFF00, r3 ; move port register address to r3 mov @r3, r1 ; move port register content to r1 and #0xFB, r1 ; logical operation mov r1, @r3 ; move result back to port register
Meanwhile Mr. T also found a timer driven LED is also sharing with the same pin with motor control, and the timer interrupt priority is lower than the motor control external interrupt. After a short survey, Mr. T simulated the occurrence of the bug.
;LED driver in timer interrupt (currently Motor is ON) mov #0xFF00, r4 mov @r4, r2 or #0x40,r2 ;Interrupt from Motor control mov #0xFF00, r3 ; move port register address to r3 mov @r3, r1 ; move port register content to r1 and #0xFB, r1 ; logical operation mov r1, @r3 ; move result back to port register ;switch back to LED timer interrupt, now Motor is OFF mov r2,@r4 ;The motor is switched to ON, since the bit2 is written with H
Mr. T offered 3 solutions:
- The software should depoly interrupt mask mutex approach. During the critical motor operation, the rest of interrupts should be disabled.
- Move the port operation out of the interrupt service routine to the main loop. Disable multiple thread access to the port register. However the scheduling of RTOS task should be designed very well. Otherwise there are some other side effects.
- Re-allocate the port access time frame for each tasks or change the I/O usage for different tasks.
Since the hardware layout is hard to change at that moment and no RTOS is involved, finally solution A is approved.
Conclusion
In classic 8051, the port registers are bit-addressable, but more RISC microcontrollers use memory map port registers. As a result, port access takes one machine instruction cycle in 8051, while takes more instruction cycles in RISC microcontrollers. The port access in RISC maybe be interrupted and altered.
Because the port access is just one line of code in C language, it is very common to ignore it. If you are going to port the design from CISC to RISC microcontroller, you should take care of it.
The same principle also effective in timers and DMA access. The engineers should remind themselves of this issue during designing the software architect.
- allankliu's blog
- Login or register to post comments
- 318 reads


