Further work on Pinecil compile

This commit is contained in:
Ben V. Brown
2020-08-18 18:58:00 +10:00
parent 3560f6c5c1
commit 2becaa5eab
22 changed files with 1214 additions and 1260 deletions

View File

@@ -0,0 +1,710 @@
/*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ARM CM3 port.
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value should also ensure backward compatibility.
FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 255
#endif
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
#else
/* The way the SysTick is clocked is not modified in case it is not the same
as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 8UL )
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
#define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000UL )
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL )
/* For strict compliance with the Cortex-M spec the task start address should
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
* generate the tick interrupt.
*/
void vPortSetupTimerInterrupt( void );
/*
* Exception handlers.
*/
void xPortPendSVHandler( void ) __attribute__ (( naked ));
void xPortSysTickHandler( void );
void vPortSVCHandler( void ) __attribute__ (( naked ));
/*
* Start first task is a separate function so it can be tested in isolation.
*/
static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/*
* The number of SysTick increments that make up one tick period.
*/
#if configUSE_TICKLESS_IDLE == 1
static uint32_t ulTimerCountsForOneTick = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* The maximum number of tick periods that can be suppressed is limited by the
* 24 bit resolution of the SysTick timer.
*/
#if configUSE_TICKLESS_IDLE == 1
static uint32_t xMaximumPossibleSuppressedTicks = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
* power functionality only.
*/
#if configUSE_TICKLESS_IDLE == 1
static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
#if ( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void )
{
__asm volatile (
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" orr r14, #0xd \n"
" bx r14 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
/*-----------------------------------------------------------*/
static void prvPortStartFirstTask( void )
{
__asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc 0 \n" /* System call to start first task. */
" nop \n"
);
}
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
BaseType_t xPortStartScheduler( void )
{
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
#if( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
value. */
*pucFirstUserPriorityRegister = ulOriginalPriority;
}
#endif /* conifgASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. */
prvTaskExitError();
/* Should not get here! */
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if( uxCriticalNesting == 1 )
{
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
}
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
/*-----------------------------------------------------------*/
void xPortPendSVHandler( void )
{
/* This is a naked function. */
__asm volatile
(
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
" \n" /* Restore the context, including the critical nesting count. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n"
" isb \n"
" bx r14 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
void xPortSysTickHandler( void )
{
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known. */
portDISABLE_INTERRUPTS();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
TickType_t xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
}
/* Stop the SysTick momentarily. The time the SysTick is stopped for
is accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__asm volatile( "cpsid i" );
__asm volatile( "dsb" );
__asm volatile( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{
/* Restart from whatever is left in the count register to complete
this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__asm volatile( "cpsie i" );
}
else
{
/* Set the new reload value. */
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
xModifiableIdleTime = xExpectedIdleTime;
configPRE_SLEEP_PROCESSING( &xModifiableIdleTime );
if( xModifiableIdleTime > 0 )
{
__asm volatile( "dsb" );
__asm volatile( "wfi" );
__asm volatile( "isb" );
}
configPOST_SLEEP_PROCESSING( &xExpectedIdleTime );
/* Stop SysTick. Again, the time the SysTick is stopped for is
accounted for as best it can be, but using the tickless mode will
inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__asm volatile( "cpsie i" );
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
/* The tick interrupt has already executed, and the SysTick
count reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something
that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
}
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* The tick interrupt handler will already have pended the tick
processing in the kernel. As the pending tick will be
processed as soon as this function exits, the tick value
maintained by the tick is stepped forward by one less than the
time spent waiting. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
Work out how long the sleep lasted rounded to complete tick
periods (not the ulReload value which accounted for part
ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
}
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
value. The critical section is used to ensure the tick interrupt
can only execute once in the case that the reload register is near
zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL();
{
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
}
portEXIT_CRITICAL();
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
#if configUSE_TICKLESS_IDLE == 1
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
}
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
/*-----------------------------------------------------------*/
#if( configASSERT_DEFINED == 1 )
void vPortValidateInterruptPriority( void )
{
uint32_t ulCurrentInterrupt;
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
{
/* Look up the interrupt's priority. */
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View File

@@ -0,0 +1,284 @@
/*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html
***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?
http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.
http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.
1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
#define portYIELD() \
{ \
/* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
\
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__asm volatile( "dsb" ); \
__asm volatile( "isb" ); \
}
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
{
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
return ucReturn;
}
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
/* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/
#ifdef configASSERT
void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif
/* portNOP() is not required by this port. */
#define portNOP()
#define portINLINE __inline
#ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline))
#endif
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
{
uint32_t ulCurrentInterrupt;
BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. */
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
if( ulCurrentInterrupt == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
__asm volatile
(
" mov %0, %1 \n" \
" msr basepri, %0 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
__asm volatile
(
" mrs %0, basepri \n" \
" mov %1, %2 \n" \
" msr basepri, %1 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
);
}
/*-----------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View File

@@ -12,7 +12,8 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore;
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
#define FLAG_TIMEOUT 1000
void FRToSI2C::CpltCallback() {
void FRToSI2C::CpltCallback()
{
//TODO
}
@@ -20,28 +21,31 @@ void FRToSI2C::CpltCallback() {
*
* @param obj The I2C object
*/
int i2c_start() {
int i2c_start()
{
int timeout;
/* clear I2C_FLAG_AERR Flag */
i2c_flag_clear(I2C0, I2C_FLAG_AERR);
/* wait until I2C_FLAG_I2CBSY flag is reset */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET)
{
if ((timeout--) == 0)
{
return (int) -1;
return (int)-1;
}
}
/* ensure the i2c has been stopped */
timeout = FLAG_TIMEOUT
;
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) {
if ((timeout--) == 0) {
return (int) -1;
timeout = FLAG_TIMEOUT;
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP)
{
if ((timeout--) == 0)
{
return (int)-1;
}
}
@@ -49,30 +53,34 @@ int i2c_start() {
i2c_start_on_bus(I2C0);
/* ensure the i2c has been started successfully */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
if ((timeout--) == 0) {
return (int) -1;
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET)
{
if ((timeout--) == 0)
{
return (int)-1;
}
}
return (int) 0;
return (int)0;
}
/** Send STOP command
*
* @param obj The I2C object
*/
int i2c_stop() {
int i2c_stop()
{
/* generate a STOP condition */
i2c_stop_on_bus(I2C0);
/* wait for STOP bit reset */
int timeout = FLAG_TIMEOUT;
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) {
if ((timeout--) == 0) {
while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP))
{
if ((timeout--) == 0)
{
return -1;
}
}
@@ -86,26 +94,32 @@ int i2c_stop() {
* @param last Acknoledge
* @return The read byte
*/
int i2c_byte_read(int last) {
int i2c_byte_read(int last)
{
int timeout;
if (last) {
if (last)
{
/* disable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_DISABLE);
} else {
}
else
{
/* enable acknowledge */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}
/* wait until the byte is received */
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) {
if ((timeout--) == 0) {
while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET)
{
if ((timeout--) == 0)
{
return -1;
}
}
return (int) i2c_data_receive(I2C0);
return (int)i2c_data_receive(I2C0);
}
/** Write one byte
@@ -114,15 +128,17 @@ int i2c_byte_read(int last) {
* @param data Byte to be written
* @return 0 if NAK was received, 1 if ACK was received, 2 for timeout.
*/
int i2c_byte_write(int data) {
int i2c_byte_write(int data)
{
int timeout;
i2c_data_transmit(I2C0, data);
/* wait until the byte is transmitted */
timeout = FLAG_TIMEOUT;
while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET)
|| ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) {
if ((timeout--) == 0) {
while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET))
{
if ((timeout--) == 0)
{
return 2;
}
}
@@ -131,7 +147,8 @@ int i2c_byte_write(int data) {
}
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
uint8_t *pData, uint16_t Size) {
uint8_t *pData, uint16_t Size)
{
if (!lock())
return false;
@@ -140,13 +157,18 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
/* wait until I2C_FLAG_I2CBSY flag is reset */
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
if ((timeout--) == 0) {
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return false;
} else {
if (timeout % 5 == 0) {
}
else
{
if (timeout % 5 == 0)
{
i2c_stop();
}
}
@@ -155,10 +177,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
i2c_start_on_bus(I2C0);
/* ensure the i2c has been started successfully */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return false;
@@ -170,9 +193,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
timeout = 0;
/* wait until I2C_FLAG_ADDSEND flag is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
{
timeout++;
if (timeout > 100000) {
if (timeout > 100000)
{
i2c_stop();
unlock();
return false;
@@ -180,7 +205,8 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
}
bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR);
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR);
if (no_ack) {
if (no_ack)
{
i2c_stop();
unlock();
return false;
@@ -190,21 +216,23 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
int status = i2c_byte_write(MemAddress);
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR);
no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB);
if (status == 2 || no_ack) {
if (status == 2 || no_ack)
{
i2c_stop();
unlock();
return false;
}
//////////////////////////// //Restart into read
//////////////////////////// //Restart into read
/* generate a START condition */
i2c_start_on_bus(I2C0);
/* ensure the i2c has been started successfully */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return false;
@@ -216,9 +244,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
timeout = 0;
/* wait until I2C_FLAG_ADDSEND flag is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
{
timeout++;
if (timeout > 100000) {
if (timeout > 100000)
{
i2c_stop();
unlock();
return false;
@@ -228,13 +258,15 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
/* clear ADDSEND */
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR);
if (no_ack) {
if (no_ack)
{
i2c_stop();
unlock();
return false;
}
for (count = 0; count < Size; count++) {
pData[count] = i2c_byte_read(count == (Size - 1));
for (count = 0; count < Size; count++)
{
pData[count] = i2c_byte_read(count == (uint32_t)(Size - 1));
}
/* if not sequential write, then send stop */
@@ -243,17 +275,20 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
unlock();
return true;
}
void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) {
void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data)
{
Mem_Write(address, reg, &data, 1);
}
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg)
{
uint8_t temp = 0;
Mem_Read(add, reg, &temp, 1);
return temp;
}
void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
uint8_t *pData, uint16_t Size) {
uint8_t *pData, uint16_t Size)
{
if (!lock())
return;
@@ -261,15 +296,19 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
int timeout = 0;
/* wait until I2C_FLAG_I2CBSY flag is reset */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return;
} else {
if (timeout % 5 == 0) {
}
else
{
if (timeout % 5 == 0)
{
i2c_stop();
}
}
@@ -278,10 +317,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
i2c_start_on_bus(I2C0);
/* ensure the i2c has been started successfully */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return;
@@ -293,9 +333,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
timeout = 0;
/* wait until I2C_FLAG_ADDSEND flag is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
{
timeout++;
if (timeout > 100000) {
if (timeout > 100000)
{
i2c_stop();
unlock();
return;
@@ -305,9 +347,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
/* clear ADDSEND */
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
int status = i2c_byte_write(MemAddress);
for (count = 0; count < Size; count++) {
for (count = 0; count < Size; count++)
{
status = i2c_byte_write(pData[count]);
if (status != 1) {
if (status != 1)
{
i2c_stop();
unlock();
return;
@@ -320,7 +364,8 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
unlock();
}
void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size)
{
if (!lock())
return;
uint32_t count = 0;
@@ -328,13 +373,18 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
/* wait until I2C_FLAG_I2CBSY flag is reset */
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) {
if ((timeout--) == 0) {
while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return;
} else {
if (timeout % 5 == 0) {
}
else
{
if (timeout % 5 == 0)
{
i2c_stop();
}
}
@@ -343,10 +393,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
i2c_start_on_bus(I2C0);
/* ensure the i2c has been started successfully */
timeout = FLAG_TIMEOUT
;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) {
if ((timeout--) == 0) {
timeout = FLAG_TIMEOUT;
while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET)
{
if ((timeout--) == 0)
{
i2c_stop();
unlock();
return;
@@ -358,9 +409,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
timeout = 0;
/* wait until I2C_FLAG_ADDSEND flag is set */
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
{
timeout++;
if (timeout > 100000) {
if (timeout > 100000)
{
i2c_stop();
unlock();
return;
@@ -370,9 +423,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
/* clear ADDSEND */
i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);
for (count = 0; count < Size; count++) {
for (count = 0; count < Size; count++)
{
int status = i2c_byte_write(pData[count]);
if (status != 1) {
if (status != 1)
{
i2c_stop();
unlock();
return;
@@ -385,7 +440,8 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
unlock();
}
bool FRToSI2C::probe(uint16_t DevAddress) {
bool FRToSI2C::probe(uint16_t DevAddress)
{
if (!lock())
return false;
i2c_start();
@@ -393,14 +449,16 @@ bool FRToSI2C::probe(uint16_t DevAddress) {
i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER);
/* wait until ADDSEND bit is set */
int timeout = FLAG_TIMEOUT;
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) {
if (i2c_flag_get(I2C0, I2C_FLAG_AERR)
|| i2c_flag_get(I2C0, I2C_FLAG_BERR)) {
while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND))
{
if (i2c_flag_get(I2C0, I2C_FLAG_AERR) || i2c_flag_get(I2C0, I2C_FLAG_BERR))
{
i2c_stop();
unlock();
return false;
}
if (timeout-- == 0) {
if (timeout-- == 0)
{
i2c_stop();
unlock();
return false;
@@ -422,17 +480,20 @@ bool FRToSI2C::probe(uint16_t DevAddress) {
return !no_ack;
}
void FRToSI2C::I2C_Unstick() {
void FRToSI2C::I2C_Unstick()
{
unstick_I2C();
}
bool FRToSI2C::lock() {
bool FRToSI2C::lock()
{
if (I2CSemaphore == nullptr)
return true;
return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE;
return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE;
}
void FRToSI2C::unlock() {
void FRToSI2C::unlock()
{
if (I2CSemaphore == nullptr)
return;
xSemaphoreGive(I2CSemaphore);

View File

@@ -0,0 +1,27 @@
/*
* Model_Config.h
*
* Created on: 25 Jul 2020
* Author: Ralim
*/
#ifndef BSP_MINIWARE_MODEL_CONFIG_H_
#define BSP_MINIWARE_MODEL_CONFIG_H_
/*
* Lookup for mapping features <-> Models
*/
#if defined(MODEL_Pinecil) > 1
#error "Multiple models defined!"
#elif defined(MODEL_Pinecil) == 0
#error "No model defined!"
#endif
#ifdef MODEL_Pinecil
#define ACCEL_LIS
#define TEMP_TMP36
#define POW_QC
#define POW_PD
#endif
#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */

View File

@@ -1,3 +1,4 @@
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "portmacro.h"
@@ -6,36 +7,32 @@
#include "riscv_encoding.h"
#include "n200_timer.h"
#include "n200_eclic.h"
/* Standard Includes */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
/* Each task maintains its own interrupt status in the critical nesting variable. */
UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
#if USER_MODE_TASKS
#ifdef __riscv_flen
unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13));
unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13));
#else
unsigned long MSTATUS_INIT = (MSTATUS_MPIE);
unsigned long MSTATUS_INIT = (MSTATUS_MPIE);
#endif
#else
#ifdef __riscv_flen
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13));
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13));
#else
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE);
unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE);
#endif
#endif
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
static void prvTaskExitError(void);
/**
* @brief System Call Trap
@@ -47,52 +44,51 @@ static void prvTaskExitError( void );
*/
unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1)
{
switch(mcause&0X00000fff)
switch (mcause & 0X00000fff)
{
//on User and Machine ECALL, handler the request
case 8:
case 11:
//on User and Machine ECALL, handler the request
case 8:
case 11:
{
if (arg1 == IRQ_DISABLE)
{
if(arg1==IRQ_DISABLE)
{
//zero out mstatus.mpie
clear_csr(mstatus,MSTATUS_MPIE);
}
else if(arg1==IRQ_ENABLE)
{
//set mstatus.mpie
set_csr(mstatus,MSTATUS_MPIE);
}
else if(arg1==PORT_YIELD)
{
//always yield from machine mode
//fix up mepc on sync trap
unsigned long epc = read_csr(mepc);
vPortYield_from_ulSynchTrap(sp,epc+4);
}
else if(arg1==PORT_YIELD_TO_RA)
{
vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp))));
}
break;
//zero out mstatus.mpie
clear_csr(mstatus, MSTATUS_MPIE);
}
default:
else if (arg1 == IRQ_ENABLE)
{
/* 异常处理 */
extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp);
handle_trap(mcause,sp);
//set mstatus.mpie
set_csr(mstatus, MSTATUS_MPIE);
}
else if (arg1 == PORT_YIELD)
{
//always yield from machine mode
//fix up mepc on sync trap
unsigned long epc = read_csr(mepc);
vPortYield_from_ulSynchTrap(sp, epc + 4);
}
else if (arg1 == PORT_YIELD_TO_RA)
{
vPortYield_from_ulSynchTrap(sp, (*(unsigned long *)(sp + 1 * sizeof(sp))));
}
break;
}
default:
{
/* 异常处理 */
extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp);
handle_trap(mcause, sp);
}
}
//fix mepc and return
unsigned long epc = read_csr(mepc);
write_csr(mepc,epc+4);
write_csr(mepc, epc + 4);
return sp;
}
/*-----------------------------------------------------------*/
/**
* @brief 设置触发软中断
* @note 目的是在软中断内进行任务上下文切换
@@ -100,24 +96,22 @@ unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long
*/
void vPortSetMSIPInt(void)
{
*(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01;
*(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) |= 0x01;
__asm volatile("fence");
__asm volatile("fence.i");
}
/*-----------------------------------------------------------*/
/**
* @brief 清除软中断
*
*/
void vPortClearMSIPInt(void)
{
*(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01;
*(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01;
}
/*-----------------------------------------------------------*/
/**
* @brief 执行任务上下文切换,在portasm.S中被调用
*
@@ -125,23 +119,22 @@ void vPortClearMSIPInt(void)
* @param arg1
* @return unsigned long sp地址
*/
unsigned long taskswitch( unsigned long sp, unsigned long arg1)
unsigned long taskswitch(unsigned long sp, unsigned long arg1)
{
//always yield from machine mode
//fix up mepc on
unsigned long epc = read_csr(mepc);
vPortYield(sp,epc); //never returns
vPortYield(sp, epc); //never returns
return sp;
}
/*-----------------------------------------------------------*/
/**
* @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用
*
*/
void vDoTaskSwitchContext( void )
void vDoTaskSwitchContext(void)
{
portDISABLE_INTERRUPTS();
vTaskSwitchContext();
@@ -149,45 +142,42 @@ void vDoTaskSwitchContext( void )
}
/*-----------------------------------------------------------*/
/**
* @brief 进入临界段
*
*/
void vPortEnterCritical( void )
void vPortEnterCritical(void)
{
#if USER_MODE_TASKS
ECALL(IRQ_DISABLE);
#else
portDISABLE_INTERRUPTS();
#endif
#if USER_MODE_TASKS
ECALL(IRQ_DISABLE);
#else
portDISABLE_INTERRUPTS();
#endif
uxCriticalNesting++;
}
/*-----------------------------------------------------------*/
/**
* @brief 退出临界段
*
*/
void vPortExitCritical( void )
void vPortExitCritical(void)
{
configASSERT( uxCriticalNesting );
configASSERT(uxCriticalNesting);
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
if (uxCriticalNesting == 0)
{
#if USER_MODE_TASKS
ECALL(IRQ_ENABLE);
#else
portENABLE_INTERRUPTS();
#endif
#if USER_MODE_TASKS
ECALL(IRQ_ENABLE);
#else
portENABLE_INTERRUPTS();
#endif
}
return;
}
/*-----------------------------------------------------------*/
/**
* @brief Clear current interrupt mask and set given mask
*
@@ -195,11 +185,10 @@ void vPortExitCritical( void )
*/
void vPortClearInterruptMask(int int_mask)
{
eclic_set_mth (int_mask);
eclic_set_mth(int_mask);
}
/*-----------------------------------------------------------*/
/**
* @brief Set interrupt mask and return current interrupt enable register
*
@@ -207,15 +196,14 @@ void vPortClearInterruptMask(int int_mask)
*/
int xPortSetInterruptMask(void)
{
int int_mask=0;
int_mask=eclic_get_mth();
int int_mask = 0;
int_mask = eclic_get_mth();
portDISABLE_INTERRUPTS();
return int_mask;
}
/*-----------------------------------------------------------*/
/**
* @brief 初始化任务栈帧
*
@@ -224,30 +212,30 @@ int xPortSetInterruptMask(void)
* @param pvParameters 任务参数
* @return StackType_t* 完成初始化后的栈顶
*/
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
#ifdef __riscv_flen
pxTopOfStack -= 32; /* 浮点寄存器 */
pxTopOfStack -= 32; /* 浮点寄存器 */
#endif
pxTopOfStack--;
*pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */
*pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */
pxTopOfStack--;
*pxTopOfStack = 0x40; /* CSR_SUBM */
*pxTopOfStack = 0x40; /* CSR_SUBM */
pxTopOfStack--;
*pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */
*pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */
pxTopOfStack--;
*pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */
*pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */
pxTopOfStack -= 22;
*pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */
*pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */
pxTopOfStack -=9;
pxTopOfStack -= 9;
*pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
pxTopOfStack--;
@@ -255,25 +243,24 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
}
/*-----------------------------------------------------------*/
/**
* @brief 任务退出函数
*
*/
void prvTaskExitError( void )
void prvTaskExitError(void)
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
configASSERT(uxCriticalNesting == ~0UL);
portDISABLE_INTERRUPTS();
for( ;; );
for (;;)
;
}
/*-----------------------------------------------------------*/
/**
* @brief tick中断
* @note 由于该中断配置为向量模式则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler
@@ -281,39 +268,38 @@ void prvTaskExitError( void )
*/
void vPortSysTickHandler(void)
{
volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP);
volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP);
UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
#if CONFIG_SYSTEMVIEW_EN
#if CONFIG_SYSTEMVIEW_EN
traceISR_ENTER();
#endif
#endif
uint64_t now = *mtime;
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
*mtimecmp = now;
/* 调用freertos的tick增加接口 */
if( xTaskIncrementTick() != pdFALSE )
if (xTaskIncrementTick() != pdFALSE)
{
#if CONFIG_SYSTEMVIEW_EN
#if CONFIG_SYSTEMVIEW_EN
traceISR_EXIT_TO_SCHEDULER();
#endif
#endif
portYIELD();
}
#if CONFIG_SYSTEMVIEW_EN
#if CONFIG_SYSTEMVIEW_EN
else
{
traceISR_EXIT();
}
#endif
#endif
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
}
/*-----------------------------------------------------------*/
/**
* @brief 初始化tick
*
@@ -321,21 +307,20 @@ void vPortSysTickHandler(void)
void vPortSetupTimer(void)
{
/* 内核timer定时器使用64位的计数器来实现 */
volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME);
volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP);
volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME);
volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP);
portENTER_CRITICAL();
uint64_t now = *mtime;
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
*mtimecmp = now;
uint64_t now = *mtime;
now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ);
*mtimecmp = now;
portEXIT_CRITICAL();
eclic_set_vmode(CLIC_INT_TMR);
eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0);
eclic_irq_enable(CLIC_INT_TMR, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0);
}
/*-----------------------------------------------------------*/
/**
* @brief 初始化软中断
*
@@ -343,11 +328,10 @@ void vPortSetupTimer(void)
void vPortSetupMSIP(void)
{
eclic_set_vmode(CLIC_INT_SFT);
eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0);
eclic_irq_enable(CLIC_INT_SFT, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0);
}
/*-----------------------------------------------------------*/
/**
* @brief 调度启动前的初始化准备
*

View File

@@ -1,14 +1,13 @@
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifndef PINE_PORTMACRO_H
#define PINE_PORTMACRO_H
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include "riscv_encoding.h"
/*-----------------------------------------------------------
* Port specific definitions.
*
@@ -20,123 +19,128 @@ extern "C" {
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
#if (configUSE_16_BIT_TICKS == 1)
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#define portMAX_DELAY (TickType_t)0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Architecture specifics. */
extern void vPortYield(unsigned long,unsigned long);
extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long);
extern int xPortSetInterruptMask(void);
extern void vPortClearInterruptMask( int uxSavedStatusValue );
#define portSTACK_GROWTH (-1)
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/
/* Architecture specifics. */
extern void vPortYield(unsigned long, unsigned long);
extern void vPortYield_from_ulSynchTrap(unsigned long, unsigned long);
extern int xPortSetInterruptMask(void);
extern void vPortClearInterruptMask(int uxSavedStatusValue);
/*-----------------------------------------------------------*/
/*System Calls */
/*-----------------------------------------------------------*/
//ecall macro used to store argument in a3
#define ECALL(arg) ({ \
register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \
asm volatile ("ecall" \
: "+r" (a2) \
: \
: "memory"); \
a2; \
#define ECALL(arg) ({ \
register uintptr_t a2 asm("a2") = (uintptr_t)(arg); \
asm volatile("ecall" \
: "+r"(a2) \
: \
: "memory"); \
a2; \
})
extern void vPortSetMSIPInt(void);
extern void vPortSetMSIPInt(void);
#define port_MSIPSET_BIT vPortSetMSIPInt()
#define IRQ_DISABLE 20
#define IRQ_ENABLE 30
#define PORT_YIELD 40
#define PORT_YIELD_TO_RA 50
#define IRQ_DISABLE 20
#define IRQ_ENABLE 30
#define PORT_YIELD 40
#define PORT_YIELD_TO_RA 50
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
/* the return after the ECALL is VERY important */
//#define portYIELD() ECALL(PORT_YIELD);
#define portYIELD() port_MSIPSET_BIT;
#if CONFIG_SYSTEMVIEW_EN
#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } }
#ifdef CONFIG_SYSTEMVIEW_EN
#define portEND_SWITCHING_ISR(xSwitchRequired) \
{ \
if (xSwitchRequired != pdFALSE) \
{ \
traceISR_EXIT_TO_SCHEDULER(); \
portYIELD(); \
} \
else \
{ \
traceISR_EXIT(); \
} \
}
#else
#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD()
#define portEND_SWITCHING_ISR(xSwitchRequired) \
if (xSwitchRequired != pdFALSE) \
portYIELD()
#endif
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern void eclic_set_mth (uint8_t mth);
#define portDISABLE_INTERRUPTS() \
{ \
eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \
__asm volatile("fence"); \
__asm volatile("fence.i"); \
}
#define portENABLE_INTERRUPTS() eclic_set_mth(0)
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/* Critical section management. */
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
extern void eclic_set_mth(uint8_t mth);
#define portDISABLE_INTERRUPTS() \
{ \
eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY) | 0x1f); \
__asm volatile("fence"); \
__asm volatile("fence.i"); \
}
#define portENABLE_INTERRUPTS() eclic_set_mth(0)
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime);
#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime)
#endif
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#define portINLINE __inline
#define portINLINE __inline
#ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__(( always_inline))
#define portFORCE_INLINE inline __attribute__((always_inline))
#endif
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View File

@@ -1,176 +0,0 @@
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
/* Run in FLASH */
flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k
ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K
/* Run in RAM */
/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k
ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K
*/
}
SECTIONS
{
__stack_size = DEFINED(__stack_size) ? __stack_size : 2K;
.init :
{
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash
.ilalign :
{
. = ALIGN(4);
PROVIDE( _ilm_lma = . );
} >flash AT>flash
.ialign :
{
PROVIDE( _ilm = . );
} >flash AT>flash
.text :
{
*(.rodata .rodata.*)
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >flash AT>flash
.fini :
{
KEEP (*(SORT_NONE(.fini)))
} >flash AT>flash
. = ALIGN(4);
PROVIDE (__etext = .);
PROVIDE (_etext = .);/*0x80022c8*/
PROVIDE (etext = .);/*0x80022c8*/
PROVIDE( _eilm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >flash AT>flash
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >flash AT>flash
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >flash AT>flash
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >flash AT>flash
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >flash AT>flash
. = ALIGN(4);
PROVIDE( _eilm = . );
.lalign :
{
. = ALIGN(4);
PROVIDE( _data_lma = . );
} >flash AT>flash
.dalign :
{
. = ALIGN(4);
PROVIDE( _data = . );
} >ram AT>flash
.data :
{
*(.rdata)
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800);
*(.sdata .sdata.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
} >ram AT>flash
. = ALIGN(4);
PROVIDE( _edata = . );
PROVIDE( edata = . );
PROVIDE( _fbss = . ); /*0X200052A0 0X200002A0*/
PROVIDE( __bss_start = . );
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
} >ram AT>ram
. = ALIGN(8);
PROVIDE( _end = . ); /*0X2000,0340*/
PROVIDE( end = . );
PROVIDE( heap_start = . );
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
{
PROVIDE( heap_end = . );
. = __stack_size;
PROVIDE( _sp = . );
} >ram AT>ram
}

View File

@@ -18,14 +18,16 @@
*
*
*/
class FRToSI2C {
class FRToSI2C
{
public:
static void init() {
static void init()
{
I2CSemaphore = nullptr;
}
static void FRToSInit() {
static void FRToSInit()
{
I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer);
xSemaphoreGive(I2CSemaphore);
}
@@ -33,20 +35,22 @@ public:
static void CpltCallback(); //Normal Tx Callback
static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress,
uint8_t *pData, uint16_t Size);
uint8_t *pData, uint16_t Size);
static void Mem_Write(uint16_t DevAddress, uint16_t MemAddress,
uint8_t *pData, uint16_t Size);
uint8_t *pData, uint16_t Size);
//Returns true if device ACK's being addressed
static bool probe(uint16_t DevAddress);
static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx,
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data);
static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg);
private:
static bool lock();
static void unlock();
static void I2C_Unstick();
static SemaphoreHandle_t I2CSemaphore;
static StaticSemaphore_t xSemaphoreBuffer;

View File

@@ -10,43 +10,55 @@
#include "LIS2DH12.hpp"
#include "cmsis_os.h"
typedef struct {
typedef struct
{
const uint8_t reg;
const uint8_t value;
} LIS_REG;
static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz
{ LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off
{ LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins
{ LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on
{ LIS_CTRL_REG5, 0b00000010 }, { LIS_CTRL_REG6, 0b01100010 },
//Basically setup the unit to run, and enable 4D orientation detection
{ LIS_INT2_CFG, 0b01111110 }, //setup for movement detection
{ LIS_INT2_THS, 0x28 }, { LIS_INT2_DURATION, 64 }, {
LIS_INT1_CFG, 0b01111110 }, { LIS_INT1_THS, 0x28 }, {
LIS_INT1_DURATION, 64 } };
static const LIS_REG i2c_registers[] = {{LIS_CTRL_REG1, 0x17}, // 25Hz
{LIS_CTRL_REG2, 0b00001000}, // Highpass filter off
{LIS_CTRL_REG3, 0b01100000}, // Setup interrupt pins
{LIS_CTRL_REG4, 0b00001000}, // Block update mode off, HR on
{LIS_CTRL_REG5, 0b00000010},
{LIS_CTRL_REG6, 0b01100010},
//Basically setup the unit to run, and enable 4D orientation detection
{LIS_INT2_CFG, 0b01111110}, //setup for movement detection
{LIS_INT2_THS, 0x28},
{LIS_INT2_DURATION, 64},
{LIS_INT1_CFG, 0b01111110},
{LIS_INT1_THS, 0x28},
{LIS_INT1_DURATION, 64}};
void LIS2DH12::initalize() {
void LIS2DH12::initalize()
{
#ifdef ACCEL_LIS
for (size_t index = 0;
index < (sizeof(i2c_registers) / sizeof(i2c_registers[0]));
index++) {
index < (sizeof(i2c_registers) / sizeof(i2c_registers[0]));
index++)
{
FRToSI2C::I2C_RegisterWrite(LIS2DH_I2C_ADDRESS,
i2c_registers[index].reg, i2c_registers[index].value);
i2c_registers[index].reg, i2c_registers[index].value);
}
#endif
}
void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z)
{
#ifdef ACCEL_LIS
std::array<int16_t, 3> sensorData;
FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8,
reinterpret_cast<uint8_t*>(sensorData.begin()),
sensorData.size() * sizeof(int16_t));
reinterpret_cast<uint8_t *>(sensorData.begin()),
sensorData.size() * sizeof(int16_t));
x = sensorData[0];
y = sensorData[1];
z = sensorData[2];
#endif
}
bool LIS2DH12::detect() {
bool LIS2DH12::detect()
{
return FRToSI2C::probe(LIS2DH_I2C_ADDRESS);
}

View File

@@ -11,15 +11,18 @@
#include "LIS2DH12_defines.hpp"
#include "BSP.h"
class LIS2DH12 {
class LIS2DH12
{
public:
static bool detect();
static void initalize();
//1 = rh, 2,=lh, 8=flat
static Orientation getOrientation() {
static Orientation getOrientation()
{
#ifdef LIS_ORI_FLIP
uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,
LIS_INT2_SRC) >> 2);
LIS_INT2_SRC) >>
2);
if (val == 8)
val = 3;
else if (val == 1)
@@ -30,11 +33,13 @@ public:
val = 3;
return static_cast<Orientation>(val);
#endif
#ifdef MODEL_TS100
return static_cast<Orientation>((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1);
#ifdef ACCEL_LIS
return static_cast<Orientation>((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, LIS_INT2_SRC) >> 2) - 1);
#else
return Orientation::ORIENTATION_FLAT;
#endif
}
static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z);
static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z);
private:
};

View File

@@ -9,20 +9,19 @@
#define INC_FREERTOSHOOKS_H_
#include "FreeRTOS.h"
#include "cmsis_os.h"
#include "unit.h"
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
// RToS
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
void vApplicationIdleHook(void);
// RToS
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize);
void vApplicationIdleHook(void);
#ifdef __cplusplus
}
#endif
#endif /* INC_FREERTOSHOOKS_H_ */

View File

@@ -10,9 +10,8 @@
#ifndef SETTINGS_H_
#define SETTINGS_H_
#include <stdint.h>
#include "stm32f1xx_hal.h"
#include "unit.h"
#define SETTINGSVERSION ( 0x20 )
#define SETTINGSVERSION (0x20)
/*Change this if you change the struct below to prevent people getting \
out of sync*/
@@ -20,47 +19,48 @@
* This struct must be a multiple of 2 bytes as it is saved / restored from
* flash in uint16_t chunks
*/
typedef struct {
uint8_t version; // Used to track if a reset is needed on firmware upgrade
typedef struct
{
uint8_t version; // Used to track if a reset is needed on firmware upgrade
uint16_t SolderingTemp; // current set point for the iron
uint16_t SleepTemp; // temp to drop to in sleep
uint8_t SleepTime; // minutes timeout to sleep
uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80
uint8_t OrientationMode :2; // If true we want to invert the display for lefties
uint8_t sensitivity :4; // Sensitivity of accelerometer (5 bits)
uint8_t autoStartMode :2; // Should the unit automatically jump straight
// into soldering mode when power is applied
uint8_t ShutdownTime; // Time until unit shuts down if left alone
uint8_t boostModeEnabled :1; // Boost mode swaps BUT_A in soldering mode to
// temporary soldering temp over-ride
uint8_t coolingTempBlink :1; // Should the temperature blink on the cool
// down screen until its <50C
uint8_t detailedIDLE :1; // Detailed idle screen
uint8_t detailedSoldering :1; // Detailed soldering screens
uint16_t SolderingTemp; // current set point for the iron
uint16_t SleepTemp; // temp to drop to in sleep
uint8_t SleepTime; // minutes timeout to sleep
uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80
uint8_t OrientationMode : 2; // If true we want to invert the display for lefties
uint8_t sensitivity : 4; // Sensitivity of accelerometer (5 bits)
uint8_t autoStartMode : 2; // Should the unit automatically jump straight
// into soldering mode when power is applied
uint8_t ShutdownTime; // Time until unit shuts down if left alone
uint8_t boostModeEnabled : 1; // Boost mode swaps BUT_A in soldering mode to
// temporary soldering temp over-ride
uint8_t coolingTempBlink : 1; // Should the temperature blink on the cool
// down screen until its <50C
uint8_t detailedIDLE : 1; // Detailed idle screen
uint8_t detailedSoldering : 1; // Detailed soldering screens
#ifdef ENABLED_FAHRENHEIT_SUPPORT
uint8_t temperatureInF :1; // Should the temp be in F or C (true is F)
uint8_t temperatureInF : 1; // Should the temp be in F or C (true is F)
#endif
uint8_t descriptionScrollSpeed :1; // Description scroll speed
uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt)
uint8_t descriptionScrollSpeed : 1; // Description scroll speed
uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt)
uint16_t voltageDiv; // Voltage divisor factor
uint16_t BoostTemp; // Boost mode set point for the iron
uint16_t voltageDiv; // Voltage divisor factor
uint16_t BoostTemp; // Boost mode set point for the iron
uint16_t CalibrationOffset; // This stores the temperature offset for this tip
// in the iron.
uint8_t powerLimitEnable; // Allow toggling of power limit without changing value
uint8_t powerLimit; // Maximum power iron allowed to output
uint8_t powerLimit; // Maximum power iron allowed to output
uint16_t TipGain; // uV/C * 10, it can be used to convert tip thermocouple voltage to temperateture TipV/TipGain = TipTemp
uint8_t ReverseButtonTempChangeEnabled; // Change the plus and minus button assigment
uint16_t TempChangeLongStep; // Change the plus and minus button assigment
uint16_t TempChangeShortStep; // Change the plus and minus button assigment
uint16_t TempChangeLongStep; // Change the plus and minus button assigment
uint16_t TempChangeShortStep; // Change the plus and minus button assigment
uint32_t padding; // This is here for in case we are not an even divisor so
// that nothing gets cut off
//MUST BE LAST
uint32_t padding; // This is here for in case we are not an even divisor so
// that nothing gets cut off
//MUST BE LAST
} systemSettingsType;

View File

@@ -8,19 +8,20 @@ extern uint32_t currentTempTargetDegC;
extern bool settingsWereReset;
extern bool usb_pd_available;
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
void vApplicationStackOverflowHook(xTaskHandle *pxTask,
signed portCHAR *pcTaskName);
void vApplicationStackOverflowHook(TaskHandle_t *pxTask,
signed portCHAR *pcTaskName);
//Threads
void startGUITask(void const *argument);
void startPIDTask(void const *argument);
void startMOVTask(void const *argument);
extern TaskHandle_t pidTaskNotification;
extern uint8_t accelInit;
extern uint32_t lastMovementTime;
//Threads
void startGUITask(void const *argument);
void startPIDTask(void const *argument);
void startMOVTask(void const *argument);
extern TaskHandle_t pidTaskNotification;
extern uint8_t accelInit;
extern uint32_t lastMovementTime;
#ifdef __cplusplus
}
#endif

View File

@@ -7,7 +7,9 @@
#include "FreeRTOSHooks.h"
#include "BSP.h"
void vApplicationIdleHook(void) {
#include "cmsis_os.h"
void vApplicationIdleHook(void)
{
resetWatchdog();
}
@@ -16,19 +18,19 @@ static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
*ppxIdleTaskStackBuffer = &xIdleStack[0];
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
/* place for user code */
}
void vApplicationStackOverflowHook(xTaskHandle *pxTask,
signed portCHAR *pcTaskName) {
(void) pxTask;
(void) pcTaskName;
asm("bkpt");
// We dont have a good way to handle a stack overflow at this point in time
void vApplicationStackOverflowHook(TaskHandle_t *pxTask,
signed portCHAR *pcTaskName)
{
(void)pxTask;
(void)pcTaskName;
// We dont have a good way to handle a stack overflow at this point in time
reboot();
}

View File

@@ -20,7 +20,8 @@ TaskHandle_t pidTaskNotification = NULL;
uint32_t currentTempTargetDegC = 0; // Current temperature target in C
/* StartPIDTask function */
void startPIDTask(void const *argument __unused) {
void startPIDTask(void const *argument __unused)
{
/*
* We take the current tip temperature & evaluate the next step for the tip
* control PWM.
@@ -29,27 +30,32 @@ void startPIDTask(void const *argument __unused) {
TickType_t lastPowerPulseStart = 0;
TickType_t lastPowerPulseEnd = 0;
history<int32_t, PID_TIM_HZ> tempError = { { 0 }, 0, 0 };
history<int32_t, PID_TIM_HZ> tempError = {{0}, 0, 0};
currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will
// be over-ridden rapidly
pidTaskNotification = xTaskGetCurrentTaskHandle();
uint32_t PIDTempTarget = 0;
for (;;) {
for (;;)
{
if (ulTaskNotifyTake(pdTRUE, 2000)) {
if (ulTaskNotifyTake(pdTRUE, 2000))
{
// This is a call to block this thread until the ADC does its samples
int32_t x10WattsOut = 0;
// Do the reading here to keep the temp calculations churning along
uint32_t currentTipTempInC = TipThermoModel::getTipInC(true);
PIDTempTarget = currentTempTargetDegC;
if (PIDTempTarget) {
if (PIDTempTarget)
{
// Cap the max set point to 450C
if (PIDTempTarget > (450)) {
if (PIDTempTarget > (450))
{
//Maximum allowed output
PIDTempTarget = (450);
}
//Safety check that not aiming higher than current tip can measure
if (PIDTempTarget > TipThermoModel::getTipMaxInC()) {
if (PIDTempTarget > TipThermoModel::getTipMaxInC())
{
PIDTempTarget = TipThermoModel::getTipMaxInC();
}
// Convert the current tip to degree's C
@@ -73,7 +79,7 @@ void startPIDTask(void const *argument __unused) {
// Once we have feed-forward temp estimation we should be able to better tune this.
int32_t x10WattsNeeded = tempToX10Watts(tError);
// tempError.average());
// tempError.average());
// note that milliWattsNeeded is sometimes negative, this counters overshoot
// from I term's inertia.
x10WattsOut += x10WattsNeeded;
@@ -89,38 +95,41 @@ void startPIDTask(void const *argument __unused) {
// and counters extra power if the iron is no longer losing temp.
// basically: temp - lastTemp
// Unfortunately, our temp signal is too noisy to really help.
}
//If the user turns on the option of using an occasional pulse to keep the power bank on
if (systemSettings.KeepAwakePulse) {
if (systemSettings.KeepAwakePulse)
{
if (xTaskGetTickCount() - lastPowerPulseStart
> powerPulseRate) {
if (xTaskGetTickCount() - lastPowerPulseStart > powerPulseRate)
{
lastPowerPulseStart = xTaskGetTickCount();
lastPowerPulseEnd = lastPowerPulseStart
+ powerPulseDuration;
lastPowerPulseEnd = lastPowerPulseStart + powerPulseDuration;
}
//If current PID is less than the pulse level, check if we want to constrain to the pulse as the floor
if (x10WattsOut < systemSettings.KeepAwakePulse
&& xTaskGetTickCount() < lastPowerPulseEnd) {
if (x10WattsOut < systemSettings.KeepAwakePulse && xTaskGetTickCount() < lastPowerPulseEnd)
{
x10WattsOut = systemSettings.KeepAwakePulse;
}
}
//Secondary safety check to forcefully disable header when within ADC noise of top of ADC
if (getTipRawTemp(0) > (0x7FFF - 150)) {
if (getTipRawTemp(0) > (0x7FFF - 150))
{
x10WattsOut = 0;
}
if (systemSettings.powerLimitEnable
&& x10WattsOut > (systemSettings.powerLimit * 10)) {
if (systemSettings.powerLimitEnable && x10WattsOut > (systemSettings.powerLimit * 10))
{
setTipX10Watts(systemSettings.powerLimit * 10);
} else {
}
else
{
setTipX10Watts(x10WattsOut);
}
HAL_IWDG_Refresh(&hiwdg);
} else {
resetWatchdog();
}
else
{
//ADC interrupt timeout
setTipPWM(0);
}