source: trunk/libs/newlib/src/libgloss/or1k/include/or1k-support.h @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 17.0 KB
Line 
1/* Copyright (c) 2014 Authors
2 *
3 * Contributor Julius Baxter <julius.baxter@orsoc.se>
4 * Contributor Stefan Wallentowitz <stefan.wallentowitz@tum.de>
5 *
6 * The authors hereby grant permission to use, copy, modify, distribute,
7 * and license this software and its documentation for any purpose, provided
8 * that existing copyright notices are retained in all copies and that this
9 * notice is included verbatim in any distributions. No written agreement,
10 * license, or royalty fee is required for any of the authorized uses.
11 * Modifications to this software may be copyrighted by their authors
12 * and need not follow the licensing terms described here, provided that
13 * the new terms are clearly indicated on the first page of each file where
14 * they apply.
15 */
16
17/* -------------------------------------------------------------------------- */
18/* This program is commented throughout in a fashion suitable for processing
19with Doxygen. */
20/* -------------------------------------------------------------------------- */
21
22#include <stdint.h>
23
24#ifndef __OR1K_SUPPORT_H__
25#define __OR1K_SUPPORT_H__
26
27/*!
28* \defgroup or1k_macros OR1K macros
29* @{
30*/
31
32/*!
33* Access byte-sized memory mapped register
34*
35* Used to access a byte-sized memory mapped register. It avoids usage errors
36* when not defining register addresses volatile and handles casting correctly.
37*
38* Example for both read and write:
39*
40* \code
41* uint8_t status = REG8(IPBLOCK_STATUS_REG_ADDR);
42* REG8(IPBLOCK_ENABLE) = 1;
43* \endcode
44*
45* \param add Register address
46*/
47#define REG8(add) *((volatile unsigned char *) (add))
48
49/*!
50* Access halfword-sized memory mapped register
51*
52* Used to access a 16 byte-sized memory mapped register. It avoids usage errors
53* when not defining register addresses volatile and handles casting correctly.
54*
55* See REG8() for an example.
56*
57* \param add Register address
58*/
59#define REG16(add) *((volatile unsigned short *) (add))
60
61/*!
62* Access word-sized memory mapped register
63*
64* Used to access a word-sized memory mapped register. It avoids usage errors
65* when not defining register addresses volatile and handles casting correctly.
66*
67* See REG8() for an example.
68*
69* \param add Register address
70*/
71#define REG32(add) *((volatile unsigned long *) (add))
72/*!
73* @}
74*/
75
76/*!
77* \defgroup or1k_interrupts OR1K interrupt control
78*
79* Interrupt control function prototypes
80*
81* @{
82*/
83
84/*! Function pointer to interrupt handler functions */
85typedef void (*or1k_interrupt_handler_fptr)(void* data);
86
87/*!
88* Add interrupt handler for interrupt line
89*
90* Registers a callback function for a certain interrupt line.
91*
92* \param line Interrupt line/id to register a handler for
93* \param handler Handler to register
94* \param data Data value passed to the handler
95*/
96void or1k_interrupt_handler_add(uint32_t line,
97                or1k_interrupt_handler_fptr handler,
98                void* data);
99
100/*!
101* Enable interrupts from a given line
102*
103* Unmask the given interrupt line. It is also important to enable interrupts
104* in general, e.g., using or1k_interrupts_enable().
105*
106* \param line Interrupt line to enable
107*/
108void or1k_interrupt_enable(int line);
109
110/*!
111* Disable interrupts from a given line
112*
113* Mask given interrupt line. It can be unmasked using or1k_interrupt_enable().
114*
115* \param line Interrupt line to disable
116*/
117void or1k_interrupt_disable(int line);
118
119/*!
120* Disable interrupts
121*
122* This disables the interrupt exception. This is sufficient to disable all
123* interrupts. It does not change the mask register (which is modified using
124* or1k_interrupt_enable() and or1k_interrupt_disable()).
125*
126* The interrupt exception can be enabled using or1k_interrupts_enable().
127*
128* Finally, the status of the interrupt exception enable flag is returned by
129* this function. That allows to call this function even if interrupts are
130* already disabled. To restore the value of the interrupt exception enable
131* flag, use the or1k_interrupts_restore() function. That way you avoid to
132* accidentally enable interrupts. Example:
133*
134* \code
135* void f() {
136*   uint32_t interrupt_status = or1k_interrupts_disable();
137*   // do something
138*   or1k_interrupts_restore(status);
139* }
140* \endcode
141*
142* This code will preserve the original status of the interrupt enable flag.
143*
144* \return Interrupt exception enable flag before call
145*/
146uint32_t or1k_interrupts_disable(void);
147
148/*!
149* Enable interrupt exception
150*
151* Enable the interrupt exception. Beside the interrupt exception, it is also
152* necessary to enable the individual interrupt lines using
153* or1k_interrupt_enable().
154*
155* You should avoid using this function together with or1k_interrupts_disable()
156* to guard atomic blocks as it unconditionally enables the interrupt
157* exception (see documentation of or1k_interrupts_disable()).
158*/
159void or1k_interrupts_enable(void);
160
161/*!
162* Restore interrupt exception enable flag
163*
164* This function restores the given status to the processor.
165* or1k_interrupts_restore(0) is identical to or1k_interrupts_disable() and
166* or1k_interrupts_restore(SPR_SR_IEE) is identical to or1k_interrupts_enable().
167*
168* It is for example used to guard an atomic block and restore the original
169* status of the interrupt exception enable flag as returned by
170* or1k_interrupts_disable(). See the documentation of or1k_interrupts_disable()
171* for a usage example.
172*
173* \param status Status of the flag to restore
174*/
175void or1k_interrupts_restore(uint32_t status);
176
177/*!
178 * Disable timer and interrupt exception
179 *
180 * This function disables the timer and interrupt exception to guard critical
181 * sections. It returns the status of the enable bits before the critical
182 * section, that is restored with or1k_critical_end().
183 *
184 * Example:
185 * \code
186 * ...
187 * uint32_t status = or1k_critical_start();
188 * // critical part
189 * or1k_critical_end(status);
190 * ...
191 * \endcode
192 *
193 * \return Status of timer and interrupt exception at time of call
194 */
195uint32_t or1k_critical_begin();
196
197/*!
198 * Enable timer and interrupt exception
199 *
200 * Restore the timer and interrupt exception enable. The restore value is the
201 * return value from or1k_critical_start().
202 *
203 * \param restore Interrupt and timer exception enable restore value
204 */
205void or1k_critical_end(uint32_t restore);
206/*!
207* @}
208*/
209
210/*!
211* \defgroup or1k_exception Exception handling
212* @{
213*/
214/*! Function pointer to an exception handler function */
215typedef void (*or1k_exception_handler_fptr)(void);
216
217/*!
218* Register exception handler
219*
220* Register an exception handler for the given exception id. This handler is
221* in the following then called when the exception occurs. You can thereby
222* individually handle those exceptions.
223*
224* \param id Exception id
225* \param handler Handler callback
226*/
227void or1k_exception_handler_add(int id, or1k_exception_handler_fptr handler);
228/*!
229* @}
230*/
231
232/*!
233* \defgroup or1k_spr SPR access
234* @{
235*/
236
237/*!
238* Move value to special purpose register
239*
240* Move data value to a special purpose register
241*
242* \param spr SPR identifier, see spr-defs.h for macros
243* \param value value to move to SPR
244*/
245static inline void or1k_mtspr (uint32_t spr, uint32_t value)
246{
247        __asm__ __volatile__ ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
248}
249
250/*!
251* Copy value from special purpose register
252*
253* Copy a data value from the given special purpose register.
254*
255* \param spr SPR identifier, see spr-defs.h for macros
256* \return SPR data value
257*/
258static inline uint32_t or1k_mfspr (uint32_t spr) {
259        uint32_t value;
260        __asm__ __volatile__ ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
261        return value;
262}
263/*!
264* @}
265*/
266
267/*!
268* \defgroup or1k_util Miscellaneous utility functions
269*
270* @{
271*/
272
273/*!
274* Report value to simulator
275*
276* Uses the built-in simulator functionality.
277*
278* \param value Value to report
279*/
280void or1k_report (unsigned long int value);
281
282/*!
283* Get (pseudo) random number
284*
285* This should return pseudo-random numbers, based on a Galois LFSR.
286*
287* \return (Pseudo) Random number
288*/
289unsigned long int or1k_rand(void);
290
291/*!
292 * Register UART callback
293 *
294 * This function sets a callback function that is called when a character is
295 * received via UART. The callback function has no return and a gets the
296 * character as parameter. When a character is received, the function is called.
297 *
298 * Example (UART echo):
299 * \code
300 * void uart_in(char c) {
301 *   printf("%c", c); // Echo
302 * }
303 *
304 * int main() {
305 *   or1k_uart_set_read_cb(&uart_in);
306 *   or1k_interrupts_enable();
307 *
308 *   while (1) {}
309 * }
310 * \endcode
311 */
312void or1k_uart_set_read_cb(void (*cb)(char c));
313/*!
314* @}
315*/
316
317/*!
318* \defgroup or1k_cache Cache control
319*
320* @{
321*/
322
323/*!
324* Enable instruction cache
325*/
326void or1k_icache_enable(void);
327
328/*!
329* Disable instruction cache
330*/
331void or1k_icache_disable(void);
332
333/*!
334* Flush instruction cache
335*
336* Invalidate instruction cache entry
337*
338* \param entry Entry to invalidate
339*/
340void or1k_icache_flush(uint32_t entry);
341
342/*!
343* Enable data cache
344*/
345void or1k_dcache_enable(void);
346
347/*!
348* Disable data cache
349*/
350void or1k_dcache_disable(void);
351
352/*!
353* Flush data cache
354*
355* Invalidate data cache entry
356*
357* \param entry Entry to invalidate
358*/
359void or1k_dcache_flush(unsigned long entry);
360/*!
361* @}
362*/
363
364/*!
365* \defgroup or1k_mmu MMU control
366* @{
367*/
368
369/*!
370* Enable instruction MMU
371*/
372void or1k_immu_enable(void);
373
374/*!
375* Disable instruction MMU
376*/
377void or1k_immu_disable(void);
378
379/*!
380* Enable data MMU
381*/
382void or1k_dmmu_enable(void);
383
384/*!
385* Disable data MMU
386*/
387void or1k_dmmu_disable(void);
388/*!
389* @}
390*/
391
392/*!
393* \defgroup or1k_timer Timer control
394*
395* The tick timer can be used for time measurement, operating system scheduling
396* etc. By default it is initialized to continuously count the ticks of a
397* certain period after calling or1k_timer_init(). The period can later be
398* changed using or1k_timer_set_period().
399*
400* The timer is controlled using or1k_timer_enable(), or1k_timer_disable(),
401* or1k_timer_restore(), or1k_timer_pause(). After initialization it is required
402* to enable the timer the first time using or1k_timer_enable().
403* or1k_timer_disable() only disables the tick timer interrupts, it does not
404* disable the timer counting. If you plan to use a pair of or1k_timer_disable()
405* and or1k_timer_enable() to protect sections of your code against interrupts
406* you should use or1k_timer_disable() and or1k_timer_restore(), as it may be
407* possible that the timer interrupt was not enabled before disabling it,
408* enable would then start it unconditionally. or1k_timer_pause() pauses the
409* counting.
410*
411* In the default mode you can get the tick value using or1k_timer_get_ticks()
412* and reset this value using or1k_timer_reset_ticks().
413*
414* Example for using the default mode:
415*
416* \code
417* int main() {
418*   uint32_t ticks = 0;
419*   uint32_t timerstate;
420*   or1k_timer_init(100);
421*   or1k_timer_enable();
422*   while (1) {
423*     while (ticks == or1k_timer_get_ticks()) { }
424*     timerstate = or1k_timer_disable();
425*     // do something atomar
426*     or1k_timer_restore(timerstate);
427*     if (ticks == 100) {
428*       printf("A second elapsed\n");
429*       or1k_timer_reset_ticks();
430*       ticks = 0;
431*     }
432*   }
433* }
434* \endcode
435*
436* It is possible to change the mode of the tick timer using
437* or1k_timer_set_mode(). Allowed values are the correct bit pattern (including
438* the bit positions) for the TTMR register, it is recommended to use the macros
439* defined in spr-defs.h. For example, implementing an operating system with
440* scheduling decisions of varying duration favors the implementation of single
441* run tick timer. Here, each quantum is started before leaving the operating
442* system kernel. The counter can be restarted with or1k_timer_reset().
443* Example:
444*
445* \code
446* void tick_handler(void) {
447*   // Make schedule decision
448*   // and set new thread
449*   or1k_timer_reset();
450*   // End of exception, new thread will run
451* }
452*
453* int main() {
454*   // Configure operating system and start threads..
455*
456*   // Configure timer
457*   or1k_timer_init(50);
458*   or1k_timer_set_handler(&tick_handler);
459*   or1k_timer_set_mode(SPR_TTMR_SR);
460*   or1k_timer_enable();
461*
462*   // Schedule first thread and die..
463* }
464* \endcode
465*
466* @{
467*/
468
469/*!
470* Initialize tick timer
471*
472* This initializes the tick timer in default mode (see \ref or1k_timer for
473* details).
474*
475* \param hz Initial period of the tick timer
476* \return 0 if successful, -1 if timer not present
477*/
478int or1k_timer_init(unsigned int hz);
479
480/*!
481* Set period of timer
482*
483* Set the period of the timer to a value in Hz. The frequency from the board
484* support package is used to determine the match value.
485*/
486void or1k_timer_set_period(uint32_t hz);
487
488/*!
489* Replace the timer interrupt handler
490*
491* By default the tick timer is used to handle timer ticks. The user can replace
492* this with an own handler for example when implementing an operating system.
493*
494* \param handler The callback function pointer to the handler
495*/
496void or1k_timer_set_handler(void (*handler)(void));
497
498/*!
499* Set timer mode
500*
501* The timer has different modes (see architecture manual). The default is to
502* automatically restart counting (SPR_TTMR_RT), others are single run
503* (SPR_TTMR_SR) and continuous run (SPR_TTMR_CR).
504*
505* \param mode a valid mode (use definitions from spr-defs.h as it is important
506* that those are also at the correct position in the bit field!)
507*/
508void or1k_timer_set_mode(uint32_t mode);
509
510/*!
511* Enable timer interrupt
512*
513* Enable the timer interrupt exception, independent of the status before.
514* If you want to enable the timer conditionally, for example to implement a
515* non-interruptible sequence of code, you should use or1k_timer_restore(). See
516* the description of or1k_timer_disable() for more details.
517*
518* The enable will also restore the mode if the timer was paused previously.
519*/
520void or1k_timer_enable(void);
521
522/*!
523* Disable timer interrupt
524*
525* This disables the timer interrupt exception and returns the state of the
526* interrupt exception enable flag before the call. This can be used with
527* or1k_timer_restore() to implement sequences of code that are not allowed to
528* be interrupted. Using or1k_timer_enable() will unconditionally enable the
529* interrupt independent of the state before calling or1k_timer_disable().
530* For an example see \ref or1k_timer.
531*
532* \return Status of timer interrupt before call
533*/
534uint32_t or1k_timer_disable(void);
535
536/*!
537* Restore timer interrupt exception flag
538*
539* Restores the timer interrupt exception flag as returned by
540* or1k_timer_disable(). See the description of or1k_timer_disable() and \ref
541* or1k_timer for details and an example.
542*
543* \param sr_tee Status of timer interrupt
544*/
545void or1k_timer_restore(uint32_t sr_tee);
546
547/*!
548* Pause timer counter
549*
550* Pauses the counter of the tick timer. The counter will hold its current value
551* and it can be started again with or1k_timer_enable() which will restore the
552* configured mode.
553*/
554void or1k_timer_pause(void);
555
556/*!
557* Reset timer counter
558*/
559void or1k_timer_reset(void);
560
561/*!
562* Get timer ticks
563*
564* Get the global ticks of the default configuration. This will increment the
565* tick counter according to the preconfigured period.
566*
567* \return Current value of ticks
568*/
569unsigned long or1k_timer_get_ticks(void);
570
571/*!
572* Reset timer ticks
573*
574* Resets the timer ticks in default configuration to 0.
575*/
576void or1k_timer_reset_ticks(void);
577/*!
578* @}
579*/
580
581/*!
582 * \defgroup or1k_multicore Multicore and Synchronization Support
583 *
584 * @{
585 */
586
587/*!
588 * Compiled with multicore support
589 *
590 * \return 1 if compiled with multicore support, 0 otherwise
591 */
592uint32_t or1k_has_multicore_support(void);
593
594/*!
595 * Read core identifier
596 *
597 * \return Core identifier
598 */
599uint32_t or1k_coreid(void);
600
601/*!
602 * Read number of cores
603 *
604 * \return Total number of cores
605 */
606uint32_t or1k_numcores(void);
607
608/*!
609 * Load linked
610 *
611 * Load a value from the given address and link it. If the following
612 * or1k_sync_sc() goes to the same address and there was no conflicting access
613 * between loading and storing, the value is written back, else the write fails.
614 *
615 * \param address Address to load value from
616 * \return Value read from the address
617 */
618uint32_t or1k_sync_ll(void *address);
619
620/**
621 * Store conditional
622 *
623 * Conditionally store a value to the address. The address must have been read
624 * before using or1k_sync_ll() and there must be no other load link after that,
625 * otherwise this will always fail. In case there was no other write to the same
626 * address in between the load link and the store conditional, the store is
627 * successful, otherwise it will also fail.
628 *
629 * \param address Address to conditionally store to
630 * \param value Value to write to address
631 * \return 1 if success, 0 if fail
632 */
633int or1k_sync_sc(void *address, uint32_t value);
634
635/*!
636 * Compare and Swap
637 *
638 * Loads a data item from the memory and compares a given value to it. If the
639 * values match, a new value is written to the memory, if they mismatch, the
640 * operation is aborted. The whole operation is atomic, i.e., it is guaranteed
641 * that no other core changes the value between the read and the write.
642 *
643 * \param address Address to operate on
644 * \param compare Compare value
645 * \param swap New value to write
646 * \return The value read from memory (can be used to check for success)
647 */
648uint32_t or1k_sync_cas(void *address, uint32_t compare, uint32_t swap);
649
650/*!
651 * Test and Set Lock
652 *
653 * Check for a lock on an address. This means, if there is 0 at an address it
654 * will overwrite it with 1 and return 0. If the lock was already set (value
655 * 1 read from address), the function returns 1. The operation is atomic.
656 *
657 * \param address Address of the lock
658 * \return 0 if success, 1 if failed
659 */
660int or1k_sync_tsl(void *address);
661/*!
662 * @}
663 */
664
665#endif /* __NEWLIB_OR1K_SUPPORT_H__ */
Note: See TracBrowser for help on using the repository browser.