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