Commit b7f4e50311a708f1d07c6add476b4f7812d25bd4
1 parent
2a3e33f7
TC:
- access to register not working - acess to rc return rb register - emulate TC usage for fast delay
Showing
1 changed file
with
62 additions
and
28 deletions
hw/at91_tc.c
... | ... | @@ -72,15 +72,23 @@ static void at91_tc_tick(void *opaque) |
72 | 72 | { |
73 | 73 | TCChannelState *s = opaque; |
74 | 74 | |
75 | - s->cv++; | |
76 | - /* TODO: Overflow check */ | |
77 | - if (s->cv == s->ra) { | |
78 | - s->sr |= SR_CPAS; | |
79 | - } | |
80 | - if (s->cv == s->rb) { | |
81 | - s->sr |= SR_CPBS; | |
82 | - } | |
83 | - if (s->cv == s->rc) { | |
75 | + if (s->mr & MR_WAVE) { | |
76 | + s->cv++; | |
77 | + /* TODO: Overflow check */ | |
78 | + if (s->cv == s->ra) { | |
79 | + s->sr |= SR_CPAS; | |
80 | + } | |
81 | + if (s->cv == s->rb) { | |
82 | + s->sr |= SR_CPBS; | |
83 | + } | |
84 | + if (s->cv == s->rc) { | |
85 | + s->sr |= SR_CPCS; | |
86 | + if (s->mr & MR_RCTRIG) { | |
87 | + s->cv = 0; | |
88 | + } | |
89 | + } | |
90 | + } else { | |
91 | + s->cv = s->rc; | |
84 | 92 | s->sr |= SR_CPCS; |
85 | 93 | if (s->mr & MR_RCTRIG) { |
86 | 94 | s->cv = 0; |
... | ... | @@ -106,7 +114,7 @@ static uint32_t at91_tc_channel_read(TCChannelState *s, |
106 | 114 | case TC_RB: |
107 | 115 | return s->rb; |
108 | 116 | case TC_RC: |
109 | - return s->rb; | |
117 | + return s->rc; | |
110 | 118 | case TC_SR: |
111 | 119 | sr = s->sr; |
112 | 120 | s->sr = 0; |
... | ... | @@ -119,6 +127,23 @@ static uint32_t at91_tc_channel_read(TCChannelState *s, |
119 | 127 | } |
120 | 128 | } |
121 | 129 | |
130 | +static int at91_tc_get_freq(uint32_t cmr) | |
131 | +{ | |
132 | + int freq; | |
133 | + | |
134 | + switch (cmr & 7) { | |
135 | + case 0: freq = at91_master_clock_frequency / 2; break; | |
136 | + case 1: freq = at91_master_clock_frequency / 8; break; | |
137 | + case 2: freq = at91_master_clock_frequency / 32; break; | |
138 | + case 3: freq = at91_master_clock_frequency / 128; break; | |
139 | + case 4: freq = at91_master_clock_frequency / 1024; break; | |
140 | + default: /* TODO: External clocks */ | |
141 | + freq = at91_master_clock_frequency / 16; | |
142 | + break; | |
143 | + } | |
144 | + return freq; | |
145 | +} | |
146 | + | |
122 | 147 | static void at91_tc_channel_write(TCChannelState *s, |
123 | 148 | target_phys_addr_t offset, uint32_t value) |
124 | 149 | { |
... | ... | @@ -127,30 +152,36 @@ static void at91_tc_channel_write(TCChannelState *s, |
127 | 152 | switch (offset) { |
128 | 153 | case TC_CCR: |
129 | 154 | if ((value & 3) == 1) { |
130 | - if (s->mr & MR_WAVE) { | |
131 | - s->cv = 0; | |
132 | - ptimer_run(s->timer, 0); | |
155 | + if (!(s->mr & MR_WAVE)) { | |
156 | + if (s->imr == 0 && s->rc != 0) { | |
157 | + freq = at91_tc_get_freq(s->mr); | |
158 | + freq /= s->rc; | |
159 | + if (freq > 1000) { | |
160 | + //just busy loop too wait something, with resolution more then 1ms | |
161 | + s->cv = s->rc; | |
162 | + s->sr |= SR_CPCS; | |
163 | + if (s->mr & MR_RCTRIG) { | |
164 | + s->cv = 0; | |
165 | + } | |
166 | + break; | |
167 | + } | |
168 | + } | |
169 | + //tick only once, this should speedup system | |
170 | + ptimer_set_limit(s->timer, s->rc, 1); | |
133 | 171 | } |
134 | - /* TODO: Counter mode */ | |
172 | + | |
173 | + s->cv = 0; | |
174 | + ptimer_run(s->timer, 0); | |
135 | 175 | } else if (value & 2) { |
136 | 176 | ptimer_stop(s->timer); |
177 | + ptimer_set_limit(s->timer, 1, 1); | |
137 | 178 | } |
138 | 179 | break; |
139 | 180 | case TC_CMR: |
140 | - if (value & MR_WAVE) { | |
141 | - switch (value & 7) { | |
142 | - case 0: freq = at91_master_clock_frequency / 2; break; | |
143 | - case 1: freq = at91_master_clock_frequency / 8; break; | |
144 | - case 2: freq = at91_master_clock_frequency / 32; break; | |
145 | - case 3: freq = at91_master_clock_frequency / 128; break; | |
146 | - case 4: freq = at91_master_clock_frequency / 1024; break; | |
147 | - default: /* TODO: External clocks */ | |
148 | - freq = at91_master_clock_frequency / 16; | |
149 | - break; | |
150 | - } | |
151 | - ptimer_set_freq(s->timer, freq); | |
152 | - } | |
153 | - /* TODO: Counter mode */ | |
181 | + freq = at91_tc_get_freq(value); | |
182 | + | |
183 | + ptimer_set_freq(s->timer, freq); | |
184 | + | |
154 | 185 | s->mr = value; |
155 | 186 | break; |
156 | 187 | case TC_RA: |
... | ... | @@ -175,6 +206,7 @@ static uint32_t at91_tc_mem_read(void *opaque, target_phys_addr_t offset) |
175 | 206 | { |
176 | 207 | TCState *s = opaque; |
177 | 208 | |
209 | + offset &= TC_SIZE - 1; | |
178 | 210 | switch (offset) { |
179 | 211 | case TC_BMR: |
180 | 212 | return 0; /* TODO */ |
... | ... | @@ -194,6 +226,8 @@ static void at91_tc_mem_write(void *opaque, target_phys_addr_t offset, |
194 | 226 | { |
195 | 227 | TCState *s = opaque; |
196 | 228 | |
229 | + offset &= TC_SIZE - 1; | |
230 | + | |
197 | 231 | switch (offset) { |
198 | 232 | case TC_BCR: |
199 | 233 | return; /* TODO */ | ... | ... |