207 lines
5.0 KiB
C
207 lines
5.0 KiB
C
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "gd32f107c_eval.h"
|
|
#include "gd32f10x_gpio.h"
|
|
#include "stdio.h"
|
|
#define BUTTON_USER GPIO_PIN_14
|
|
#define LED2_USER_PORT GPIOC
|
|
#define LED5_TICK_PORT GPIOE
|
|
#define LED2_USER GPIO_PIN_0
|
|
#define LED5_TICK GPIO_PIN_1
|
|
#define TASK_HELLO_WORLD_DELAY 500
|
|
#define TASK_TOGGLE_LED_DELAY 125
|
|
void vTaskHelloWorld( void *pvParameters);
|
|
void vTaskToggleLed( void *pvParameters);
|
|
int stdout_putchar (int ch);
|
|
int stdin_getchar (void);
|
|
void DelayMS(unsigned char ms);
|
|
|
|
int stdout_putchar (int ch)
|
|
{
|
|
usart_data_transmit(EVAL_COM1, (uint16_t)ch);
|
|
while (!usart_flag_get(EVAL_COM1, USART_FLAG_TBE)){}
|
|
|
|
return ch;
|
|
}
|
|
int stdin_getchar (void)
|
|
{
|
|
return usart_data_receive(EVAL_COM1);
|
|
}
|
|
|
|
/**! \brief vInitMCU
|
|
* Initial MCU configuration
|
|
*/
|
|
static void vInitMCU(void)
|
|
{
|
|
SystemInit();
|
|
//gd_eval_led_init(LED2);
|
|
//gd_eval_led_on(LED2);
|
|
rcu_periph_clock_enable(RCU_GPIOC);
|
|
|
|
gpio_init(LED2_USER_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED2_USER);
|
|
gpio_bit_set(LED2_USER_PORT, LED2_USER);
|
|
|
|
rcu_periph_clock_enable(RCU_GPIOE);
|
|
gpio_init(LED5_TICK_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED5_TICK);
|
|
gpio_bit_set(LED5_TICK_PORT, LED5_TICK);
|
|
|
|
gd_eval_com_init(EVAL_COM1);
|
|
rcu_periph_clock_enable(RCU_GPIOB);
|
|
gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, BUTTON_USER);
|
|
}
|
|
|
|
/**! \brief vTaskHelloWorld procedure
|
|
*
|
|
* \param Not Used.
|
|
*/
|
|
void vTaskHelloWorld( void *pvParameters)
|
|
{
|
|
char ButtonState = 0;
|
|
for( ;; )
|
|
{
|
|
ButtonState = !gpio_input_bit_get(GPIOB, BUTTON_USER);
|
|
if (ButtonState)
|
|
{
|
|
printf("Hello world\n");
|
|
vTaskDelay(TASK_HELLO_WORLD_DELAY);
|
|
}
|
|
}
|
|
}
|
|
/**! \brief vTaskToggleLed procedure
|
|
*
|
|
* \param Not Used.
|
|
*/
|
|
void vTaskToggleLed( void *pvParameters)
|
|
{
|
|
char toggle = 1;
|
|
for( ;; )
|
|
{
|
|
if (toggle)
|
|
{
|
|
gpio_bit_reset(LED2_USER_PORT, LED2_USER);
|
|
}
|
|
else
|
|
{
|
|
gpio_bit_set(LED2_USER_PORT, LED2_USER);
|
|
}
|
|
toggle = !toggle;
|
|
vTaskDelay(TASK_TOGGLE_LED_DELAY);
|
|
}
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
vInitMCU();
|
|
xTaskCreate(vTaskToggleLed, "ToggleLed", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, NULL);
|
|
xTaskCreate(vTaskHelloWorld, "HelloWorld", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, NULL);
|
|
vTaskStartScheduler();
|
|
while(1);
|
|
}
|
|
|
|
/**! \func void vApplicationMallocFailedHook( void )
|
|
* \brief This hook function is called when allocation failed.
|
|
*/
|
|
void vApplicationMallocFailedHook( void )
|
|
{
|
|
#if defined (DEBUG)
|
|
printf("Malloc Failed Hook\n");
|
|
__ASM("BKPT #0\n");
|
|
#endif
|
|
NVIC_SystemReset();
|
|
while(TRUE){}
|
|
}
|
|
|
|
|
|
/**! \func vApplicationTickHook( void )
|
|
* \brief Toggles LED5_TICK to indicate RTOS running well
|
|
*/
|
|
void vApplicationTickHook( void )
|
|
{
|
|
static uint16_t tickCounter = 0;
|
|
if(++tickCounter == configTICK_RATE_HZ)
|
|
{
|
|
gpio_bit_reset(LED5_TICK_PORT, LED5_TICK);
|
|
tickCounter = 0;
|
|
}
|
|
else if(tickCounter == configTICK_RATE_HZ/2)
|
|
{
|
|
gpio_bit_set(LED5_TICK_PORT, LED5_TICK);
|
|
}
|
|
}
|
|
|
|
/**! \func vApplicationIdleHook( void )
|
|
* \brief Idle task Hook
|
|
*/
|
|
void vApplicationIdleHook( void )
|
|
{
|
|
#if defined (DEBUG)
|
|
int32_t delta = (configTICK_RATE_HZ-(TASK_TOGGLE_LED_DELAY + TASK_HELLO_WORLD_DELAY)) % configTICK_RATE_HZ;
|
|
if (delta < 0) delta = -delta;
|
|
|
|
static uint32_t idleHookCounter = 0;
|
|
uint32_t currentTick = xTaskGetTickCount();
|
|
if(currentTick > idleHookCounter + delta)
|
|
{
|
|
printf("Idle Hook %d\n", idleHookCounter);//__ASM("BKPT #0\n");
|
|
}
|
|
idleHookCounter = currentTick;
|
|
#endif
|
|
}
|
|
|
|
/**! \func vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
|
* \brief Stack overflow Hook
|
|
*/
|
|
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
|
{
|
|
#if defined (DEBUG)
|
|
printf("Stack Overflow Hook\n");
|
|
__ASM("BKPT #0\n");
|
|
#endif
|
|
NVIC_SystemReset();
|
|
while(TRUE){}
|
|
}
|
|
|
|
|
|
__attribute__((used)) void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
|
|
{
|
|
/* These are volatile to try and prevent the compiler/linker optimising them
|
|
away as the variables never actually get used. If the debugger won't show the
|
|
values of the variables, make them global my moving their declaration outside
|
|
of this function. */
|
|
static volatile uint32_t r0;
|
|
static volatile uint32_t r1;
|
|
static volatile uint32_t r2;
|
|
static volatile uint32_t r3;
|
|
static volatile uint32_t r12;
|
|
static volatile uint32_t lr; /* Link register. */
|
|
static volatile uint32_t pc; /* Program counter. */
|
|
static volatile uint32_t psr;/* Program status register. */
|
|
|
|
r0 = pulFaultStackAddress[ 0 ];
|
|
r1 = pulFaultStackAddress[ 1 ];
|
|
r2 = pulFaultStackAddress[ 2 ];
|
|
r3 = pulFaultStackAddress[ 3 ];
|
|
|
|
r12 = pulFaultStackAddress[ 4 ];
|
|
lr = pulFaultStackAddress[ 5 ];
|
|
pc = pulFaultStackAddress[ 6 ];
|
|
psr = pulFaultStackAddress[ 7 ];
|
|
#ifdef DEBUG
|
|
printf("Hard Fault Hook\n");
|
|
__asm volatile("BKPT #0\n") ;
|
|
#endif
|
|
NVIC_SystemReset();
|
|
/* When the following line is hit, the variables contain the register values. */
|
|
for( ;; );
|
|
}
|
|
|
|
void DelayMS(unsigned char ms)
|
|
{
|
|
unsigned long us = 1000*ms;
|
|
|
|
while (us--)
|
|
{
|
|
__NOP();
|
|
}
|
|
}
|