|
我用的本网站移植的一个范本,但是没有串口中断的部分,我依葫芦画写了一段,但是一给串口发数据系统就死机了,后来我参照ucos官网的例子改了下,也是不能用。
附程序代码:
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; ATmega128 Specific code for V2.8x
; (AVR-GCC 4.1.1)
;
;
; File : OS_CPU_A.ASM
; By : Xiawei <xiawei0311@gmail.com>
; AVR-GCC version : 4.1.1 , WinAVR 20070122
; Date : September 9th,2007
;
;********************************************************************************************************
#include <avr/io.h>
#define OS_CPU_A
#include "../Config/OS_CFG.h"
#include "OS_CPU.h"
;********************************************************************************************************
; I/O PORT ADDRESSES
;********************************************************************************************************
;********************************************************************************************************
; PUBLIC DECLARATIONS
;********************************************************************************************************
.global OSStartHighRdy
.global OSCtxSw
.global OSIntCtxSw
.global TIMER0_COMP_vect
.global OSTickISR
.global OSTickISR2
.global SIG_UART0_RECV
.global OSUART0ISR
.global OS_CPU_SR_Save
.global OS_CPU_SR_Restore
;********************************************************************************************************
; EXTERNAL DECLARATIONS
;********************************************************************************************************
.extern OSIntExit
.extern OSIntNesting
.extern OSPrioCur
.extern OSPrioHighRdy
.extern OSRunning
.extern OSTaskSwHook
.extern OSTCBCur
.extern OSTCBHighRdy
.extern OSTimeTick
.extern OSUart0Rec
;********************************************************************************************************
; MACROS
;********************************************************************************************************
; Push all registers and the status register
.macro PUSHRS
push r0
push r1
push r2
push r3
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push r16
push r17
push r18
push r19
push r20
push r21
push r22
push r23
push r24
push r25
push r26
push r27
push r28
push r29
push r30
push r31
in r16,_SFR_IO_ADDR(SREG)
push r16
.endm
; Pop all registers and the status registers
.macro POPRS
pop r16
out _SFR_IO_ADDR(SREG),r16
pop r31
pop r30
pop r29
pop r28
pop r27
pop r26
pop r25
pop r24
pop r23
pop r22
pop r21
pop r20
pop r19
pop r18
pop r17
pop r16
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
pop r3
pop r2
pop r1
pop r0
.endm
.macro PUSH_ALL
ST -Y,R0
ST -Y,R1
ST -Y,R2
ST -Y,R3
ST -Y,R4
ST -Y,R5
ST -Y,R6
ST -Y,R7
ST -Y,R8
ST -Y,R9
ST -Y,R10
ST -Y,R11
ST -Y,R12
ST -Y,R13
ST -Y,R14
ST -Y,R15
ST -Y,R16
ST -Y,R17
ST -Y,R18
ST -Y,R19
ST -Y,R20
ST -Y,R21
ST -Y,R22
ST -Y,R23
ST -Y,R24
ST -Y,R25
ST -Y,R26
ST -Y,R27
ST -Y,R30
ST -Y,R31
IN R16,_SFR_IO_ADDR(RAMPZ)
ST -Y,R16
.ENDM
.macro POP_ALL
LD R16,Y+
OUT _SFR_IO_ADDR(RAMPZ),R16
LD R31,Y+
LD R30,Y+
LD R27,Y+
LD R26,Y+
LD R25,Y+
LD R24,Y+
LD R23,Y+
LD R22,Y+
LD R21,Y+
LD R20,Y+
LD R19,Y+
LD R18,Y+
LD R17,Y+
LD R16,Y+
LD R15,Y+
LD R14,Y+
LD R13,Y+
LD R12,Y+
LD R11,Y+
LD R10,Y+
LD R9,Y+
LD R8,Y+
LD R7,Y+
LD R6,Y+
LD R5,Y+
LD R4,Y+
LD R3,Y+
LD R2,Y+
LD R1,Y+
LD R0,Y+
.ENDM
.macro PUSH_SREG
in r16 _SFR_IO_ADDR(SREG)
st -Y,r16
.endm
.macro PUSH_SP
in r16, _SFR_IO_ADDR(SPH)
st -Y,r16
in r16, _SFR_IO_ADDR(SPL)
st -Y,r16
.endm
.macro POP_SP
LD R16,Y+
OUT _SFR_IO_ADDR(SPL),R16
LD R16,Y+
OUT _SFR_IO_ADDR(SPH),R16
.endm
.macro POP_SREG_INT
LD R16,Y+
CBR R16,128
OUT _SFR_IO_ADDR(SREG),R16
.endm
.text
.section .text
;********************************************************************************************************
; START HIGHEST PRIORITY TASK READY-TO-RUN
;
; Description : This function is called by OSStart() to start the highest priority task that was created
; by your application before calling OSStart().
;
; Note(s) : 1) The (data)stack frame is assumed to look as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> LSB of (return) stack pointer (Low memory)
; SPH of (return) stack pointer
; Flags to load in status register
; R31
; R30
; R7
; .
; .
; .
; R0 (High memory)
;
; where the stack pointer points to the task start address.
;
;
; 2) OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;********************************************************************************************************
OSStartHighRdy:
#if OS_CPU_HOOKS_EN > 0
CALL OSTaskSwHook ; Invoke user defined context switch hook
#endif
LDS R16,OSRunning ; Indicate that we are multitasking
INC R16 ;
STS OSRunning,R16 ;
LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task
LDS R31,OSTCBHighRdy+1 ; ready to run
LD R28,Z+ ; Load stack L pointer
OUT _SFR_IO_ADDR(SPL),R28
LD R29,Z+ ;
OUT _SFR_IO_ADDR(SPH),R29
POPRS ; Pop all registers and status register
RET ; Start task
;********************************************************************************************************
; TASK LEVEL CONTEXT SWITCH
;
; Description : This function is called when a task makes a higher priority task ready-to-run.
;
; Note(s) : 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; SP+0 --> LSB of task code address
; +1 MSB of task code address (High memory)
;
; 3) The saved context of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> LSB of (return) stack pointer (Low memory)
; SPH of (return) stack pointer
; Flags to load in status register
; R31
; R30
; R7
; .
; .
; .
; R0 (High memory)
;********************************************************************************************************
OSCtxSw:
PUSHRS ; Save current tasks context
LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr
LDS R31,OSTCBCur+1 ;
IN r28,_SFR_IO_ADDR(SPL)
ST Z+,R28 ; Save Y (R29:R28) pointer
IN r29,_SFR_IO_ADDR(SPH)
ST Z+,R29 ;
#if OS_CPU_HOOKS_EN > 0
CALL OSTaskSwHook ; Call user defined task switch hook
#endif
LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
STS OSPrioCur,R16
LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task
LDS R31,OSTCBHighRdy+1 ; ready to run
STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy
STS OSTCBCur+1,R31 ;
LD R28,Z+ ; Restore Y pointer
OUT _SFR_IO_ADDR(SPL),R28
LD R29,Z+ ;
OUT _SFR_IO_ADDR(SPH),R29
POPRS ; Restore all registers and the status register
RETI
;*********************************************************************************************************
; INTERRUPT LEVEL CONTEXT SWITCH
;
; Description : This function is called by OSIntExit() to perform a context switch to a task that has
; been made ready-to-run by an ISR.
;
; Note(s) : 1) Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 2) The stack frame of the task to suspend looks as follows:
;
; SP+0 --> LSB of return address of OSIntCtxSw() (Low memory)
; +1 MSB of return address of OSIntCtxSw()
; +2 LSB of return address of OSIntExit()
; +3 MSB of return address of OSIntExit()
; possible SREG save
; +4 LSB of task code address
; +5 MSB of task code address (High memory)
;
; 3) The saved context of the task to resume looks as follows:
;
; OSTCBHighRdy->OSTCBStkPtr --> Flags to load in status register (Low memory)
; R31
; R30
; R7
; .
; .
; .
; R0 (High memory)
;*********************************************************************************************************
OSIntCtxSw:
#if OS_CPU_HOOKS_EN > 0
CALL OSTaskSwHook ; Call user defined task switch hook
#endif
LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
STS OSPrioCur,R16 ;
LDS R30,OSTCBHighRdy ; Z = OSTCBHighRdy->OSTCBStkPtr
LDS R31,OSTCBHighRdy+1 ;
STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy
STS OSTCBCur+1,R31 ;
LD R28,Z+ ; Restore Y pointer
OUT _SFR_IO_ADDR(SPL),R28
LD R29,Z+ ;
OUT _SFR_IO_ADDR(SPH),R29
POPRS ; Restore all registers and status register
RET
;********************************************************************************************************
; SYSTEM TICK ISR
;
; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred.
;
;
;********************************************************************************************************
TIMER0_COMP_vect:
OSTickISR:
PUSHRS ; Save all registers and status register
LDS R16,OSIntNesting ; Notify uC/OS-II of ISR
INC R16 ;
STS OSIntNesting,R16 ;
CLZ ;清零Z标志位,为下面的比较做好准备
CPI R16,1 ;比较OSIntNesting是否为1
BREQ OSTickISR2 ;如果是1,则跳转至OSTickISR2
SEI ; Enable interrupts
CALL OSTimeTick ; Call uC/OS-IIs tick updating function
CALL OSIntExit ; Notify uC/OS-II about end of ISR
POPRS ; Restore all registers and status register
RET ; Note: RET instead of RETI
OSTickISR2:
LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr
LDS R31,OSTCBCur+1 ;
IN r28,_SFR_IO_ADDR(SPL)
ST Z+,R28 ; Save Y (R29:R28) pointer
IN r29,_SFR_IO_ADDR(SPH)
ST Z+,R29 ;OSTCBCur->OSTCBStkPtr=SP
SEI ; 使能中断,继续执行OSTickISR中被打断的指令(可选用)
CALL OSTimeTick ; Call uC/OS-IIs tick updating function
CALL OSIntExit ; Notify uC/OS-II about end of ISR
POPRS ; Restore all registers and status register
RET ;
;******************************下面开始是我加的
SIG_UART0_RECV:
PUSH_ALL ; Save all registers and status register
IN R16,_SFR_IO_ADDR(SREG) ; Save the SREG but with interrupts enabled
SBR R16,128
ST -Y,R16
PUSH_SP ; Save the task's hardware stack pointer onto task's stack
LDS R16,OSIntNesting ; Notify uC/OS-II of ISR
INC R16 ;
STS OSIntNesting,R16 ;
CPI R16,1 ; if (OSIntNesting == 1) {
BRNE OSUART0ISR
LDS R30,OSTCBCur ; OSTCBCur->OSTCBStkPtr = Y
LDS R31,OSTCBCur+1
ST Z+,R28
ST Z+,R29 ; }
OSUART0ISR:
CALL OSUart0Rec ; Call tick Handler written in C
CALL OSIntExit ; Notify uC/OS-II about end of ISR
POP_SP ; Restore the hardware stack pointer from task's stack
POP_SREG_INT
POP_ALL ; Restore all registers
RETI
;********************我加的到此结束
;********************************************************************************************************
; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3
;
; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3.
;
; OS_CPU_SR OSCPUSaveSR (void)
; Get current value of SREG
; Disable interrupts
; Return original value of SREG
;
; void OSCPURestoreSR (OS_CPU_SR cpu_sr)
; Set SREG to cpu_sr
; Return
;********************************************************************************************************
OS_CPU_SR_Save:
IN R16,_SFR_IO_ADDR(SREG) ; Get current state of interrupts disable flag
CLI ; Disable interrupts
RET ; Return original SREG value in R16
OS_CPU_SR_Restore:
OUT _SFR_IO_ADDR(SREG),R16 ; Restore SREG
RET ; Return
说明:
1)PUSH_ALL和PUSHRS的功能是一样的,一个是ucos官网的例子,一个本网大虾移植的。
2)串口例程SIG_UART0_RECV是我加的,这个标号也是Atmega128的串口0的中断标识,我是参照TIMER0_COMP_vect的模式,不知道能否被识别
3)OSUart0Rec串口接收例程,在另外的主程序中
void OSUart0Rec(void)
{
if(UCSR0A & (1<<RXC0))
{
OS_ENTER_CRITICAL();
combuffer0=UDR0;
OS_EXIT_CRITICAL();
}
}
4)串口初始化代码
void InitComm()
{
// init usrt0
UCSR0A &=~(1<<U2X0);
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
UBRR0H = 0;
UBRR0L = 51;
/*
// init usrt1
UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
UBRR1H = 0;
UBRR1L = 51;
*/
}
不知道错在哪儿了?请大虾指正,先谢谢了。 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|