Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRTOS/FreeRTOS-Kernel-Partner-Supported-Ports.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'GCC/AVR_AVRDx/port.c')
-rw-r--r--GCC/AVR_AVRDx/port.c277
1 files changed, 162 insertions, 115 deletions
diff --git a/GCC/AVR_AVRDx/port.c b/GCC/AVR_AVRDx/port.c
index f81af94..fd3e293 100644
--- a/GCC/AVR_AVRDx/port.c
+++ b/GCC/AVR_AVRDx/port.c
@@ -50,119 +50,6 @@ extern volatile RTOS_TCB_t * volatile pxCurrentTCB;
/*-----------------------------------------------------------*/
/*
- * Macro to save all the general purpose registers, the save the stack pointer
- * into the TCB.
- *
- * The first thing we do is save the flags then disable interrupts. This is to
- * guard our stack against having a context switch interrupt after we have already
- * pushed the registers onto the stack - causing the 32 registers to be on the
- * stack twice.
- *
- * r1 is set to zero as the compiler expects it to be thus, however some
- * of the math routines make use of R1.
- *
- * The interrupts will have been disabled during the call to portSAVE_CONTEXT()
- * so we need not worry about reading/writing to the stack pointer.
- */
-
-#define portSAVE_CONTEXT() \
- asm volatile ( "push r0 \n\t" \
- "in r0, __SREG__ \n\t" \
- "cli \n\t" \
- "push r0 \n\t" \
- "in r0, __RAMPZ__ \n\t" \
- "push r0 \n\t" \
- "push r1 \n\t" \
- "clr r1 \n\t" \
- "push r2 \n\t" \
- "push r3 \n\t" \
- "push r4 \n\t" \
- "push r5 \n\t" \
- "push r6 \n\t" \
- "push r7 \n\t" \
- "push r8 \n\t" \
- "push r9 \n\t" \
- "push r10 \n\t" \
- "push r11 \n\t" \
- "push r12 \n\t" \
- "push r13 \n\t" \
- "push r14 \n\t" \
- "push r15 \n\t" \
- "push r16 \n\t" \
- "push r17 \n\t" \
- "push r18 \n\t" \
- "push r19 \n\t" \
- "push r20 \n\t" \
- "push r21 \n\t" \
- "push r22 \n\t" \
- "push r23 \n\t" \
- "push r24 \n\t" \
- "push r25 \n\t" \
- "push r26 \n\t" \
- "push r27 \n\t" \
- "push r28 \n\t" \
- "push r29 \n\t" \
- "push r30 \n\t" \
- "push r31 \n\t" \
- "lds r26, pxCurrentTCB \n\t" \
- "lds r27, pxCurrentTCB + 1 \n\t" \
- "in r0, __SP_L__ \n\t" \
- "st x+, r0 \n\t" \
- "in r0, __SP_H__ \n\t" \
- "st x+, r0 \n\t" );
-
-/*
- * Opposite to portSAVE_CONTEXT(). Interrupts will have been disabled during
- * the context save so we can write to the stack pointer.
- */
-
-#define portRESTORE_CONTEXT() \
- asm volatile ( "lds r26, pxCurrentTCB \n\t" \
- "lds r27, pxCurrentTCB + 1 \n\t" \
- "ld r28, x+ \n\t" \
- "out __SP_L__, r28 \n\t" \
- "ld r29, x+ \n\t" \
- "out __SP_H__, r29 \n\t" \
- "pop r31 \n\t" \
- "pop r30 \n\t" \
- "pop r29 \n\t" \
- "pop r28 \n\t" \
- "pop r27 \n\t" \
- "pop r26 \n\t" \
- "pop r25 \n\t" \
- "pop r24 \n\t" \
- "pop r23 \n\t" \
- "pop r22 \n\t" \
- "pop r21 \n\t" \
- "pop r20 \n\t" \
- "pop r19 \n\t" \
- "pop r18 \n\t" \
- "pop r17 \n\t" \
- "pop r16 \n\t" \
- "pop r15 \n\t" \
- "pop r14 \n\t" \
- "pop r13 \n\t" \
- "pop r12 \n\t" \
- "pop r11 \n\t" \
- "pop r10 \n\t" \
- "pop r9 \n\t" \
- "pop r8 \n\t" \
- "pop r7 \n\t" \
- "pop r6 \n\t" \
- "pop r5 \n\t" \
- "pop r4 \n\t" \
- "pop r3 \n\t" \
- "pop r2 \n\t" \
- "pop r1 \n\t" \
- "pop r0 \n\t" \
- "out __RAMPZ__, r0 \n\t" \
- "pop r0 \n\t" \
- "out __SREG__, r0 \n\t" \
- "pop r0 \n\t" );
-
-/*-----------------------------------------------------------*/
-
-/*
* Perform hardware setup to enable ticks from timer.
*/
static void prvSetupTimerInterrupt( void );
@@ -206,8 +93,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--;
- *pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */
+#if defined(__AVR_HAVE_RAMPZ__)
+ *pxTopOfStack = (StackType_t)0x00; /* RAMPZ */
pxTopOfStack--;
+#endif
/* Now the remaining registers. The compiler expects R1 to be 0. */
*pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
@@ -310,11 +199,15 @@ void vPortYieldFromTick( void )
*/
static void prvSetupTimerInterrupt( void )
{
+ /* Configure low-power timer used in tickless mode */
+#if (configUSE_TICKLESS_IDLE == 1)
+ RTC_INIT();
+#endif
TICK_init();
}
/*-----------------------------------------------------------*/
-#if configUSE_PREEMPTION == 1
+#if (configUSE_PREEMPTION == 1)
/*
* Tick ISR for preemptive scheduler. We can use a naked attribute as
@@ -344,3 +237,157 @@ static void prvSetupTimerInterrupt( void )
xTaskIncrementTick();
}
#endif /* if configUSE_PREEMPTION == 1 */
+
+#if (configUSE_TICKLESS_IDLE == 1)
+
+volatile uint32_t RTC_OVF_Count = 0;
+
+ISR(RTC_CNT_vect)
+{
+ if (RTC.INTFLAGS & RTC_OVF_bm )
+ {
+ RTC_OVF_Count += 0x00010000;
+ RTC.INTFLAGS = (RTC_OVF_bm);
+ }
+
+ if (RTC.INTFLAGS & RTC_CMP_bm )
+ {
+ RTC.INTFLAGS = (RTC_CMP_bm);
+ //Disable compare interrupt
+ RTC.INTCTRL &= (0xFF ^ RTC_CMP_bm);
+ }
+
+}
+
+static uint32_t ulGetExternalTime(void)
+{
+ uint32_t time_rtc;
+
+ while (RTC.STATUS & RTC_CNTBUSY_bm)
+ {
+ ;
+ }
+ time_rtc = RTC.CNT;
+ time_rtc += RTC_OVF_Count;
+ return time_rtc;
+}
+
+static void vSetWakeTimeInterrupt(uint16_t xExpectedIdleTime)
+{
+ uint32_t rtc_cnt_time;
+
+ /* compute the required */
+ rtc_cnt_time = RTC_TICKS_TO_COUNTS(xExpectedIdleTime);
+ rtc_cnt_time += ulGetExternalTime();
+
+ while (RTC.STATUS & RTC_CMPBUSY_bm)
+ {
+ ;
+ }
+ RTC.CMP = (rtc_cnt_time & 0xFFFF);
+
+ //Enable compare interrupt
+ RTC.INTCTRL |= RTC_CMP_bm;
+}
+
+/* Define the function that is called by portSUPPRESS_TICKS_AND_SLEEP(). */
+__attribute__((weak)) void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime)
+{
+ eSleepModeStatus eSleepStatus;
+ uint32_t ulLowPowerTimeBeforeSleep, ulLowPowerTimeAfterSleep;
+
+ /* Read the current time from a time source that will remain operational
+ while the microcontroller is in a low power state. */
+ ulLowPowerTimeBeforeSleep = ulGetExternalTime();
+
+ /* Stop the timer that is generating the tick interrupt. */
+ TICK_TMR_STOP();
+
+ /* Enter a critical section that will not effect interrupts bringing the MCU
+ out of sleep mode. */
+ portDISABLE_INTERRUPTS();
+
+ /* Ensure it is still ok to enter the sleep mode. */
+ eSleepStatus = eTaskConfirmSleepModeStatus();
+
+ if (eSleepStatus == eAbortSleep)
+ {
+ /* A task has been moved out of the Blocked state since this macro was
+ * executed, or a context switch is being held pending. Do not enter a
+ * sleep state. Restart the tick and exit the critical section. */
+ TICK_TMR_START();
+ portENABLE_INTERRUPTS();
+ }
+ else
+ {
+ if (eSleepStatus == eNoTasksWaitingTimeout)
+ {
+ /* A user definable macro that allows application code to be inserted
+ * here. Such application code can be used to minimize power consumption
+ * further by turning off IO, peripheral clocks, the Flash, etc. */
+ configPRE_PWR_DOWN_PROCESSING();
+
+ /* There are no running state tasks and no tasks that are blocked with a
+ * time out. Assuming the application does not care if the tick time slips
+ * with respect to calendar time then enter a deep sleep that can only be
+ * woken by (in this demo case) the user button being pushed on the
+ * Curiosity Nano board. If the application does require the tick time
+ * to keep better track of the calender time then the PIT peripheral can be
+ * used to make rough adjustments. */
+ portSET_MODE_AND_SLEEP(SLEEP_MODE_PWR_DOWN);
+
+ /* A user definable macro that allows application code to be inserted
+ * here. Such application code can be used to reverse any actions taken
+ * by the configPRE_STOP_PROCESSING() */
+ configPOST_PWR_DOWN_PROCESSING();
+ }
+ else
+ {
+ /* Configure an interrupt to bring the microcontroller out of its low
+ * power state at the time the kernel next needs to execute. The
+ * interrupt must be generated from a source that remains operational
+ * when the microcontroller is in a low power state. */
+ vSetWakeTimeInterrupt(xExpectedIdleTime);
+
+ /* Allow the application to define some pre-sleep processing. This is
+ * the standard configPRE_SLEEP_PROCESSING() macro as described on the
+ * FreeRTOS.org website. */
+ configPRE_SLEEP_PROCESSING(xExpectedIdleTime);
+
+ /* Enter the low power state. */
+ portSET_MODE_AND_SLEEP(SLEEP_MODE_STANDBY);
+
+ /* Determine how long the microcontroller was actually in a low power
+ * state for, which will be less than xExpectedIdleTime if the
+ * microcontroller was brought out of low power mode by an interrupt
+ * other than that configured by the vSetWakeTimeInterrupt() call.
+ * Note that the scheduler is suspended before
+ * portSUPPRESS_TICKS_AND_SLEEP() is called, and resumed when
+ * portSUPPRESS_TICKS_AND_SLEEP() returns. Therefore no other tasks will
+ * execute until this function completes. */
+ ulLowPowerTimeAfterSleep = ulGetExternalTime();
+
+ /* Allow the application to define some post sleep processing. This is
+ * the standard configPOST_SLEEP_PROCESSING() macro, as described on the
+ * FreeRTOS.org website.
+ * It can be used to reverse the actions of configPRE_SLEEP_PROCESSING(),
+ * and in so doing, return the microcontroller back to its fully operational state */
+ configPOST_SLEEP_PROCESSING(xExpectedIdleTime);
+
+ /* Correct the kernels tick count to account for the time the
+ * microcontroller spent in its low power state. */
+ vTaskStepTick(RTC_COUNTS_TO_TICKS(ulLowPowerTimeAfterSleep - ulLowPowerTimeBeforeSleep));
+ // vTaskStepTick(xExpectedIdleTime);
+
+ }
+
+ /* Exit the critical section - it might be possible to do this immediately
+ * after the SET_MODE_AND_SLEEP calls. */
+ portENABLE_INTERRUPTS();
+
+ /* Restart the timer that is generating the tick interrupt. */
+ TICK_TMR_START();
+ }
+}
+
+#endif