aboutsummaryrefslogtreecommitdiffstats
path: root/ports/ARM7/chcore.h
blob: eed850266257088caa859ab990c8f9ee7cc6e431 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
    ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _CHCORE_H_
#define _CHCORE_H_

typedef void *regarm;

/*
 * Interrupt saved context.
 */
struct extctx {
  regarm  spsr_irq;
  regarm  lr_irq;
  regarm  r0;
  regarm  r1;
  regarm  r2;
  regarm  r3;
  regarm  r12;
  regarm  lr_usr;
};

/*
 * System saved context.
 */
struct intctx {
  regarm  r4;
  regarm  r5;
  regarm  r6;
#ifndef CH_CURRP_REGISTER_CACHE
  regarm  r7;
#endif
  regarm  r8;
  regarm  r9;
  regarm  r10;
  regarm  r11;
  regarm  lr;
};

/*
 * Port dependent part of the Thread structure, you may add fields in
 * this structure.
 */
typedef struct {
  struct intctx *r13;
} Context;

/*
 * Platform dependent part of the \p chThdCreate() API.
 */
#define SETUP_CONTEXT(workspace, wsize, pf, arg) {                      \
  tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace +              \
                                     wsize -                            \
                                     sizeof(struct intctx));            \
  tp->p_ctx.r13->r4 = pf;                                               \
  tp->p_ctx.r13->r5 = arg;                                              \
  tp->p_ctx.r13->lr = threadstart;                                      \
}

#ifdef THUMB
#ifdef __cplusplus
extern "C" {
#endif
  void chSysLock(void);
  void chSysUnlock(void);
#ifdef __cplusplus
}
#endif
#else /* !THUMB */
#define chSysLock() asm("msr     CPSR_c, #0x9F")
#define chSysUnlock() asm("msr     CPSR_c, #0x1F")
#endif /* THUMB */

#ifdef THUMB
#define INT_REQUIRED_STACK 0x10
#else /* !THUMB */
#define INT_REQUIRED_STACK 0
#endif /* !THUMB */
#define StackAlign(n) ((((n) - 1) | 3) + 1)
#define UserStackSize(n) StackAlign(sizeof(Thread) +                    \
                                    sizeof(struct intctx) +             \
                                    sizeof(struct extctx) +             \
                                    (n) +                               \
                                    INT_REQUIRED_STACK)
#define WorkingArea(s, n) uint32_t s[UserStackSize(n) >> 2];

#ifdef THUMB
#define chSysSwitchI chSysSwitchI_thumb

#define chSysIRQEnterI() {                                              \
  asm(".code 32                                 \n\t"                   \
      "stmfd    sp!, {r0-r3, r12, lr}           \n\t"                   \
      "add      r0, pc, #1                      \n\t"                   \
      "bx       r0                              \n\t"                   \
      ".code 16                                 \n\t");                 \
}

#define chSysIRQExitI() {                                               \
  asm("ldr      r0, =IrqCommon                  \n\t"                   \
      "bx       r0                              \n\t");                 \
}
#else /* !THUMB */
#define chSysSwitchI chSysSwitchI_arm

#define chSysIRQEnterI() {                                              \
  asm("stmfd    sp!, {r0-r3, r12, lr}           \n\t");                 \
}

#define chSysIRQExitI() {                                               \
  asm("b        IrqCommon                       \n\t");                 \
}
#endif /* !THUMB */

/* It requires zero bytes, but better be safe.*/
#define IDLE_THREAD_STACK_SIZE 8

#ifdef __cplusplus
extern "C" {
#endif
  void _IdleThread(void *p) __attribute__((noreturn));
  void chSysHalt(void);
  void chSysSwitchI(Thread *otp, Thread *ntp);
  void chSysPuts(char *msg);
  void threadstart(void);
#ifdef __cplusplus
}
#endif

#endif /* _CHCORE_H_ */