00001
00055 #include "stepper_at91.h"
00056
00057 #include "cfg/cfg_stepper.h"
00058 #include <cfg/macros.h>
00059 #include <cfg/debug.h>
00060
00061 #include <cpu/types.h>
00062 #include <cpu/irq.h>
00063
00064 #include <io/arm.h>
00065
00066
00067
00068
00069
00070
00071 #define STEPPER_DELAY_ON_COMPARE_C 20
00072
00073
00074
00075
00076 static ISR_PROTO(stepper_tc0_irq);
00077 static ISR_PROTO(stepper_tc1_irq);
00078 static ISR_PROTO(stepper_tc2_irq);
00079
00081 static struct TimerCounter stepper_timers[CONFIG_TC_STEPPER_MAX_NUM] =
00082 {
00083 {
00084 .timer_id = TC0_ID,
00085 .blk_ctrl_set = TC_NONEXC0,
00086 .chl_mode_reg = &TC0_CMR,
00087 .chl_ctrl_reg = &TC0_CCR,
00088 .comp_effect_mask = TC_ACPA_MASK,
00089 .comp_effect_set = TC_ACPA_SET_OUTPUT,
00090 .comp_effect_clear = TC_ACPA_CLEAR_OUTPUT,
00091 .comp_effect_c_mask = TC_ACPC_MASK,
00092 .comp_effect_c_clear = TC_ACPC_CLEAR_OUTPUT,
00093 .ext_event_set = TC_EEVT_XC0,
00094 .comp_reg = &TC0_RA,
00095 .comp_c_reg = &TC0_RC,
00096 .count_val_reg = &TC0_CV,
00097 .irq_enable_reg = &TC0_IER,
00098 .irq_disable_reg = &TC0_IDR,
00099 .irq_set_mask = BV(TC_CPAS),
00100 .irq_mask_reg = &TC0_IMR,
00101 .isr = stepper_tc0_irq,
00102 .status_reg = &TC0_SR,
00103 .tio_pin = TIOA0,
00104 .callback = NULL,
00105 .motor = NULL,
00106 },
00107 {
00108 .timer_id = TC0_ID,
00109 .blk_ctrl_set = TC_NONEXC0,
00110 .chl_mode_reg = &TC0_CMR,
00111 .chl_ctrl_reg = &TC0_CCR,
00112 .comp_reg = &TC0_RB,
00113 .comp_c_reg = &TC0_RC,
00114 .count_val_reg = &TC0_CV,
00115 .comp_effect_mask = TC_BCPB_MASK,
00116 .comp_effect_set = TC_BCPB_SET_OUTPUT,
00117 .comp_effect_clear = TC_BCPB_CLEAR_OUTPUT,
00118 .comp_effect_c_mask = TC_BCPC_MASK,
00119 .comp_effect_c_clear = TC_BCPC_CLEAR_OUTPUT,
00120 .ext_event_set = TC_EEVT_XC0,
00121 .irq_enable_reg = &TC0_IER,
00122 .irq_disable_reg = &TC0_IDR,
00123 .irq_set_mask = BV(TC_CPBS),
00124 .irq_mask_reg = &TC0_IMR,
00125 .isr = stepper_tc0_irq,
00126 .status_reg = &TC0_SR,
00127 .tio_pin = TIOB0,
00128 .callback = NULL,
00129 .motor = NULL,
00130 },
00131 {
00132 .timer_id = TC1_ID,
00133 .blk_ctrl_set = TC_NONEXC1,
00134 .chl_mode_reg = &TC1_CMR,
00135 .chl_ctrl_reg = &TC1_CCR,
00136 .comp_reg = &TC1_RA,
00137 .comp_c_reg = &TC1_RC,
00138 .count_val_reg = &TC1_CV,
00139 .comp_effect_mask = TC_ACPA_MASK,
00140 .comp_effect_set = TC_ACPA_SET_OUTPUT,
00141 .comp_effect_clear = TC_ACPA_CLEAR_OUTPUT,
00142 .comp_effect_c_mask = TC_ACPC_MASK,
00143 .comp_effect_c_clear = TC_ACPC_CLEAR_OUTPUT,
00144 .ext_event_set = TC_EEVT_XC1,
00145 .irq_enable_reg = &TC1_IER,
00146 .irq_disable_reg = &TC1_IDR,
00147 .irq_set_mask = BV(TC_CPAS),
00148 .irq_mask_reg = &TC1_IMR,
00149 .isr = stepper_tc1_irq,
00150 .status_reg = &TC1_SR,
00151 .tio_pin = TIOA1,
00152 .callback = NULL,
00153 .motor = NULL,
00154 },
00155 {
00156 .timer_id = TC1_ID,
00157 .blk_ctrl_set = TC_NONEXC1,
00158 .chl_mode_reg = &TC1_CMR,
00159 .chl_ctrl_reg = &TC1_CCR,
00160 .comp_reg = &TC1_RB,
00161 .comp_c_reg = &TC1_RC,
00162 .count_val_reg = &TC1_CV,
00163 .comp_effect_mask = TC_BCPB_MASK,
00164 .comp_effect_set = TC_BCPB_SET_OUTPUT,
00165 .comp_effect_clear = TC_BCPB_CLEAR_OUTPUT,
00166 .comp_effect_c_mask = TC_BCPC_MASK,
00167 .comp_effect_c_clear = TC_BCPC_CLEAR_OUTPUT,
00168 .ext_event_set = TC_EEVT_XC1,
00169 .irq_enable_reg = &TC1_IER,
00170 .irq_disable_reg = &TC1_IDR,
00171 .irq_set_mask = BV(TC_CPBS),
00172 .irq_mask_reg = &TC1_IMR,
00173 .isr = stepper_tc1_irq,
00174 .status_reg = &TC1_SR,
00175 .tio_pin = TIOB1,
00176 .callback = NULL,
00177 .motor = NULL,
00178 },
00179 {
00180 .timer_id = TC2_ID,
00181 .blk_ctrl_set = TC_NONEXC2,
00182 .chl_mode_reg = &TC2_CMR,
00183 .chl_ctrl_reg = &TC2_CCR,
00184 .comp_reg = &TC2_RA,
00185 .comp_c_reg = &TC2_RC,
00186 .count_val_reg = &TC2_CV,
00187 .comp_effect_mask = TC_ACPA_MASK,
00188 .comp_effect_set = TC_ACPA_SET_OUTPUT,
00189 .comp_effect_clear = TC_ACPA_CLEAR_OUTPUT,
00190 .comp_effect_c_mask = TC_ACPC_MASK,
00191 .comp_effect_c_clear = TC_ACPC_CLEAR_OUTPUT,
00192 .ext_event_set = TC_EEVT_XC2,
00193 .irq_enable_reg = &TC2_IER,
00194 .irq_disable_reg = &TC2_IDR,
00195 .irq_set_mask = BV(TC_CPAS),
00196 .irq_mask_reg = &TC2_IMR,
00197 .isr = stepper_tc2_irq,
00198 .status_reg = &TC2_SR,
00199 .tio_pin = TIOA2,
00200 .callback = NULL,
00201 .motor = NULL,
00202 },
00203 {
00204 .timer_id = TC2_ID,
00205 .blk_ctrl_set = TC_NONEXC2,
00206 .chl_mode_reg = &TC2_CMR,
00207 .chl_ctrl_reg = &TC2_CCR,
00208 .comp_reg = &TC2_RB,
00209 .comp_c_reg = &TC2_RC,
00210 .count_val_reg = &TC2_CV,
00211 .comp_effect_mask = TC_BCPB_MASK,
00212 .comp_effect_set = TC_BCPB_SET_OUTPUT,
00213 .comp_effect_clear = TC_BCPB_CLEAR_OUTPUT,
00214 .comp_effect_c_mask = TC_BCPC_MASK,
00215 .comp_effect_c_clear = TC_BCPC_CLEAR_OUTPUT,
00216 .ext_event_set = TC_EEVT_XC2,
00217 .irq_enable_reg = &TC2_IER,
00218 .irq_disable_reg = &TC2_IDR,
00219 .irq_set_mask = BV(TC_CPBS),
00220 .irq_mask_reg = &TC2_IMR,
00221 .isr = stepper_tc2_irq,
00222 .status_reg = &TC2_SR,
00223 .tio_pin = TIOB2,
00224 .callback = NULL,
00225 .motor = NULL,
00226 }
00227 };
00228
00232 INLINE void stepper_tc_tio_irq(struct TimerCounter * t)
00233 {
00234
00235 *t->chl_mode_reg &= ~t->comp_effect_c_mask;
00236 *t->chl_mode_reg |= t->comp_effect_c_clear;
00237
00238
00239
00240
00241
00242
00243 *t->comp_c_reg = *t->count_val_reg + STEPPER_DELAY_ON_COMPARE_C;
00244
00245
00246 t->callback(t->motor);
00247
00248 *t->chl_mode_reg &= ~t->comp_effect_c_mask;
00249 }
00250
00251
00252
00253
00254
00255 DECLARE_ISR(stepper_tc0_irq)
00256 {
00257
00258
00259
00260
00261
00262
00263 uint32_t status_reg = TC0_SR & TC0_IMR;
00264
00265 if (status_reg & BV(TC_CPAS))
00266 stepper_tc_tio_irq(&stepper_timers[TC_TIOA0]);
00267
00268 if (status_reg & BV(TC_CPBS))
00269 stepper_tc_tio_irq(&stepper_timers[TC_TIOB0]);
00270
00271
00272 AIC_EOICR = 0;
00273
00274 }
00275
00276
00277
00278
00279 DECLARE_ISR(stepper_tc1_irq)
00280 {
00281
00282
00283
00284
00285
00286
00287 uint32_t status_reg = TC1_SR & TC1_IMR;
00288
00289 if (status_reg & BV(TC_CPAS))
00290 stepper_tc_tio_irq(&stepper_timers[TC_TIOA1]);
00291
00292 if (status_reg & BV(TC_CPBS))
00293 stepper_tc_tio_irq(&stepper_timers[TC_TIOB1]);
00294
00295
00296
00297 AIC_EOICR = 0;
00298 }
00299
00300
00301
00302
00303
00304 DECLARE_ISR(stepper_tc2_irq)
00305 {
00306
00307
00308
00309
00310
00311
00312
00313 uint32_t status_reg = TC2_SR & TC2_IMR;
00314
00315 if (status_reg & BV(TC_CPAS))
00316 stepper_tc_tio_irq(&stepper_timers[TC_TIOA2]);
00317
00318 if (status_reg & BV(TC_CPBS))
00319 stepper_tc_tio_irq(&stepper_timers[TC_TIOB2]);
00320
00321
00322 AIC_EOICR = 0;
00323
00324 }
00325
00332 void stepper_tc_setup(int index, stepper_isr_t callback, struct Stepper *motor)
00333 {
00334 ASSERT(index < CONFIG_TC_STEPPER_MAX_NUM);
00335
00336 motor->timer = &stepper_timers[index];
00337
00338
00339 TIO_PIO_PDR = BV(motor->timer->tio_pin);
00340 TIO_PIO_ABSR = BV(motor->timer->tio_pin);
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 *motor->timer->chl_mode_reg = BV(TC_WAVE);
00352 *motor->timer->chl_mode_reg |= motor->timer->ext_event_set;
00353 *motor->timer->chl_mode_reg &= ~TC_WAVSEL_MASK;
00354 *motor->timer->chl_mode_reg |= TC_WAVSEL_UP;
00355 *motor->timer->chl_mode_reg |= STEPPER_MCK_PRESCALER;
00356 *motor->timer->chl_mode_reg |= motor->timer->comp_effect_clear;
00357 *motor->timer->chl_mode_reg &= ~motor->timer->comp_effect_c_mask;
00358
00359
00360 *motor->timer->comp_reg = 0;
00361 *motor->timer->comp_c_reg = 0;
00362
00363
00364 cpu_flags_t flags;
00365 IRQ_SAVE_DISABLE(flags);
00366
00367
00368
00369
00370
00371
00372
00373
00374 AIC_SVR(motor->timer->timer_id) = motor->timer->isr;
00375 AIC_SMR(motor->timer->timer_id) = AIC_SRCTYPE_INT_LEVEL_SENSITIVE;
00376 AIC_IECR = BV(motor->timer->timer_id);
00377
00378
00379 stepper_tc_irq_disable(motor->timer);
00380
00381 IRQ_RESTORE(flags);
00382
00383
00384 motor->timer->callback = callback;
00385 motor->timer->motor = motor;
00386 }
00387
00391 void stepper_tc_init(void)
00392 {
00393 STEPPER_STROBE_INIT;
00394
00395 ASSERT(CONFIG_NUM_STEPPER_MOTORS <= CONFIG_TC_STEPPER_MAX_NUM);
00396
00397
00398
00399
00400
00401
00402
00403 for (int i = 0; i < CONFIG_TC_STEPPER_MAX_NUM; i++)
00404 {
00405 PMC_PCER = BV(stepper_timers[i].timer_id);
00406 *stepper_timers[i].irq_disable_reg = 0xFFFFFFFF;
00407 TC_BMR = stepper_timers[i].blk_ctrl_set;
00408 }
00409
00410
00411
00412
00413 for (int i = 0; i < CONFIG_TC_STEPPER_MAX_NUM; i++)
00414 *stepper_timers[i].chl_ctrl_reg = (BV(TC_CLKEN) | BV(TC_SWTRG));
00415
00416 }
00417