SAM4SD32 (SAM4S-EK2)
Loading...
Searching...
No Matches
tc.c
Go to the documentation of this file.
1
33/*
34 * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35 */
36
37#include <assert.h>
38#include "tc.h"
39
41
42#ifdef __cplusplus
43extern "C" {
44#endif
47
48#ifndef TC_WPMR_WPKEY_PASSWD
49#define TC_WPMR_WPKEY_PASSWD TC_WPMR_WPKEY((uint32_t)0x54494D)
50#endif
51
71 Tc *p_tc,
72 uint32_t ul_channel,
73 uint32_t ul_mode)
74{
75 TcChannel *tc_channel;
76
77 /* Validate inputs. */
78 Assert(p_tc);
79 Assert(ul_channel <
80 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
81 tc_channel = p_tc->TC_CHANNEL + ul_channel;
82
83 /* Disable TC clock. */
84 tc_channel->TC_CCR = TC_CCR_CLKDIS;
85
86 /* Disable interrupts. */
87 tc_channel->TC_IDR = 0xFFFFFFFF;
88
89 /* Clear status register. */
90 tc_channel->TC_SR;
91
92 /* Set mode. */
93 tc_channel->TC_CMR = ul_mode;
94}
95
104 Tc *p_tc)
105{
106 /* Validate inputs. */
107 Assert(p_tc);
108
109 p_tc->TC_BCR = TC_BCR_SYNC;
110}
111
124 Tc *p_tc,
125 uint32_t ul_blockmode)
126{
127 /* Validate inputs. */
128 Assert(p_tc);
129
130 p_tc->TC_BMR = ul_blockmode;
131}
132
133#if (!SAM3U) || defined(__DOXYGEN__)
134
148 Tc *p_tc,
149 uint32_t ul_channel,
150 uint32_t ul_steppermode)
151{
152 /* Validate inputs. */
153 Assert(p_tc);
154 Assert(ul_channel <
155 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
156
157 p_tc->TC_CHANNEL[ul_channel].TC_SMMR = ul_steppermode;
158 return 0;
159}
160
161#endif /* (!SAM3U) || defined(__DOXYGEN__) */
162
170 Tc *p_tc,
171 uint32_t ul_channel)
172{
173 /* Validate inputs. */
174 Assert(p_tc);
175 Assert(ul_channel <
176 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
177
178 p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
179}
180
188 Tc *p_tc,
189 uint32_t ul_channel)
190{
191 /* Validate inputs. */
192 Assert(p_tc);
193 Assert(ul_channel <
194 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
195
196 p_tc->TC_CHANNEL[ul_channel].TC_CCR = TC_CCR_CLKDIS;
197}
198
207uint32_t tc_read_cv(
208 Tc *p_tc,
209 uint32_t ul_channel)
210{
211 /* Validate inputs. */
212 Assert(p_tc);
213 Assert(ul_channel <
214 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
215
216 return p_tc->TC_CHANNEL[ul_channel].TC_CV;
217}
218
227uint32_t tc_read_ra(
228 Tc *p_tc,
229 uint32_t ul_channel)
230{
231 /* Validate inputs. */
232 Assert(p_tc);
233 Assert(ul_channel <
234 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
235
236 return p_tc->TC_CHANNEL[ul_channel].TC_RA;
237}
238
247uint32_t tc_read_rb(
248 Tc *p_tc,
249 uint32_t ul_channel)
250{
251 /* Validate inputs. */
252 Assert(p_tc);
253 Assert(ul_channel <
254 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
255
256 return p_tc->TC_CHANNEL[ul_channel].TC_RB;
257}
258
267uint32_t tc_read_rc(
268 Tc *p_tc,
269 uint32_t ul_channel)
270{
271 /* Validate inputs. */
272 Assert(p_tc);
273 Assert(ul_channel <
274 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
275
276 return p_tc->TC_CHANNEL[ul_channel].TC_RC;
277}
278
287 Tc *p_tc,
288 uint32_t ul_channel,
289 uint32_t ul_value)
290{
291 /* Validate inputs. */
292 Assert(p_tc);
293 Assert(ul_channel <
294 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
295
296 p_tc->TC_CHANNEL[ul_channel].TC_RA = ul_value;
297}
298
307 Tc *p_tc,
308 uint32_t ul_channel,
309 uint32_t ul_value)
310{
311 /* Validate inputs. */
312 Assert(p_tc);
313 Assert(ul_channel <
314 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
315
316 p_tc->TC_CHANNEL[ul_channel].TC_RB = ul_value;
317}
318
327 Tc *p_tc,
328 uint32_t ul_channel,
329 uint32_t ul_value)
330{
331 /* Validate inputs. */
332 Assert(p_tc);
333 Assert(ul_channel <
334 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
335
336 p_tc->TC_CHANNEL[ul_channel].TC_RC = ul_value;
337}
338
363 Tc *p_tc,
364 uint32_t ul_channel,
365 uint32_t ul_sources)
366{
367 TcChannel *tc_channel;
368
369 /* Validate inputs. */
370 Assert(p_tc);
371 Assert(ul_channel <
372 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
373 tc_channel = p_tc->TC_CHANNEL + ul_channel;
374 tc_channel->TC_IER = ul_sources;
375}
376
401 Tc *p_tc,
402 uint32_t ul_channel,
403 uint32_t ul_sources)
404{
405 TcChannel *tc_channel;
406
407 /* Validate inputs. */
408 Assert(p_tc);
409 Assert(ul_channel <
410 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
411 tc_channel = p_tc->TC_CHANNEL + ul_channel;
412 tc_channel->TC_IDR = ul_sources;
413}
414
424 Tc *p_tc,
425 uint32_t ul_channel)
426{
427 TcChannel *tc_channel;
428
429 /* Validate inputs. */
430 Assert(p_tc);
431 Assert(ul_channel <
432 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
433 tc_channel = p_tc->TC_CHANNEL + ul_channel;
434 return tc_channel->TC_IMR;
435}
436
446 Tc *p_tc,
447 uint32_t ul_channel)
448{
449 TcChannel *tc_channel;
450
451 /* Validate inputs. */
452 Assert(p_tc);
453 Assert(ul_channel <
454 (sizeof(p_tc->TC_CHANNEL) / sizeof(p_tc->TC_CHANNEL[0])));
455
456 tc_channel = p_tc->TC_CHANNEL + ul_channel;
457 return tc_channel->TC_SR;
458}
459
460/* TC divisor used to find the lowest acceptable timer frequency */
461#define TC_DIV_FACTOR 65536
462
463#if (!SAM4L) && !defined(__DOXYGEN__)
464
465#ifndef FREQ_SLOW_CLOCK_EXT
466#define FREQ_SLOW_CLOCK_EXT 32768 /* External slow clock frequency (hz) */
467#endif
468
487uint32_t tc_find_mck_divisor(
488 uint32_t ul_freq,
489 uint32_t ul_mck,
490 uint32_t *p_uldiv,
491 uint32_t *p_ultcclks,
492 uint32_t ul_boardmck)
493{
494 const uint32_t divisors[5] = { 2, 8, 32, 128,
495 ul_boardmck / FREQ_SLOW_CLOCK_EXT };
496 uint32_t ul_index;
497 uint32_t ul_high, ul_low;
498
499 /* Satisfy frequency bound. */
500 for (ul_index = 0;
501 ul_index < (sizeof(divisors) / sizeof(divisors[0]));
502 ul_index++) {
503 ul_high = ul_mck / divisors[ul_index];
504 ul_low = ul_high / TC_DIV_FACTOR;
505 if (ul_freq > ul_high) {
506 return 0;
507 } else if (ul_freq >= ul_low) {
508 break;
509 }
510 }
511 if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
512 return 0;
513 }
514
515 /* Store results. */
516 if (p_uldiv) {
517 *p_uldiv = divisors[ul_index];
518 }
519
520 if (p_ultcclks) {
521 *p_ultcclks = ul_index;
522 }
523
524 return 1;
525}
526
527#endif /* (!SAM4L) */
528
529#if (SAM4L) || defined(__DOXYGEN__)
554 uint32_t ul_freq,
555 uint32_t ul_mck,
556 uint32_t *p_uldiv,
557 uint32_t *p_ultcclks,
558 uint32_t ul_boardmck)
559{
560 const uint32_t divisors[5] = { 0, 2, 8, 32, 128};
561 uint32_t ul_index;
562 uint32_t ul_high, ul_low;
563
564 UNUSED(ul_boardmck);
565
566 /* Satisfy frequency bound. */
567 for (ul_index = 1;
568 ul_index < (sizeof(divisors) / sizeof(divisors[0]));
569 ul_index++) {
570 ul_high = ul_mck / divisors[ul_index];
571 ul_low = ul_high / TC_DIV_FACTOR;
572 if (ul_freq > ul_high) {
573 return 0;
574 } else if (ul_freq >= ul_low) {
575 break;
576 }
577 }
578 if (ul_index >= (sizeof(divisors) / sizeof(divisors[0]))) {
579 return 0;
580 }
581
582 /* Store results. */
583 if (p_uldiv) {
584 *p_uldiv = divisors[ul_index];
585 }
586
587 if (p_ultcclks) {
588 *p_ultcclks = ul_index;
589 }
590
591 return 1;
592}
593
594#endif /* (SAM4L) || defined(__DOXYGEN__) */
595
596#if (!SAM4L && !SAMG) || defined(__DOXYGEN__)
597
618 Tc *p_tc,
619 uint32_t ul_sources)
620{
621 /* Validate inputs. */
622 Assert(p_tc);
623
624 p_tc->TC_QIER = ul_sources;
625}
626
647 Tc *p_tc,
648 uint32_t ul_sources)
649{
650 /* Validate inputs. */
651 Assert(p_tc);
652
653 p_tc->TC_QIDR = ul_sources;
654}
655
666 Tc *p_tc)
667{
668 /* Validate inputs. */
669 Assert(p_tc);
670
671 return p_tc->TC_QIMR;
672}
673
684 Tc *p_tc)
685{
686 /* Validate inputs. */
687 Assert(p_tc);
688
689 return p_tc->TC_QISR;
690}
691
692#endif /* (!SAM4L && !SAMG) || defined(__DOXYGEN__) */
693
694#if (!SAM3U) || defined(__DOXYGEN__)
695
705 Tc *p_tc,
706 uint32_t ul_enable)
707{
708 /* Validate inputs. */
709 Assert(p_tc);
710
711 if (ul_enable) {
713 } else {
715 }
716}
717
718#endif /* (!SAM3U) || defined(__DOXYGEN__) */
719
720#if SAM4L || defined(__DOXYGEN__)
721
732 Tc *p_tc)
733{
734 /* Validate inputs. */
735 Assert(p_tc);
736
737 return p_tc->TC_FEATURES;
738}
739
750 Tc *p_tc)
751{
752 /* Validate inputs. */
753 Assert(p_tc);
754
755 return p_tc->TC_VERSION;
756}
757
758#endif /* SAM4L || defined(__DOXYGEN__) */
759
761
762#ifdef __cplusplus
763}
764#endif
#define TC_BCR_SYNC
(TC_BCR) Synchro Command
#define TC_CCR_SWTRG
(TC_CCR) Software Trigger Command
#define TC_WPMR_WPEN
(TC_WPMR) Write Protect Enable
#define TC_CCR_CLKEN
(TC_CCR) Counter Clock Enable Command
#define TC_CCR_CLKDIS
(TC_CCR) Counter Clock Disable Command
uint32_t tc_get_qdec_interrupt_status(Tc *p_tc)
Get current TC QDEC interrupt status.
Definition tc.c:683
uint32_t tc_get_interrupt_mask(Tc *p_tc, uint32_t ul_channel)
Read the TC interrupt mask for the specified channel.
Definition tc.c:423
void tc_enable_interrupt(Tc *p_tc, uint32_t ul_channel, uint32_t ul_sources)
Enable the TC interrupts on the specified channel.
Definition tc.c:362
uint32_t tc_read_rb(Tc *p_tc, uint32_t ul_channel)
Read TC Register B (RB) on the specified channel.
Definition tc.c:247
void tc_write_rb(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register B (RB) on the specified channel.
Definition tc.c:306
uint32_t tc_read_rc(Tc *p_tc, uint32_t ul_channel)
Read TC Register C (RC) on the specified channel.
Definition tc.c:267
void tc_init(Tc *p_tc, uint32_t ul_channel, uint32_t ul_mode)
Configure TC for timer, waveform generation, or capture.
Definition tc.c:70
void tc_set_block_mode(Tc *p_tc, uint32_t ul_blockmode)
Configure the TC Block mode.
Definition tc.c:123
void tc_write_rc(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register C (RC) on the selected channel.
Definition tc.c:326
uint32_t tc_find_mck_divisor(uint32_t ul_freq, uint32_t ul_mck, uint32_t *p_uldiv, uint32_t *p_ultcclks, uint32_t ul_boardmck)
Find the best PBA/MCK divisor.
Definition tc.c:553
uint32_t tc_get_qdec_interrupt_mask(Tc *p_tc)
Read TC QDEC interrupt mask.
Definition tc.c:665
void tc_start(Tc *p_tc, uint32_t ul_channel)
Start the TC clock on the specified channel.
Definition tc.c:169
void tc_disable_interrupt(Tc *p_tc, uint32_t ul_channel, uint32_t ul_sources)
Disable TC interrupts on the specified channel.
Definition tc.c:400
void tc_disable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
Disable TC QDEC interrupts.
Definition tc.c:646
void tc_write_ra(Tc *p_tc, uint32_t ul_channel, uint32_t ul_value)
Write to TC Register A (RA) on the specified channel.
Definition tc.c:286
void tc_enable_qdec_interrupt(Tc *p_tc, uint32_t ul_sources)
Enable TC QDEC interrupts.
Definition tc.c:617
void tc_sync_trigger(Tc *p_tc)
Asserts a SYNC signal to generate a software trigger on all channels.
Definition tc.c:103
uint32_t tc_get_feature(Tc *p_tc)
Indicate TC features.
Definition tc.c:731
void tc_set_writeprotect(Tc *p_tc, uint32_t ul_enable)
Enable or disable write protection of TC registers.
Definition tc.c:704
void tc_stop(Tc *p_tc, uint32_t ul_channel)
Stop the TC clock on the specified channel.
Definition tc.c:187
uint32_t tc_get_version(Tc *p_tc)
Indicate TC version.
Definition tc.c:749
uint32_t tc_init_2bit_gray(Tc *p_tc, uint32_t ul_channel, uint32_t ul_steppermode)
Configure TC for 2-bit Gray Counter for Stepper Motor.
Definition tc.c:147
uint32_t tc_get_status(Tc *p_tc, uint32_t ul_channel)
Get the current status for the specified TC channel.
Definition tc.c:445
uint32_t tc_read_ra(Tc *p_tc, uint32_t ul_channel)
Read TC Register A (RA) on the specified channel.
Definition tc.c:227
uint32_t tc_read_cv(Tc *p_tc, uint32_t ul_channel)
Read the counter value on the specified channel.
Definition tc.c:207
#define FREQ_SLOW_CLOCK_EXT
Definition pio.c:58
TcChannel hardware registers.
__O uint32_t TC_IER
(TcChannel Offset: 0x24) Interrupt Enable Register
__IO uint32_t TC_RA
(TcChannel Offset: 0x14) Register A
__IO uint32_t TC_RB
(TcChannel Offset: 0x18) Register B
__IO uint32_t TC_SMMR
(TcChannel Offset: 0x8) Stepper Motor Mode Register
__I uint32_t TC_SR
(TcChannel Offset: 0x20) Status Register
__IO uint32_t TC_RC
(TcChannel Offset: 0x1C) Register C
__O uint32_t TC_IDR
(TcChannel Offset: 0x28) Interrupt Disable Register
__O uint32_t TC_CCR
(TcChannel Offset: 0x0) Channel Control Register
__I uint32_t TC_IMR
(TcChannel Offset: 0x2C) Interrupt Mask Register
__IO uint32_t TC_CMR
(TcChannel Offset: 0x4) Channel Mode Register
__I uint32_t TC_CV
(TcChannel Offset: 0x10) Counter Value
__O uint32_t TC_QIDR
(Tc Offset: 0xCC) QDEC Interrupt Disable Register
__IO uint32_t TC_BMR
(Tc Offset: 0xC4) Block Mode Register
__I uint32_t TC_QIMR
(Tc Offset: 0xD0) QDEC Interrupt Mask Register
TcChannel TC_CHANNEL[TCCHANNEL_NUMBER]
(Tc Offset: 0x0) channel = 0 .
__IO uint32_t TC_WPMR
(Tc Offset: 0xE4) Write Protect Mode Register
__O uint32_t TC_BCR
(Tc Offset: 0xC0) Block Control Register
__O uint32_t TC_QIER
(Tc Offset: 0xC8) QDEC Interrupt Enable Register
__I uint32_t TC_QISR
(Tc Offset: 0xD4) QDEC Interrupt Status Register
#define TC_DIV_FACTOR
Definition tc.c:461
#define TC_WPMR_WPKEY_PASSWD
Definition tc.c:49
SAM Timer Counter (TC) driver.