Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
F
firmware
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Monitor
Service Desk
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
card10
firmware
Commits
77bd73ba
Commit
77bd73ba
authored
3 years ago
by
rahix
Browse files
Options
Downloads
Plain Diff
Merge 'Switch systick to 32 kHz clock source'
See merge request
!475
parents
e99885b5
e524d839
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!475
change(pycardium): Switch systick to 32 kHz clock source
Pipeline
#5255
passed
3 years ago
Stage: build
Stage: deploy
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
pycardium/mphalport.c
+53
-19
53 additions, 19 deletions
pycardium/mphalport.c
with
53 additions
and
19 deletions
pycardium/mphalport.c
+
53
−
19
View file @
77bd73ba
...
...
@@ -20,6 +20,30 @@
#include
<stdio.h>
#include
<string.h>
// Smallest interval which can be reached exactly
#define SYSTICK_INTERVAL_US 15625ULL
#define SYSTICK_FREQ_HZ (1000000 / SYSTICK_INTERVAL_US)
/*
* Copied from core_cm4.h and modified to select the
* 32768 Hz RTC crystal as the clock source */
static
uint32_t
systick_config
(
uint32_t
ticks
)
{
if
((
ticks
-
1
)
>
SysTick_LOAD_RELOAD_Msk
)
return
(
1
);
/* Reload value impossible */
SysTick
->
LOAD
=
ticks
-
1
;
/* set reload register */
NVIC_SetPriority
(
SysTick_IRQn
,
(
1
<<
__NVIC_PRIO_BITS
)
-
1
);
/* set Priority for Systick Interrupt */
SysTick
->
VAL
=
0
;
/* Load the SysTick Counter Value */
SysTick
->
CTRL
=
SysTick_CTRL_TICKINT_Msk
|
SysTick_CTRL_ENABLE_Msk
;
/* Enable SysTick IRQ and SysTick Timer */
return
(
0
);
/* Function successful */
}
/* Initialize everything for MicroPython */
void
pycardium_hal_init
(
void
)
{
...
...
@@ -33,9 +57,9 @@ void pycardium_hal_init(void)
epic_interrupt_enable
(
EPIC_INT_UART_RX
);
/*
* Configure SysTick timer for
1ms
period.
* Configure SysTick timer for
SYSTICK_INTERVAL_US
period.
*/
S
ys
T
ick_
C
onfig
(
SystemCoreClock
/
1000
);
s
ys
t
ick_
c
onfig
(
32768
/
SYSTICK_FREQ_HZ
);
}
/******************************************************************************
...
...
@@ -141,14 +165,21 @@ void SysTick_Handler(void)
*/
static
uint64_t
systick_get_us
()
{
uint32_t
val
,
count
;
uint32_t
irqsaved
=
__get_PRIMASK
();
__set_PRIMASK
(
0
);
uint64_t
counts_per_us
=
SystemCoreClock
/
1000000
;
uint64_t
us
=
systick_count
*
1000
+
(
SysTick
->
LOAD
-
SysTick
->
VAL
)
/
counts_per_us
;
/* The asynchronous/slow clocking of the systick means that
* its value can jump to 0 before the interrupt is triggered.
* Simply wait until it is not 0 and then read the count. */
do
{
__set_PRIMASK
(
0
);
val
=
SysTick
->
VAL
;
count
=
systick_count
;
__set_PRIMASK
(
irqsaved
);
}
while
(
val
==
0
);
__set_PRIMASK
(
irqsaved
);
uint64_t
us
=
count
*
SYSTICK_INTERVAL_US
+
(
SysTick
->
LOAD
-
val
)
*
1000000ULL
/
32768
;
return
us
;
}
...
...
@@ -160,14 +191,12 @@ static void systick_delay_precise(uint32_t us)
* instruction, read the current timer value to ensure as little skew as
* possible.
*
* Subtract 0.3us (constant_offset) to account for the duration of the
* calculations.
* Accuracy is about 30 us (due to the 32 kHz systick)
*/
uint32_t
count_to_overflow
=
SysTick
->
VAL
;
uint32_t
count_reload
=
SysTick
->
LOAD
;
uint32_t
clocks_per_us
=
SystemCoreClock
/
1000000
;
uint32_t
constant_offset
=
clocks_per_us
*
3
/
10
;
uint32_t
delay_count
=
us
*
clocks_per_us
-
constant_offset
;
uint32_t
delay_count
=
us
*
32768
/
1000000
;
/*
* Calculate the final count for both paths. Marked as volatile so the
...
...
@@ -203,14 +232,14 @@ static void systick_delay_sleep(uint32_t us)
while
(
1
)
{
uint64_t
now
=
systick_get_us
();
if
(
now
>
=
final_time
)
{
if
(
(
now
+
SYSTICK_INTERVAL_US
)
>
final_time
)
{
break
;
}
/*
* Sleep with WFI if more than
1ms of delay is remaining. The
* SysTick interrupt is guaranteed to
happen within any timespan
*
of 1ms
.
* Sleep with WFI if more than
SYSTICK_INTERVAL_US of delay
*
is remaining. The
SysTick interrupt is guaranteed to
*
happen within any timespan of SYSTICK_INTERVAL_US
.
*
* Use a critical section encompassing both the check and the
* WFI to prevent a race-condition where the interrupt happens
...
...
@@ -218,7 +247,7 @@ static void systick_delay_sleep(uint32_t us)
*/
uint32_t
irqsaved
=
__get_PRIMASK
();
__set_PRIMASK
(
0
);
if
((
now
+
1000
)
<
final_time
)
{
if
((
now
+
SYSTICK_INTERVAL_US
)
<
final_time
)
{
__WFI
();
}
__set_PRIMASK
(
irqsaved
);
...
...
@@ -234,6 +263,11 @@ static void systick_delay_sleep(uint32_t us)
*/
mp_handle_pending
(
true
);
}
uint64_t
now
=
systick_get_us
();
if
(
now
<
final_time
)
{
systick_delay_precise
(
final_time
-
now
);
}
}
static
void
systick_delay
(
uint32_t
us
)
...
...
@@ -243,12 +277,12 @@ static void systick_delay(uint32_t us)
/*
* For very short delays, use the systick_delay_precise() function which
* delays with a microsecond accuracy. For anything >
1ms
, use
* delays with a microsecond accuracy. For anything >
SYSTICK_INTERVAL_US
, use
* systick_delay_sleep() which puts the CPU to sleep when nothing is
* happening and also checks for MicroPython interrupts every now and
* then.
*/
if
(
us
<
1000
)
{
if
(
us
<
SYSTICK_INTERVAL_US
)
{
systick_delay_precise
(
us
);
}
else
{
systick_delay_sleep
(
us
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment