⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avrx介绍.txt

📁 这个是我下载的关于AVR运行实时操作系统AVRX的中文文档
💻 TXT
📖 第 1 页 / 共 2 页
字号:

①AVRX的源码都是用汇编语言编写的,相对来讲代码效率很高,但是由于没有详细的API介绍文档,所以最好的入门方法就是先读懂
RTOS的源码和例程,然后进行修改,再加上自己的代码逐渐熟练应用。

②AVRX需要分配的堆栈为35个字节加上任务代码需要的额外堆栈,具体的大小取决于每个进程用的本地变量个数。比较好的确定分配
给任务堆栈大小的方法是:分配很大的堆栈(如70字节)运行一段应用程序后看堆栈到多深(因为GCC启动时把所有内存都清0了,这样
很容易看到)。不过,为了安全起见,用编译器或仿真器在估计堆栈的顶端写入几个字节的0xFFFFF去验证到底达到了多少字节,然后
分配给比测试结果多两个以上的字节给这个任务。

③启动的最后一个指令必须跳转到Epilog()。

5 结论

AVRX是一个不错的RTOS,最显著的特点就是内核小,速度快,编译后大概只需500~700字节,且基本的调度功能一个也不少。由于其
代码公开,结合不同型号AVR单片机的特性,可以在此基础上进行系统的裁减和扩展,使之能达到更好的效果,本文为AVR嵌入式系统
的应用提供了借鉴。




Overview:

AvrX - a lightweight Real Time Operating System (RTOS) for the Atmel AVR family of micro-controllers.

Features:
bullet	Fully pre-emptive, priority driven scheduler
bullet	Sixteen priority levels. Tasks with the same priority round robin schedule on a cooperative basis
bullet	Semaphores can be used for either signaling/synchronization or as mutual exclusion semaphores. Both blocking and non-blocking semantic are available
bullet	Message Queues support passing information back and forth between Tasks. Blocking and non-blocking calls are available for receipt and acknowledgement of messages.
bullet	Most non-blocking services are available when in interrupt routines.
bullet	Time Queue Manager supports single event timers. Any process can set up a timer and any process can wait on the expiration of a timer.
bullet	AvrX Supports single step debugging of running processes. The supplied monitor uses the AvrX API to halt, step and resume processes.
bullet	Small: About 700-1000 words of code space needed for all features.  
bullet	Fast: with a 10mhz clock rate a 10khz system clock rate consumes about 20% of the processor while actively tracking a timer (211 cycles including the interrupt and return).
bullet	Many chores usually delegated to timer/counter subsystems can be written as task level code with AvrX.

Tasks:

    For AvrX 2.3, the standard context switch includes all index registers X, Y & Z, R0 (LPM), SREG and the current Program Counter, a total of 10 bytes.  In addition, on a process basis, additional registers can be saved to the context. All registers can be saved at the cost of only 92 additional cycles per round trip context save/restore. All registers (standard and user saved) are filled with 0x00 when the task is initialized (AvrXInitTask).

    For AvrX 2.6, in order to support C, all registers need to be saved.  The minimum context is the 32 registers, SREG and the PC, for a total of 35 bytes.  Again, AvrXInitTask() fills all registers with 0x00.

    Only the process context is saved on the Tasks stack. All other stack usage (Kernel and interrupts) are saved on the kernel stack. This minimizes the usage of SRAM at the expense of a context switch for the first interrupt or entry into a kernel API.  Subsequent interrupts (if nesting is allowed) simply nest on the kernel stack.  For AvrX 2.5 a few API push one or two bytes onto the user stack.  But these API don't perform a context switch.

    The remaining task information (Stack pointer, or, Context Pointer) are stored in the The Process ID block (PID).  The PID structure uses six bytes of SRAM.  The additional SRAM is the pointer for queuing processes and the status bits & Priority byte.  The structure of the PID is different between 2.3 and 2.5/6 - refer to the header files for more information.

    Task Control Block is a code (flash) based table that is used to initialize a process. See sample code or AvrX.inc or AvrX.h for layout information.

    bullet	AvrXInitTask
    bullet	AvrXRunTask
    bullet	AvrXSuspend
    bullet	AvrXResume
    bullet	AvrXTaskExit
    bullet	AvrXTerminate
    bullet	AvrXHalt

Semaphores:

    Semaphores are an SRAM pointer. They have three states: PEND, WAITING and DONE. When a process is blocked on a Semaphore, it is in the WAITING state. Multiple processes can queue waiting for a Semaphore. In the latter case the semaphore can be thought of as a Mutual Exclusion Semaphore. This is used in AvrX to control access to the EEPROM interface. More typically, Semaphores are used as communications flags between interrupt routines and tasks. They are also used to synchronize tasks with Timers and Messages.
    bullet	AvrXSetSemaphore AvrXIntSetSemaphore
    bullet	AvrXWaitSemaphore
    bullet	AvrXTestSemaphore AvrXIntTestSemaphore
    bullet	AvrXResetSemaphore

Timers:

    Timer Control Blocks (TCB) are 4 (6) bytes long. They manage a 16 bit count value. The timer queue manager maintains a sorted queue of timers, each adjusted such that the sum of all timers up to and including the timer in question equal the delay value specified for that timer. Canceling a timer re-adjusts the queue so all times come out correct.

    API
    bullet	AvrXStartTimer
    bullet	AvrXTimerHandler
    bullet	AvrXCancelTimer
    bullet	AvrXWaitTimer
    bullet	AvrXTestTimer
    bullet	AvrXDelay

    In AvrX 2.6 there is an additional variation of the timer queue block, the TimerMessageBlock. Timer messages are used in the TimerMessage example code.  In short, when the timer expires, a message is queued onto a message queue.  In this way a task can wait for multiple events by waiting on a message queue.
    bullet	AvrXStartTimerMessage
    bullet	AvrXCancelTimerMessage

Message Queues:

    Message queues are defined with a Message Control Block (MCB) as the head of a queue. Messages can be queued by any process or interrupt handler and multiple processes can wait on a message queue (although there are not too many reasons for doing this). The MCB is two or four bytes long, depending upon AvrX Version. The element is a link to the next message or process in the queue. The second element is the semaphore used to signal the process waiting on the queue. The message can be thought of as more flexible form of semaphore. They can be queued up and acknowledged, or simply treated as a baton for a mutual exclusion semaphore.  Data or a pointer can be appended to the end of a message, etc.
    bullet	AvrXSendMessage
    bullet	AvrXIntSendMessage
    bullet	AvrXRecvMessage
    bullet	AvrXWaitMessage
    bullet	AvrXAckMessage
    bullet	AvrXTestMessageAck
    bullet	AvrXWaitMessageAck

Single Step Support

    AvrX has single step support that can be enabled/disabled by re-assembling the kernel. Single Step Support is enabled by defining the following variable when building the kernel library:

    #define SINGLESTEPSUPPORT

    NOTE: the file "AvrX.h", used by C code needs the above defined as well or the size of the PID will be wrong.  

    A process must be halted before it can be single stepped. There are two ways to do this: first, just initialize the process without running it (AvrXInitTask), the second is to call AvrXSuspend with the target process ID. Once the target is suspended the debug API can be called
    bullet	AvrXStepNext
    bullet	AvrXSingleStepNext

    The supplied monitor has two different step options: the first being to step between blocking calls to the kernel (e.g. AvrXWaitxxxx) This was the extent of the support in early versions. The second generates an interrupt on TIMER0 before restoring the process. The process will execute one instruction before recognizing the interrupt. Upon kernel entry that process will be removed from the run queue and re-suspended. One note: every attempt was made to not affect the system clock (TIMER0) but every so often a timer tick will be lost: pending timer interrupts will be overridden by the single step interrupt.  Of course, if TIMER1 were the system clock, then there would be no conflict between Single Step and the system clock.  Also note: in order for SS to work, additional code needs to be inserted into the TIMER0 interrupt handler.  Please refer to the sample code to see how this works.

SystemObjects:

    AvrX is built around the notion of a system object. System Objects contain a link and a semaphore followed by 0 or more bytes of data. Process Objects (PID) can queue on the Run Queue or on a Semaphore. Timer Control Blocks (TCB) can only be queued on the Timer Queue. Message Control Blocks (MCB) may queued only on a Message Queue. Processes wait on objects (timers, messages, message ack) by queuing (waiting) on the embedded semaphore in the object.

    In AvrX 2.3 (IAR version) all system data structures (Objects and Semaphores) objects are within the first page of memory and can be addressed a single byte address. Because the Avr micro-controllers use the first 96 bytes of the linear address map for registers and I/O, only 160 bytes are available for system data structures. This limits the size of an AvrX application to about 12 each of Timers, Tasks, Semaphores and Messages.  There is no such restriction for AvrX 2.5/6 (C version) as all pointers are 16 bits long.  The only restriction would be for future AVR chips that directly support more than 64kb of SRAM: all AvrX structures would have to be located in the first 64kb of ram.

    The main limit to system size is the available SRAM for process stacks, which need a minimum of 10 to 35 bytes (depending upon version) to store a process context. There is no additional stack needed for processing interrupts as long as they use the AvrX semantics. Stacks can anywhere in the first 64k of SRAM space. For best performance at least the kernel stack should be in on-chip-SRAM.
    bullet	AvrXSetObjectSemaphore
    bullet	AvrXIntSetObjectSemaphore
    bullet	AvrXResetObjectSemaphore
    bullet	AvrXWaitObjectSemaphore
    bullet	AvrXTestObjectSemaphore
    bullet	AvrXIntTestObjectSemaphore

System Stack:

    AvrX requires a stack large enough to handle all possible nested interrupts. Each entry into the kernel pushes 10 to 35 bytes onto the stack (the standard context and a return address), interrupt handlers may push more. AvrX API may temporarily push a couple more bytes. With GCC or assembly code AvrXStack is defined to be the top of SRAM and it is the designers job to make sure there is sufficient room between the AvrXStack and the upper limit of SRAM data.  With the IAR C compiler, the kernel stack is defined as the stack for "main()" and is set in the IAR linker script file.  Currently, in avrx 2.6, the C_Stack is not saved so kernel context C code must not use the data stack for anything.  There is no restriction on GCC other than the top level C task doesn't have a valid frame pointer.

    AvrX does not control or limit the nesting level. However, if your design requires more stack space than one context per interrupt source then the design might be broken or the processor simply too slow for the amount of work being done.

    Note, by default the AvrX Time Queue Manager keeps the interrupts enabled and can potentially re-enter itself. The timer manager will unwind keeping track of the number of ticks. Although overall, no system ticks will be lost, the precision of time delay events will suffer (jitter).  Also, Kernel stack will grow an additional 10 to 35 bytes with each nesting. On a 10mhz part a 10khz tick rate should be plenty of time, even with significant other interrupts (50% load), to prevent any re-entry and stack growth.

AvrX 2.3 specific information

    Avrx 2.3 has not been supported for some time.  It is poorly documented, but it can run three significant tasks on a processor with only 128 bytes of RAM.  See my mini-sumo "Cherry Blossom" for an example of AvrX 2.3 usage.

    Data Placement and Segment Control:

    AvrX 2.3 is written to the IAR assembler v1.3 available from www.atmel.com Code is collected in modules and assembled into libraries that are linked with the user code. Three DATA segments are used:
    RSEG 	AVRXDATA 	; Semaphores, queue, control blocks
    RSEG 	DATA 	; User data
    RSEG 	SSEG 	; Process Stacks

    AVRXDATA must all fit within the first page of SRAM. That means a limit of 160 bytes of AVRXDATA since SRAM starts at 0x60 (96). Even with this tight memory allocation one can define about 12 each, processes, timers, messages and semaphores. If you have more than this on an 8kb part, then maybe your design is too complicated.

    Register Usage:

    Any register allocated to an interrupt or global cannot be part of any process context. AvrX has no provisions for 
    restoring registers when in the kernel context. It only saves/restores for processes. Typically some amount of 
    registers need to be allocated for globals: high speed interrupt routines are a good example.

    AvrX has three flags that can be placed in registers to make the code smaller and faster. If they are #define then 
    AvrX will use the register else, it will allocate space in SRAM and use the flags there.

    #define 	_SysLevel 	R13 	; Kernel Nesting Level, -1 = Process
    #define 	_TimQLevel 	R14 	; Timer Queue Reentry Level
    #define 	_Running 	R15 	; Current running Process ID

    Macros

    Macros are supplied to simplify the task of declaring AvrX data structures and placing them in the correct segments.
     Macros are a mix of C and IAR assembler macros. One can use the C wrapper to make macros consistent, or one can use 
     the IAR macro for more flexibility.

    TASK(Start, StackSz, Priority, Context, ContextSz)

    TIMER(timer)

    MUTEX(mutex)

    Sample Code

    Please refer to the test cases for sample usage of CPU and AvrX initialization code and AvrX API usage.

AvrX 2.6 version specific information

    New API to set kernel stack: 

    void AvrXSetKernelStack(void *pStack)

    If you pass a NULL stack pointer, then AvrX will take the current SPL/SPH and make that the kernel stack.  This API 
    only makes sense as the first executable line in your applications "main()" code.  See the samples for details.

Detailed API descriptions

    Please refer to the source.  Each function as pretty complete descriptions in the header.  Sample code illustrates 
    how to declare and call routines.

Some thoughts on structuring code

    Not all interrupts need to be passed through AvrX. In fact, one of my favorite techniques is to have Timer0 interrupt 
    at a great speed, say 150k/sec perform some action (PWM and Encoder reading) and then once every 150 cycles then call 
    _IntProlog, then AvrXTimerHandler, then _Epilog. The call to _IntProlog will enable interrupts and the high speed code 
    will continue to run. Make sure you reset your counter before dropping into the AvrX code!

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -