Starting point for IAR RISC-V project created some time ago - checking in now so it can be completed - currently work in progress.
parent
5352cb4f45
commit
72af51cd86
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.1
|
||||
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#define configISR_STACK_SIZE_WORDS ( 200 )
|
||||
#define configCLINT_BASE_ADDRESS 0x2000000
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 1
|
||||
#define configCPU_CLOCK_HZ ( ( uint32_t ) ( 32768 ) )
|
||||
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
|
||||
#define configMAX_PRIORITIES ( 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( uint32_t ) 170 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 54 * 1024 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 8
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Software timer definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define configTIMER_QUEUE_LENGTH 4
|
||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
|
||||
|
||||
/* Task priorities. Allow these to be overridden. */
|
||||
#ifndef uartPRIMARY_PRIORITY
|
||||
#define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
|
||||
#endif
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 1
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_xTaskAbortDelay 1
|
||||
#define INCLUDE_xTaskGetHandle 1
|
||||
#define INCLUDE_xSemaphoreGetMutexHolder 1
|
||||
|
||||
/* Normal assert() semantics without relying on the provision of an assert.h
|
||||
header file. */
|
||||
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); }
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<workspace>
|
||||
<project>
|
||||
<path>$WS_DIR$\RTOSDemo.ewp</path>
|
||||
</project>
|
||||
<batchBuild />
|
||||
</workspace>
|
@ -0,0 +1,172 @@
|
||||
/* Copyright 2018 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <metal/machine/platform.h>
|
||||
|
||||
#ifdef METAL_RISCV_PLIC0
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/shutdown.h>
|
||||
#include <metal/drivers/riscv_plic0.h>
|
||||
#include <metal/machine.h>
|
||||
|
||||
unsigned int __metal_plic0_claim_interrupt (struct __metal_driver_riscv_plic0 *plic)
|
||||
{
|
||||
unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
|
||||
return __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_CLAIM));
|
||||
}
|
||||
|
||||
void __metal_plic0_complete_interrupt(struct __metal_driver_riscv_plic0 *plic,
|
||||
unsigned int id)
|
||||
{
|
||||
unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
|
||||
__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_CLAIM)) = id;
|
||||
}
|
||||
|
||||
void __metal_plic0_set_threshold(struct __metal_driver_riscv_plic0 *plic,
|
||||
unsigned int threshold)
|
||||
{
|
||||
unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
|
||||
__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_THRESHOLD)) = threshold;
|
||||
}
|
||||
|
||||
void __metal_plic0_set_priority(struct __metal_driver_riscv_plic0 *plic,
|
||||
int id, unsigned int priority)
|
||||
{
|
||||
unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
|
||||
int max_priority = __metal_driver_sifive_plic0_max_priority((struct metal_interrupt *)plic);
|
||||
if ( (max_priority) && (priority < max_priority) ) {
|
||||
__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_PRIORITY_BASE +
|
||||
(id << METAL_PLIC_SOURCE_PRIORITY_SHIFT))) = priority;
|
||||
}
|
||||
}
|
||||
|
||||
void __metal_plic0_enable(struct __metal_driver_riscv_plic0 *plic, int id, int enable)
|
||||
{
|
||||
unsigned int current;
|
||||
unsigned long hartid = __metal_myhart_id();
|
||||
unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
|
||||
|
||||
current = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_ENABLE_BASE +
|
||||
(id >> METAL_PLIC_SOURCE_SHIFT) * 4));
|
||||
__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
|
||||
METAL_RISCV_PLIC0_ENABLE_BASE +
|
||||
((id >> METAL_PLIC_SOURCE_SHIFT) * 4))) =
|
||||
enable ? (current | (1 << (id & METAL_PLIC_SOURCE_MASK)))
|
||||
: (current & ~(1 << (id & METAL_PLIC_SOURCE_MASK)));
|
||||
}
|
||||
|
||||
void __metal_plic0_default_handler (int id, void *priv) {
|
||||
metal_shutdown(300);
|
||||
}
|
||||
|
||||
void __metal_plic0_handler (int id, void *priv)
|
||||
{
|
||||
struct __metal_driver_riscv_plic0 *plic = priv;
|
||||
unsigned int idx = __metal_plic0_claim_interrupt(plic);
|
||||
int num_interrupts = __metal_driver_sifive_plic0_num_interrupts((struct metal_interrupt *)plic);
|
||||
|
||||
if ( (idx < num_interrupts) && (plic->metal_exint_table[idx]) ) {
|
||||
plic->metal_exint_table[idx](idx,
|
||||
plic->metal_exdata_table[idx].exint_data);
|
||||
}
|
||||
|
||||
__metal_plic0_complete_interrupt(plic, idx);
|
||||
}
|
||||
|
||||
void __metal_driver_riscv_plic0_init (struct metal_interrupt *controller)
|
||||
{
|
||||
struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
|
||||
|
||||
if ( !plic->init_done ) {
|
||||
int num_interrupts, line;
|
||||
struct metal_interrupt *intc;
|
||||
|
||||
for(int parent = 0; parent < __METAL_PLIC_NUM_PARENTS; parent++) {
|
||||
num_interrupts = __metal_driver_sifive_plic0_num_interrupts(controller);
|
||||
intc = __metal_driver_sifive_plic0_interrupt_parents(controller, parent);
|
||||
line = __metal_driver_sifive_plic0_interrupt_lines(controller, parent);
|
||||
|
||||
/* Initialize ist parent controller, aka cpu_intc. */
|
||||
intc->vtable->interrupt_init(intc);
|
||||
|
||||
for (int i = 0; i < num_interrupts; i++) {
|
||||
__metal_plic0_enable(plic, i, METAL_DISABLE);
|
||||
__metal_plic0_set_priority(plic, i, 0);
|
||||
plic->metal_exint_table[i] = NULL;
|
||||
plic->metal_exdata_table[i].sub_int = NULL;
|
||||
plic->metal_exdata_table[i].exint_data = NULL;
|
||||
}
|
||||
|
||||
__metal_plic0_set_threshold(plic, 0);
|
||||
|
||||
/* Register plic (ext) interrupt with with parent controller */
|
||||
intc->vtable->interrupt_register(intc, line, NULL, plic);
|
||||
/* Register plic handler for dispatching its device interrupts */
|
||||
intc->vtable->interrupt_register(intc, line, __metal_plic0_handler, plic);
|
||||
/* Enable plic (ext) interrupt with with parent controller */
|
||||
intc->vtable->interrupt_enable(intc, line);
|
||||
}
|
||||
plic->init_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int __metal_driver_riscv_plic0_register (struct metal_interrupt *controller,
|
||||
int id, metal_interrupt_handler_t isr,
|
||||
void *priv)
|
||||
{
|
||||
struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
|
||||
|
||||
if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (isr) {
|
||||
__metal_plic0_set_priority(plic ,id, 2);
|
||||
plic->metal_exint_table[id] = isr;
|
||||
plic->metal_exdata_table[id].exint_data = priv;
|
||||
} else {
|
||||
__metal_plic0_set_priority(plic, id, 1);
|
||||
plic->metal_exint_table[id] = __metal_plic0_default_handler;
|
||||
plic->metal_exdata_table[id].sub_int = priv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __metal_driver_riscv_plic0_enable (struct metal_interrupt *controller, int id)
|
||||
{
|
||||
struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
|
||||
|
||||
if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
__metal_plic0_enable(plic, id, METAL_ENABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __metal_driver_riscv_plic0_disable (struct metal_interrupt *controller, int id)
|
||||
{
|
||||
struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
|
||||
|
||||
if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
|
||||
return -1;
|
||||
}
|
||||
__metal_plic0_enable(plic, id, METAL_DISABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_plic0) = {
|
||||
.plic_vtable.interrupt_init = __metal_driver_riscv_plic0_init,
|
||||
.plic_vtable.interrupt_register = __metal_driver_riscv_plic0_register,
|
||||
.plic_vtable.interrupt_enable = __metal_driver_riscv_plic0_enable,
|
||||
.plic_vtable.interrupt_disable = __metal_driver_riscv_plic0_disable,
|
||||
};
|
||||
|
||||
#endif /* METAL_RISCV_PLIC0 */
|
@ -0,0 +1,151 @@
|
||||
/* Copyright 2018 SiFive, Inc */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <metal/machine/platform.h>
|
||||
|
||||
#ifdef METAL_SIFIVE_UART0
|
||||
|
||||
#include <metal/drivers/sifive_uart0.h>
|
||||
#include <metal/machine.h>
|
||||
|
||||
/* TXDATA Fields */
|
||||
#define UART_TXEN (1 << 0)
|
||||
#define UART_TXFULL (1 << 31)
|
||||
|
||||
/* RXDATA Fields */
|
||||
#define UART_RXEN (1 << 0)
|
||||
#define UART_RXEMPTY (1 << 31)
|
||||
|
||||
/* TXCTRL Fields */
|
||||
#define UART_NSTOP (1 << 1)
|
||||
#define UART_TXCNT(count) ((0x7 & count) << 16)
|
||||
|
||||
/* IP Fields */
|
||||
#define UART_TXWM (1 << 0)
|
||||
|
||||
#define UART_REG(offset) (((unsigned long)control_base + offset))
|
||||
#define UART_REGB(offset) (__METAL_ACCESS_ONCE((__metal_io_u8 *)UART_REG(offset)))
|
||||
#define UART_REGW(offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)UART_REG(offset)))
|
||||
|
||||
struct metal_interrupt *
|
||||
__metal_driver_sifive_uart0_interrupt_controller(struct metal_uart *uart)
|
||||
{
|
||||
return __metal_driver_sifive_uart0_interrupt_parent(uart);
|
||||
}
|
||||
|
||||
int __metal_driver_sifive_uart0_get_interrupt_id(struct metal_uart *uart)
|
||||
{
|
||||
return (__metal_driver_sifive_uart0_interrupt_line(uart) + METAL_INTERRUPT_ID_GL0);
|
||||
}
|
||||
|
||||
int __metal_driver_sifive_uart0_putc(struct metal_uart *uart, unsigned char c)
|
||||
{
|
||||
long control_base = __metal_driver_sifive_uart0_control_base(uart);
|
||||
|
||||
while ((UART_REGW(METAL_SIFIVE_UART0_TXDATA) & UART_TXFULL) != 0) { }
|
||||
UART_REGW(METAL_SIFIVE_UART0_TXDATA) = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __metal_driver_sifive_uart0_getc(struct metal_uart *uart, unsigned char *c)
|
||||
{
|
||||
uint32_t ch = UART_RXEMPTY;
|
||||
long control_base = __metal_driver_sifive_uart0_control_base(uart);
|
||||
|
||||
while (ch & UART_RXEMPTY) {
|
||||
ch = UART_REGW(METAL_SIFIVE_UART0_RXDATA);
|
||||
}
|
||||
*c = ch & 0xff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __metal_driver_sifive_uart0_get_baud_rate(struct metal_uart *guart)
|
||||
{
|
||||
struct __metal_driver_sifive_uart0 *uart = (void *)guart;
|
||||
return uart->baud_rate;
|
||||
}
|
||||
|
||||
int __metal_driver_sifive_uart0_set_baud_rate(struct metal_uart *guart, int baud_rate)
|
||||
{
|
||||
struct __metal_driver_sifive_uart0 *uart = (void *)guart;
|
||||
long control_base = __metal_driver_sifive_uart0_control_base(guart);
|
||||
struct metal_clock *clock = __metal_driver_sifive_uart0_clock(guart);
|
||||
|
||||
uart->baud_rate = baud_rate;
|
||||
|
||||
if (clock != NULL) {
|
||||
long clock_rate = clock->vtable->get_rate_hz(clock);
|
||||
UART_REGW(METAL_SIFIVE_UART0_DIV) = clock_rate / baud_rate - 1;
|
||||
UART_REGW(METAL_SIFIVE_UART0_TXCTRL) |= UART_TXEN;
|
||||
UART_REGW(METAL_SIFIVE_UART0_RXCTRL) |= UART_RXEN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pre_rate_change_callback(void *priv)
|
||||
{
|
||||
struct __metal_driver_sifive_uart0 *uart = priv;
|
||||
long control_base = __metal_driver_sifive_uart0_control_base((struct metal_uart *)priv);
|
||||
struct metal_clock *clock = __metal_driver_sifive_uart0_clock((struct metal_uart *)priv);
|
||||
|
||||
/* Detect when the TXDATA is empty by setting the transmit watermark count
|
||||
* to one and waiting until an interrupt is pending */
|
||||
|
||||
UART_REGW(METAL_SIFIVE_UART0_TXCTRL) &= ~(UART_TXCNT(0x7));
|
||||
UART_REGW(METAL_SIFIVE_UART0_TXCTRL) |= UART_TXCNT(1);
|
||||
|
||||
while((UART_REGW(METAL_SIFIVE_UART0_IP) & UART_TXWM) == 0) ;
|
||||
|
||||
/* When the TXDATA clears, the UART is still shifting out the last byte.
|
||||
* Calculate the time we must drain to finish transmitting and then wait
|
||||
* that long. */
|
||||
|
||||
long bits_per_symbol = (UART_REGW(METAL_SIFIVE_UART0_TXCTRL) & (1 << 1)) ? 9 : 10;
|
||||
long clk_freq = clock->vtable->get_rate_hz(clock);
|
||||
long cycles_to_wait = bits_per_symbol * clk_freq / uart->baud_rate;
|
||||
|
||||
for(volatile long x = 0; x < cycles_to_wait; x++)
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
static void post_rate_change_callback(void *priv)
|
||||
{
|
||||
struct __metal_driver_sifive_uart0 *uart = priv;
|
||||
metal_uart_set_baud_rate(&uart->uart, uart->baud_rate);
|
||||
}
|
||||
|
||||
void __metal_driver_sifive_uart0_init(struct metal_uart *guart, int baud_rate)
|
||||
{
|
||||
struct __metal_driver_sifive_uart0 *uart = (void *)(guart);
|
||||
struct metal_clock *clock = __metal_driver_sifive_uart0_clock(guart);
|
||||
struct __metal_driver_sifive_gpio0 *pinmux = __metal_driver_sifive_uart0_pinmux(guart);
|
||||
|
||||
if(clock != NULL) {
|
||||
metal_clock_register_pre_rate_change_callback(clock, &pre_rate_change_callback, guart);
|
||||
metal_clock_register_post_rate_change_callback(clock, &post_rate_change_callback, guart);
|
||||
}
|
||||
|
||||
metal_uart_set_baud_rate(&(uart->uart), baud_rate);
|
||||
|
||||
if (pinmux != NULL) {
|
||||
long pinmux_output_selector = __metal_driver_sifive_uart0_pinmux_output_selector(guart);
|
||||
long pinmux_source_selector = __metal_driver_sifive_uart0_pinmux_source_selector(guart);
|
||||
pinmux->gpio.vtable->enable_io(
|
||||
(struct metal_gpio *) pinmux,
|
||||
pinmux_output_selector,
|
||||
pinmux_source_selector
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_uart0) = {
|
||||
.uart.init = __metal_driver_sifive_uart0_init,
|
||||
.uart.putc = __metal_driver_sifive_uart0_putc,
|
||||
.uart.getc = __metal_driver_sifive_uart0_getc,
|
||||
.uart.get_baud_rate = __metal_driver_sifive_uart0_get_baud_rate,
|
||||
.uart.set_baud_rate = __metal_driver_sifive_uart0_set_baud_rate,
|
||||
.uart.controller_interrupt = __metal_driver_sifive_uart0_interrupt_controller,
|
||||
.uart.get_interrupt_id = __metal_driver_sifive_uart0_get_interrupt_id,
|
||||
};
|
||||
|
||||
#endif /* METAL_SIFIVE_UART0 */
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.1
|
||||
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
EXTERN ulRegTest1LoopCounter
|
||||
EXTERN ulRegTest2LoopCounter
|
||||
|
||||
PUBLIC vRegTest1Implementation
|
||||
PUBLIC vRegTest2Implementation
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION `.text`:CODE:NOROOT(2)
|
||||
CODE
|
||||
|
||||
/*
|
||||
* The register check tasks are described in the comments at the top of
|
||||
* main_full.c.
|
||||
*/
|
||||
|
||||
vRegTest1Implementation:
|
||||
|
||||
/* Fill the core registers with known values. */
|
||||
li x5, 0x5
|
||||
li x6, 0x6
|
||||
li x7, 0x7
|
||||
li x8, 0x8
|
||||
li x9, 0x9
|
||||
li x10, 0xa
|
||||
li x11, 0xb
|
||||
li x12, 0xc
|
||||
li x13, 0xd
|
||||
li x14, 0xe
|
||||
li x15, 0xf
|
||||
li x16, 0x10
|
||||
li x17, 0x11
|
||||
li x18, 0x12
|
||||
li x19, 0x13
|
||||
li x20, 0x14
|
||||
li x21, 0x15
|
||||
li x22, 0x16
|
||||
li x23, 0x17
|
||||
li x24, 0x18
|
||||
li x25, 0x19
|
||||
li x26, 0x1a
|
||||
li x27, 0x1b
|
||||
li x28, 0x1c
|
||||
li x29, 0x1d
|
||||
li x30, 0x1e
|
||||
|
||||
reg1_loop:
|
||||
|
||||
/* Check each register still contains the expected known value.
|
||||
vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation
|
||||
uses x5 as the temporary. */
|
||||
li x31, 0x5
|
||||
bne x31, x5, reg1_error_loop
|
||||
li x31, 0x6
|
||||
bne x31, x6, reg1_error_loop
|
||||
li x31, 0x7
|
||||
bne x31, x7, reg1_error_loop
|
||||
li x31, 0x8
|
||||
bne x31, x8, reg1_error_loop
|
||||
li x31, 0x9
|
||||
bne x31, x9, reg1_error_loop
|
||||
li x31, 0xa
|
||||
bne x31, x10, reg1_error_loop
|
||||
li x31, 0xb
|
||||
bne x31, x11, reg1_error_loop
|
||||
li x31, 0xc
|
||||
bne x31, x12, reg1_error_loop
|
||||
li x31, 0xd
|
||||
bne x31, x13, reg1_error_loop
|
||||
li x31, 0xe
|
||||
bne x31, x14, reg1_error_loop
|
||||
li x31, 0xf
|
||||
bne x31, x15, reg1_error_loop
|
||||
li x31, 0x10
|
||||
bne x31, x16, reg1_error_loop
|
||||
li x31, 0x11
|
||||
bne x31, x17, reg1_error_loop
|
||||
li x31, 0x12
|
||||
bne x31, x18, reg1_error_loop
|
||||
li x31, 0x13
|
||||
bne x31, x19, reg1_error_loop
|
||||
li x31, 0x14
|
||||
bne x31, x20, reg1_error_loop
|
||||
li x31, 0x15
|
||||
bne x31, x21, reg1_error_loop
|
||||
li x31, 0x16
|
||||
bne x31, x22, reg1_error_loop
|
||||
li x31, 0x17
|
||||
bne x31, x23, reg1_error_loop
|
||||
li x31, 0x18
|
||||
bne x31, x24, reg1_error_loop
|
||||
li x31, 0x19
|
||||
bne x31, x25, reg1_error_loop
|
||||
li x31, 0x1a
|
||||
bne x31, x26, reg1_error_loop
|
||||
li x31, 0x1b
|
||||
bne x31, x27, reg1_error_loop
|
||||
li x31, 0x1c
|
||||
bne x31, x28, reg1_error_loop
|
||||
li x31, 0x1d
|
||||
bne x31, x29, reg1_error_loop
|
||||
li x31, 0x1e
|
||||
bne x31, x30, reg1_error_loop
|
||||
|
||||
/* Everything passed, increment the loop counter. */
|
||||
lw x31, ulRegTest1LoopCounter
|
||||
//_RB_ lw x30, 0(x31)
|
||||
addi x30, x30, 1
|
||||
sw x30, 0(x31)
|
||||
|
||||
/* Restore clobbered register reading for next loop. */
|
||||
li x30, 0x1e
|
||||
|
||||
/* Yield to increase code coverage. */
|
||||
ecall
|
||||
|
||||
/* Start again. */
|
||||
jal reg1_loop
|
||||
|
||||
reg1_error_loop:
|
||||
/* Jump here if a register contains an uxpected value. This stops the loop
|
||||
counter being incremented so the check task knows an error was found. */
|
||||
jal reg1_error_loop
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRegTest2Implementation:
|
||||
|
||||
/* Fill the core registers with known values. */
|
||||
li x6, 0x61
|
||||
li x7, 0x71
|
||||
li x8, 0x81
|
||||
li x9, 0x91
|
||||
li x10, 0xa1
|
||||
li x11, 0xb1
|
||||
li x12, 0xc1
|
||||
li x13, 0xd1
|
||||
li x14, 0xe1
|
||||
li x15, 0xf1
|
||||
li x16, 0x20
|
||||
li x17, 0x21
|
||||
li x18, 0x22
|
||||
li x19, 0x23
|
||||
li x20, 0x24
|
||||
li x21, 0x25
|
||||
li x22, 0x26
|
||||
li x23, 0x27
|
||||
li x24, 0x28
|
||||
li x25, 0x29
|
||||
li x26, 0x2a
|
||||
li x27, 0x2b
|
||||
li x28, 0x2c
|
||||
li x29, 0x2d
|
||||
li x30, 0x2e
|
||||
li x31, 0x2f
|
||||
|
||||
Reg2_loop:
|
||||
|
||||
/* Check each register still contains the expected known value.
|
||||
vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation
|
||||
uses x31 as the temporary. */
|
||||
li x5, 0x61
|
||||
bne x5, x6, reg2_error_loop
|
||||
li x5, 0x71
|
||||
bne x5, x7, reg2_error_loop
|
||||
li x5, 0x81
|
||||
bne x5, x8, reg2_error_loop
|
||||
li x5, 0x91
|
||||
bne x5, x9, reg2_error_loop
|
||||
li x5, 0xa1
|
||||
bne x5, x10, reg2_error_loop
|
||||
li x5, 0xb1
|
||||
bne x5, x11, reg2_error_loop
|
||||
li x5, 0xc1
|
||||
bne x5, x12, reg2_error_loop
|
||||
li x5, 0xd1
|
||||
bne x5, x13, reg2_error_loop
|
||||
li x5, 0xe1
|
||||
bne x5, x14, reg2_error_loop
|
||||
li x5, 0xf1
|
||||
bne x5, x15, reg2_error_loop
|
||||
li x5, 0x20
|
||||
bne x5, x16, reg2_error_loop
|
||||
li x5, 0x21
|
||||
bne x5, x17, reg2_error_loop
|
||||
li x5, 0x22
|
||||
bne x5, x18, reg2_error_loop
|
||||
li x5, 0x23
|
||||
bne x5, x19, reg2_error_loop
|
||||
li x5, 0x24
|
||||
bne x5, x20, reg2_error_loop
|
||||
li x5, 0x25
|
||||
bne x5, x21, reg2_error_loop
|
||||
li x5, 0x26
|
||||
bne x5, x22, reg2_error_loop
|
||||
li x5, 0x27
|
||||
bne x5, x23, reg2_error_loop
|
||||
li x5, 0x28
|
||||
bne x5, x24, reg2_error_loop
|
||||
li x5, 0x29
|
||||
bne x5, x25, reg2_error_loop
|
||||
li x5, 0x2a
|
||||
bne x5, x26, reg2_error_loop
|
||||
li x5, 0x2b
|
||||
bne x5, x27, reg2_error_loop
|
||||
li x5, 0x2c
|
||||
bne x5, x28, reg2_error_loop
|
||||
li x5, 0x2d
|
||||
bne x5, x29, reg2_error_loop
|
||||
li x5, 0x2e
|
||||
bne x5, x30, reg2_error_loop
|
||||
li x5, 0x2f
|
||||
bne x5, x31, reg2_error_loop
|
||||
|
||||
/* Everything passed, increment the loop counter. */
|
||||
lw x5, ulRegTest2LoopCounter
|
||||
//_RB_ lw x6, 0(x5)
|
||||
addi x6, x6, 1
|
||||
sw x6, 0(x5)
|
||||
|
||||
/* Restore clobbered register reading for next loop. */
|
||||
li x6, 0x61
|
||||
|
||||
/* Start again. */
|
||||
jal Reg2_loop
|
||||
|
||||
reg2_error_loop:
|
||||
/* Jump here if a register contains an uxpected value. This stops the loop
|
||||
counter being incremented so the check task knows an error was found. */
|
||||
jal reg2_error_loop
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
@ -0,0 +1,397 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.1
|
||||
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* NOTE 1: This project provides two demo applications. A simple blinky style
|
||||
* project, and a more comprehensive test and demo application. The
|
||||
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
|
||||
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
|
||||
* in main.c. This file implements the comprehensive test and demo version.
|
||||
*
|
||||
* NOTE 2: This file only contains the source code that is specific to the
|
||||
* full demo. Generic functions, such FreeRTOS hook functions, and functions
|
||||
* required to configure the hardware, are defined in main.c.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* main_full() creates all the demo application tasks and software timers, then
|
||||
* starts the scheduler. The web documentation provides more details of the
|
||||
* standard demo application tasks, which provide no particular functionality,
|
||||
* but do provide a good example of how to use the FreeRTOS API.
|
||||
*
|
||||
* In addition to the standard demo tasks, the following tasks and tests are
|
||||
* defined and/or created within this file:
|
||||
*
|
||||
* "Reg test" tasks - These fill both the core registers with known values, then
|
||||
* check that each register maintains its expected value for the lifetime of the
|
||||
* task. Each task uses a different set of values. The reg test tasks execute
|
||||
* with a very low priority, so get preempted very frequently. A register
|
||||
* containing an unexpected value is indicative of an error in the context
|
||||
* switching mechanism.
|
||||
*
|
||||
* "Check" task - The check executes every three seconds. It checks that all
|
||||
* the standard demo tasks, and the register check tasks, are not only still
|
||||
* executing, but are executing without reporting any errors. If the check task
|
||||
* discovers that a task has either stalled, or reported an error, then it
|
||||
* prints an error message to the UART, otherwise it prints "Pass.".
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "semphr.h"
|
||||
|
||||
|
||||
/* Standard demo application includes. */
|
||||
#include "dynamic.h"
|
||||
#include "blocktim.h"
|
||||
#include "GenQTest.h"
|
||||
#include "recmutex.h"
|
||||
#include "TimerDemo.h"
|
||||
#include "EventGroupsDemo.h"
|
||||
#include "TaskNotify.h"
|
||||
#include "AbortDelay.h"
|
||||
#include "countsem.h"
|
||||
#include "death.h"
|
||||
#include "MessageBufferDemo.h"
|
||||
#include "StreamBufferDemo.h"
|
||||
#include "StreamBufferInterrupt.h"
|
||||
|
||||
/* Priorities for the demo application tasks. */
|
||||
#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
|
||||
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL )
|
||||
|
||||
/* The period of the check task, in ms, converted to ticks using the
|
||||
pdMS_TO_TICKS() macro. mainNO_ERROR_CHECK_TASK_PERIOD is used if no errors have
|
||||
been found, mainERROR_CHECK_TASK_PERIOD is used if an error has been found. */
|
||||
#define mainNO_ERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 3000UL )
|
||||
#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 500UL )
|
||||
|
||||
/* Parameters that are passed into the register check tasks solely for the
|
||||
purpose of ensuring parameters are passed into tasks correctly. */
|
||||
#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
|
||||
#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
|
||||
|
||||
/* The base period used by the timer test tasks. */
|
||||
#define mainTIMER_TEST_PERIOD ( 50 )
|
||||
|
||||
/* The size of the stack allocated to the check task (as described in the
|
||||
comments at the top of this file. */
|
||||
#define mainCHECK_TASK_STACK_SIZE_WORDS 100
|
||||
|
||||
/* Size of the stacks to allocated for the register check tasks. */
|
||||
#define mainREG_TEST_STACK_SIZE_WORDS 70
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by main() to run the full demo (as opposed to the blinky demo) when
|
||||
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
|
||||
*/
|
||||
void main_full( void );
|
||||
|
||||
/*
|
||||
* The check task, as described at the top of this file.
|
||||
*/
|
||||
static void prvCheckTask( void *pvParameters );
|
||||
|
||||
/*
|
||||
* Initialise and start the peripheral timers that are used to exercise external
|
||||
* interrupt processing.
|
||||
*/
|
||||
static void prvSetupPeripheralTimers( void );
|
||||
|
||||
/*
|
||||
* Register check tasks as described at the top of this file. The nature of
|
||||
* these files necessitates that they are written in an assembly file, but the
|
||||
* entry points are kept in the C file for the convenience of checking the task
|
||||
* parameter.
|
||||
*/
|
||||
static void prvRegTestTaskEntry1( void *pvParameters );
|
||||
extern void vRegTest1Implementation( void );
|
||||
static void prvRegTestTaskEntry2( void *pvParameters );
|
||||
extern void vRegTest2Implementation( void );
|
||||
|
||||
/*
|
||||
* Tick hook used by the full demo, which includes code that interacts with
|
||||
* some of the tests.
|
||||
*/
|
||||
void vFullDemoTickHook( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The following two variables are used to communicate the status of the
|
||||
register check tasks to the check task. If the variables keep incrementing,
|
||||
then the register check tasks have not discovered any errors. If a variable
|
||||
stops incrementing, then an error has been found. */
|
||||
volatile uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void main_full( void )
|
||||
{
|
||||
/* Start all the other standard demo/test tasks. They have no particular
|
||||
functionality, but do demonstrate how to use the FreeRTOS API and test the
|
||||
kernel port. */
|
||||
vStartDynamicPriorityTasks();
|
||||
vCreateBlockTimeTasks();
|
||||
vStartGenericQueueTasks( tskIDLE_PRIORITY );
|
||||
vStartRecursiveMutexTasks();
|
||||
vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
|
||||
vStartEventGroupTasks();
|
||||
vStartTaskNotifyTask();
|
||||
vCreateAbortDelayTasks();
|
||||
vStartCountingSemaphoreTasks();
|
||||
vStartMessageBufferTasks( configMINIMAL_STACK_SIZE );
|
||||
vStartStreamBufferTasks();
|
||||
vStartStreamBufferInterruptDemo();
|
||||
|
||||
/* Create the register check tasks, as described at the top of this file.
|
||||
Use xTaskCreateStatic() to create a task using only statically allocated
|
||||
memory. */
|
||||
xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */
|
||||
"Reg1", /* The name of the task. */
|
||||
mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */
|
||||
mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */
|
||||
tskIDLE_PRIORITY, /* Priority of the task. */
|
||||
NULL ); /* Can be used to pass out a handle to the created task. */
|
||||
xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
|
||||
|
||||
/* Create the task that performs the 'check' functionality, as described at
|
||||
the top of this file. */
|
||||
xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE_WORDS, NULL, mainCHECK_TASK_PRIORITY, NULL );
|
||||
|
||||
/* The set of tasks created by the following function call have to be
|
||||
created last as they keep account of the number of tasks they expect to see
|
||||
running. */
|
||||
vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
|
||||
|
||||
/* Start the scheduler. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following
|
||||
line will never be reached. If the following line does execute, then
|
||||
there was insufficient FreeRTOS heap memory available for the Idle and/or
|
||||
timer tasks to be created. See the memory management section on the
|
||||
FreeRTOS web site for more details on the FreeRTOS heap
|
||||
http://www.freertos.org/a00111.html. */
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckTask( void *pvParameters )
|
||||
{
|
||||
TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD;
|
||||
TickType_t xLastExecutionTime;
|
||||
uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
|
||||
char * const pcPassMessage = ".";
|
||||
char * pcStatusMessage = pcPassMessage;
|
||||
extern void vSendString( const char * const pcString );
|
||||
extern void vToggleLED( void );
|
||||
|
||||
/* Just to stop compiler warnings. */
|
||||
( void ) pvParameters;
|
||||
|
||||
/* Start with a pass message, after which a '.' character will be printed
|
||||
out on each successful loop. */
|
||||
vSendString( "Pass" );
|
||||
|
||||
/* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
|
||||
works correctly. */
|
||||
xLastExecutionTime = xTaskGetTickCount();
|
||||
|
||||
/* Cycle for ever, delaying then checking all the other tasks are still
|
||||
operating without error. The onboard LED is toggled on each iteration.
|
||||
If an error is detected then the delay period is decreased from
|
||||
mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the
|
||||
effect of increasing the rate at which the onboard LED toggles, and in so
|
||||
doing gives visual feedback of the system status. */
|
||||
for( ;; )
|
||||
{
|
||||
/* Delay until it is time to execute again. */
|
||||
vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );
|
||||
|
||||
/* Check all the demo tasks (other than the flash tasks) to ensure
|
||||
that they are all still running, and that none have detected an error. */
|
||||
if( xAreDynamicPriorityTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Dynamic priority demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreBlockTimeTestTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Block time demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreGenericQueueTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Generic queue demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreRecursiveMutexTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Recursive mutex demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Timer demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreEventGroupTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Event group demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreTaskNotificationTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Task notification demo/tests.\r\n";
|
||||
}
|
||||
|
||||
if( xAreAbortDelayTestTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Abort delay.\r\n";
|
||||
}
|
||||
|
||||
if( xAreCountingSemaphoreTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Counting semaphores.\r\n";
|
||||
}
|
||||
|
||||
if( xIsCreateTaskStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Suicide tasks.\r\n";
|
||||
}
|
||||
|
||||
if( xAreMessageBufferTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Message buffer.\r\n";
|
||||
}
|
||||
|
||||
if( xAreStreamBufferTasksStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Stream buffer.\r\n";
|
||||
}
|
||||
|
||||
if( xIsInterruptStreamBufferDemoStillRunning() == pdFALSE )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Stream buffer interrupt.\r\n";
|
||||
}
|
||||
|
||||
/* Check that the register test 1 task is still running. */
|
||||
if( ulLastRegTest1Value == ulRegTest1LoopCounter )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Register test 1.\r\n";
|
||||
}
|
||||
ulLastRegTest1Value = ulRegTest1LoopCounter;
|
||||
|
||||
/* Check that the register test 2 task is still running. */
|
||||
if( ulLastRegTest2Value == ulRegTest2LoopCounter )
|
||||
{
|
||||
pcStatusMessage = "ERROR: Register test 2.\r\n";
|
||||
}
|
||||
ulLastRegTest2Value = ulRegTest2LoopCounter;
|
||||
|
||||
/* Write the status message to the UART. */
|
||||
vSendString( pcStatusMessage );
|
||||
|
||||
/* If an error has been found then increase the LED toggle rate by
|
||||
increasing the cycle frequency. */
|
||||
if( pcStatusMessage != pcPassMessage )
|
||||
{
|
||||
xDelayPeriod = mainERROR_CHECK_TASK_PERIOD;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRegTestTaskEntry1( void *pvParameters )
|
||||
{
|
||||
/* Although the regtest task is written in assembler, its entry point is
|
||||
written in C for convenience of checking the task parameter is being passed
|
||||
in correctly. */
|
||||
if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )
|
||||
{
|
||||
/* Start the part of the test that is written in assembler. */
|
||||
vRegTest1Implementation();
|
||||
}
|
||||
|
||||
/* The following line will only execute if the task parameter is found to
|
||||
be incorrect. The check task will detect that the regtest loop counter is
|
||||
not being incremented and flag an error. */
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRegTestTaskEntry2( void *pvParameters )
|
||||
{
|
||||
/* Although the regtest task is written in assembler, its entry point is
|
||||
written in C for convenience of checking the task parameter is being passed
|
||||
in correctly. */
|
||||
if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )
|
||||
{
|
||||
/* Start the part of the test that is written in assembler. */
|
||||
vRegTest2Implementation();
|
||||
}
|
||||
|
||||
/* The following line will only execute if the task parameter is found to
|
||||
be incorrect. The check task will detect that the regtest loop counter is
|
||||
not being incremented and flag an error. */
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vFullDemoTickHook( void )
|
||||
{
|
||||
/* The full demo includes a software timer demo/test that requires
|
||||
prodding periodically from the tick interrupt. */
|
||||
vTimerPeriodicISRTests();
|
||||
|
||||
/* Call the periodic event group from ISR demo. */
|
||||
vPeriodicEventGroupsProcessing();
|
||||
|
||||
/* Use task notifications from an interrupt. */
|
||||
xNotifyTaskFromISR();
|
||||
|
||||
/* Writes to stream buffer byte by byte to test the stream buffer trigger
|
||||
level functionality. */
|
||||
vPeriodicStreamBufferProcessing();
|
||||
|
||||
/* Writes a string to a string buffer four bytes at a time to demonstrate
|
||||
a stream being sent from an interrupt to a task. */
|
||||
vBasicStreamBufferSendFromISR();
|
||||
|
||||
/* Called from vApplicationTickHook() when the project is configured to
|
||||
build the full test/demo applications. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.1
|
||||
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* FreeRTOS kernel includes. */
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
/******************************************************************************
|
||||
* This project provides two demo applications. A simple blinky style project,
|
||||
* and a more comprehensive test and demo application. The
|
||||
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to
|
||||
* select between the two. The simply blinky demo is implemented and described
|
||||
* in main_blinky.c. The more comprehensive test and demo application is
|
||||
* implemented and described in main_full.c.
|
||||
*
|
||||
* This file implements the code that is not demo specific, including the
|
||||
* hardware setup and standard FreeRTOS hook functions.
|
||||
*
|
||||
* ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
|
||||
* THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
|
||||
* APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
|
||||
*
|
||||
*/
|
||||
|
||||
/* UART hardware constants. */
|
||||
#define mainUART_BASE_ADDRESS ( *( volatile uint32_t * ) 0x20000000UL )
|
||||
#define mainUART_TX_DATA 0x00
|
||||
#define mainUART_TX_CTRL 0x08
|
||||
#define mainUART_RX_CTRL 0x0c
|
||||
#define mainUART_CLOCK_DIV 0x18
|
||||
#define mainUART_TX_ENABLE_BIT (1UL << 0UL)
|
||||
#define mainUART_RX_ENABLE_BIT (1UL << 0UL)
|
||||
#define mainUART_TX_FULL_BIT (1UL << 31UL)
|
||||
#define mainUART_REGISTER( offset ) ( ( mainUART_BASE_ADDRESS + offset ) )
|
||||
#define mainUART_REGISTER_WORD( offset ) ( *( ( uint32_t * ) mainUART_REGISTER( offset ) ) )
|
||||
|
||||
|
||||
/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo,
|
||||
or 0 to run the more comprehensive test and demo application. */
|
||||
#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
|
||||
|
||||
/*
|
||||
* main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
|
||||
* main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
|
||||
*/
|
||||
#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1
|
||||
extern void main_blinky( void );
|
||||
#else
|
||||
extern void main_full( void );
|
||||
#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */
|
||||
|
||||
/* Prototypes for the standard FreeRTOS callback/hook functions implemented
|
||||
within this file. See https://www.freertos.org/a00016.html */
|
||||
void vApplicationMallocFailedHook( void );
|
||||
void vApplicationIdleHook( void );
|
||||
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
|
||||
void vApplicationTickHook( void );
|
||||
|
||||
/* Prepare hardware to run the demo. */
|
||||
static void prvSetupHardware( void );
|
||||
|
||||
/* Send a message to the UART initialised in prvSetupHardware. */
|
||||
void vSendString( const char * const pcString );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int main( void )
|
||||
{
|
||||
prvSetupHardware();
|
||||
|
||||
/* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
|
||||
of this file. */
|
||||
#if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
|
||||
{
|
||||
main_blinky();
|
||||
}
|
||||
#else
|
||||
{
|
||||
main_full();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupHardware( void )
|
||||
{
|
||||
const unsigned long clock_rate = 66000000, baud_rate = 115200;
|
||||
|
||||
/* Initialise the UART. */
|
||||
mainUART_REGISTER_WORD( mainUART_CLOCK_DIV ) = clock_rate / baud_rate - 1;
|
||||
mainUART_REGISTER_WORD( mainUART_TX_CTRL ) |= mainUART_TX_ENABLE_BIT;
|
||||
mainUART_REGISTER_WORD( mainUART_RX_CTRL ) |= mainUART_RX_ENABLE_BIT;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vToggleLED( void )
|
||||
{
|
||||
static uint32_t ulLEDState = 0;
|
||||
|
||||
ulLEDState = !ulLEDState;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vSendString( const char * const pcString )
|
||||
{
|
||||
uint32_t ulIndex = 0;
|
||||
|
||||
while( pcString[ ulIndex ] != 0x00 )
|
||||
{
|
||||
while( ( mainUART_REGISTER_WORD( mainUART_TX_DATA ) & mainUART_TX_FULL_BIT ) != 0UL );
|
||||
mainUART_REGISTER_WORD(mainUART_TX_DATA) = pcString[ ulIndex ];
|
||||
ulIndex++;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationMallocFailedHook( void )
|
||||
{
|
||||
/* vApplicationMallocFailedHook() will only be called if
|
||||
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
|
||||
function that will get called if a call to pvPortMalloc() fails.
|
||||
pvPortMalloc() is called internally by the kernel whenever a task, queue,
|
||||
timer or semaphore is created. It is also called by various parts of the
|
||||
demo application. If heap_1.c or heap_2.c are used, then the size of the
|
||||
heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
|
||||
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
|
||||
to query the size of free heap space that remains (although it does not
|
||||
provide information on how the remaining heap might be fragmented). */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
__asm volatile( "ebreak" );
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
|
||||
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
|
||||
task. It is essential that code added to this hook function never attempts
|
||||
to block in any way (for example, call xQueueReceive() with a block time
|
||||
specified, or call vTaskDelay()). If the application makes use of the
|
||||
vTaskDelete() API function (as this demo application does) then it is also
|
||||
important that vApplicationIdleHook() is permitted to return to its calling
|
||||
function, because it is the responsibility of the idle task to clean up
|
||||
memory allocated by the kernel to any task that has since been deleted. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
||||
{
|
||||
( void ) pcTaskName;
|
||||
( void ) pxTask;
|
||||
|
||||
/* Run time stack overflow checking is performed if
|
||||
configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
|
||||
function is called if a stack overflow is detected. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
__asm volatile( "ebreak" );
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationTickHook( void )
|
||||
{
|
||||
/* The tests in the full demo expect some interaction with interrupts. */
|
||||
#if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
|
||||
{
|
||||
extern void vFullDemoTickHook( void );
|
||||
vFullDemoTickHook();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Called from the kernel's port layer to handle device specific external
|
||||
interrupts. */
|
||||
void vApplicationHandleTrap( uint32_t mcause )
|
||||
{
|
||||
/* Not implemented yet. */
|
||||
configASSERT( mcause == 0 );
|
||||
#warning vApplicationHandleTrap not implemented.
|
||||
#if 0
|
||||
uint32_t ulInterruptNumber;
|
||||
typedef void ( * irq_handler_t )( void );
|
||||
extern const irq_handler_t isrTable[];
|
||||
|
||||
ulInterruptNumber = PLIC->TARGET[ 0 ].CLAIM_COMPLETE;
|
||||
|
||||
/* Read handler from table. */
|
||||
/* Call handler. */
|
||||
|
||||
PLIC->TARGET[ 0 ].CLAIM_COMPLETE = ulInterruptNumber;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.2.1
|
||||
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* NOTE 1: This project provides two demo applications. A simple blinky
|
||||
* style project, and a more comprehensive test and demo application. The
|
||||
* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
|
||||
* between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
|
||||
* in main.c. This file implements the simply blinky style version.
|
||||
*
|
||||
* NOTE 2: This file only contains the source code that is specific to the
|
||||
* basic demo. Generic functions, such FreeRTOS hook functions, and functions
|
||||
* required to configure the hardware are defined in main.c.
|
||||
******************************************************************************
|
||||
*
|
||||
* main_blinky() creates one queue, and two tasks. It then starts the
|
||||
* scheduler.
|
||||
*
|
||||
* The Queue Send Task:
|
||||
* The queue send task is implemented by the prvQueueSendTask() function in
|
||||
* this file. prvQueueSendTask() sits in a loop that causes it to repeatedly
|
||||
* block for 1000 milliseconds, before sending the value 100 to the queue that
|
||||
* was created within main_blinky(). Once the value is sent, the task loops
|
||||
* back around to block for another 1000 milliseconds...and so on.
|
||||
*
|
||||
* The Queue Receive Task:
|
||||
* The queue receive task is implemented by the prvQueueReceiveTask() function
|
||||
* in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
|
||||
* blocks on attempts to read data from the queue that was created within
|
||||
* main_blinky(). When data is received, the task checks the value of the
|
||||
* data, and if the value equals the expected 100, writes 'Blink' to the UART
|
||||
* (the UART is used in place of the LED to allow easy execution in QEMU). The
|
||||
* 'block time' parameter passed to the queue receive function specifies that
|
||||
* the task should be held in the Blocked state indefinitely to wait for data to
|
||||
* be available on the queue. The queue receive task will only leave the
|
||||
* Blocked state when the queue send task writes to the queue. As the queue
|
||||
* send task writes to the queue every 1000 milliseconds, the queue receive
|
||||
* task leaves the Blocked state every 1000 milliseconds, and therefore toggles
|
||||
* the LED every 200 milliseconds.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* Priorities used by the tasks. */
|
||||
#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||
|
||||
/* The rate at which data is sent to the queue. The 200ms value is converted
|
||||
to ticks using the pdMS_TO_TICKS() macro. */
|
||||
#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )
|
||||
|
||||
/* The maximum number items the queue can hold. The priority of the receiving
|
||||
task is above the priority of the sending task, so the receiving task will
|
||||
preempt the sending task and remove the queue items each time the sending task
|
||||
writes to the queue. Therefore the queue will never have more than one item in
|
||||
it at any time, and even with a queue length of 1, the sending task will never
|
||||
find the queue full. */
|
||||
#define mainQUEUE_LENGTH ( 1 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in
|
||||
* main.c.
|
||||
*/
|
||||
void main_blinky( void );
|
||||
|
||||
/*
|
||||
* The tasks as described in the comments at the top of this file.
|
||||
*/
|
||||
static void prvQueueReceiveTask( void *pvParameters );
|
||||
static void prvQueueSendTask( void *pvParameters );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The queue used by both tasks. */
|
||||
static QueueHandle_t xQueue = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void main_blinky( void )
|
||||
{
|
||||
/* Create the queue. */
|
||||
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
|
||||
|
||||
if( xQueue != NULL )
|
||||
{
|
||||
/* Start the two tasks as described in the comments at the top of this
|
||||
file. */
|
||||
xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
|
||||
"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
|
||||
configMINIMAL_STACK_SIZE * 2U, /* The size of the stack to allocate to the task. */
|
||||
NULL, /* The parameter passed to the task - not used in this case. */
|
||||
mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
|
||||
NULL ); /* The task handle is not required, so NULL is passed. */
|
||||
|
||||
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
|
||||
|
||||
/* Start the tasks and timer running. */
|
||||
vTaskStartScheduler();
|
||||
}
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following
|
||||
line will never be reached. If the following line does execute, then
|
||||
there was insufficient FreeRTOS heap memory available for the Idle and/or
|
||||
timer tasks to be created. See the memory management section on the
|
||||
FreeRTOS web site for more details on the FreeRTOS heap
|
||||
http://www.freertos.org/a00111.html. */
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvQueueSendTask( void *pvParameters )
|
||||
{
|
||||
TickType_t xNextWakeTime;
|
||||
const unsigned long ulValueToSend = 100UL;
|
||||
BaseType_t xReturned;
|
||||
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
( void ) pvParameters;
|
||||
|
||||
/* Initialise xNextWakeTime - this only needs to be done once. */
|
||||
xNextWakeTime = xTaskGetTickCount();
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Place this task in the blocked state until it is time to run again. */
|
||||
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
|
||||
|
||||
/* Send to the queue - causing the queue receive task to unblock and
|
||||
toggle the LED. 0 is used as the block time so the sending operation
|
||||
will not block - it shouldn't need to block as the queue should always
|
||||
be empty at this point in the code. */
|
||||
xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
|
||||
configASSERT( xReturned == pdPASS );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvQueueReceiveTask( void *pvParameters )
|
||||
{
|
||||
unsigned long ulReceivedValue;
|
||||
const unsigned long ulExpectedValue = 100UL;
|
||||
const char * const pcPassMessage = "Blink\r\n";
|
||||
const char * const pcFailMessage = "Unexpected value received\r\n";
|
||||
extern void vSendString( const char * const pcString );
|
||||
extern void vToggleLED( void );
|
||||
|
||||
/* Remove compiler warning about unused parameter. */
|
||||
( void ) pvParameters;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Wait until something arrives in the queue - this task will block
|
||||
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
|
||||
FreeRTOSConfig.h. */
|
||||
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
|
||||
|
||||
/* To get here something must have been received from the queue, but
|
||||
is it the expected value? If it is, toggle the LED. */
|
||||
if( ulReceivedValue == ulExpectedValue )
|
||||
{
|
||||
vSendString( pcPassMessage );
|
||||
vToggleLED();
|
||||
ulReceivedValue = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
vSendString( pcFailMessage );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -0,0 +1,40 @@
|
||||
@REM This batch file has been generated by the IAR Embedded Workbench
|
||||
@REM C-SPY Debugger, as an aid to preparing a command line for running
|
||||
@REM the cspybat command line utility using the appropriate settings.
|
||||
@REM
|
||||
@REM Note that this file is generated every time a new debug session
|
||||
@REM is initialized, so you may want to move or rename the file before
|
||||
@REM making changes.
|
||||
@REM
|
||||
@REM You can launch cspybat by typing the name of this batch file followed
|
||||
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
|
||||
@REM
|
||||
@REM Read about available command line parameters in the C-SPY Debugging
|
||||
@REM Guide. Hints about additional command line parameters that may be
|
||||
@REM useful in specific cases:
|
||||
@REM --download_only Downloads a code image without starting a debug
|
||||
@REM session afterwards.
|
||||
@REM --silent Omits the sign-on message.
|
||||
@REM --timeout Limits the maximum allowed execution time.
|
||||
@REM
|
||||
|
||||
|
||||
@echo off
|
||||
|
||||
if not "%~1" == "" goto debugFile
|
||||
|
||||
@echo on
|
||||
|
||||
"C:\devtools\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "C:\Users\ribarry\Dev\FreeRTOS\WorkingCopy\FreeRTOS\Demo\RISC-V_RV32_SiFive_IAR\settings\RTOSDemo.Debug.general.xcl" --backend -f "C:\Users\ribarry\Dev\FreeRTOS\WorkingCopy\FreeRTOS\Demo\RISC-V_RV32_SiFive_IAR\settings\RTOSDemo.Debug.driver.xcl"
|
||||
|
||||
@echo off
|
||||
goto end
|
||||
|
||||
:debugFile
|
||||
|
||||
@echo on
|
||||
|
||||
"C:\devtools\IAR Systems\Embedded Workbench 8.3\common\bin\cspybat" -f "C:\Users\ribarry\Dev\FreeRTOS\WorkingCopy\FreeRTOS\Demo\RISC-V_RV32_SiFive_IAR\settings\RTOSDemo.Debug.general.xcl" "--debug_file=%~1" --backend -f "C:\Users\ribarry\Dev\FreeRTOS\WorkingCopy\FreeRTOS\Demo\RISC-V_RV32_SiFive_IAR\settings\RTOSDemo.Debug.driver.xcl"
|
||||
|
||||
@echo off
|
||||
:end
|
@ -0,0 +1,13 @@
|
||||
"--core=RV32IMAC"
|
||||
|
||||
"-p"
|
||||
|
||||
"C:\devtools\IAR Systems\Embedded Workbench 8.3\riscv\config\debugger\SiFive\e31arty35t.ddf"
|
||||
|
||||
"-d"
|
||||
|
||||
"sim"
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
"C:\devtools\IAR Systems\Embedded Workbench 8.3\riscv\bin\riscvproc.dll"
|
||||
|
||||
"C:\devtools\IAR Systems\Embedded Workbench 8.3\riscv\bin\riscvsim.dll"
|
||||
|
||||
"C:\Users\ribarry\Dev\FreeRTOS\WorkingCopy\FreeRTOS\Demo\RISC-V_RV32_SiFive_IAR\Debug\Exe\RTOSDemo.out"
|
||||
|
||||
--plugin="C:\devtools\IAR Systems\Embedded Workbench 8.3\riscv\bin\riscvbat.dll"
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,111 @@
|
||||
<?xml version="1.0"?>
|
||||
<settings>
|
||||
<Stack>
|
||||
<FillEnabled>0</FillEnabled>
|
||||
<OverflowWarningsEnabled>1</OverflowWarningsEnabled>
|
||||
<WarningThreshold>90</WarningThreshold>
|
||||
<SpWarningsEnabled>1</SpWarningsEnabled>
|
||||
<WarnLogOnly>1</WarnLogOnly>
|
||||
<UseTrigger>1</UseTrigger>
|
||||
<TriggerName>main</TriggerName>
|
||||
<LimitSize>0</LimitSize>
|
||||
<ByteLimit>50</ByteLimit>
|
||||
</Stack>
|
||||
<DebugChecksum>
|
||||
<Checksum>1686049390</Checksum>
|
||||
</DebugChecksum>
|
||||
<Disassembly>
|
||||
<InstrCount>0</InstrCount>
|
||||
<MixedMode>1</MixedMode>
|
||||
</Disassembly>
|
||||
<CodeCoverage>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>0</ShowSource>
|
||||
<HideCovered>0</HideCovered>
|
||||
</CodeCoverage>
|
||||
<CallStack>
|
||||
<ShowArgs>0</ShowArgs>
|
||||
</CallStack>
|
||||
<DataAlign>
|
||||
<Action>1</Action>
|
||||
<Notification>1</Notification>
|
||||
</DataAlign>
|
||||
<DriverProfiling>
|
||||
<Enabled>0</Enabled>
|
||||
<Mode>1</Mode>
|
||||
<Graph>0</Graph>
|
||||
<Symbiont>0</Symbiont>
|
||||
</DriverProfiling>
|
||||
<CallStackLog>
|
||||
<Enabled>0</Enabled>
|
||||
</CallStackLog>
|
||||
<CallStackStripe>
|
||||
<ShowTiming>1</ShowTiming>
|
||||
</CallStackStripe>
|
||||
<InterruptLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
<SumSortOrder>0</SumSortOrder>
|
||||
</InterruptLog>
|
||||
<DataLog>
|
||||
<LogEnabled>0</LogEnabled>
|
||||
<GraphEnabled>0</GraphEnabled>
|
||||
<ShowTimeLog>1</ShowTimeLog>
|
||||
<SumEnabled>0</SumEnabled>
|
||||
<ShowTimeSum>1</ShowTimeSum>
|
||||
</DataLog>
|
||||
<Interrupts>
|
||||
<Enabled>1</Enabled>
|
||||
</Interrupts>
|
||||
<MemConfig>
|
||||
<Base>1</Base>
|
||||
<Manual>0</Manual>
|
||||
<Ddf>1</Ddf>
|
||||
<TypeViol>0</TypeViol>
|
||||
<Stop>1</Stop>
|
||||
</MemConfig>
|
||||
<Trace1>
|
||||
<Enabled>0</Enabled>
|
||||
<ShowSource>1</ShowSource>
|
||||
</Trace1>
|
||||
<Simulator>
|
||||
<Freq>50000000</Freq>
|
||||
<FreqHi>0</FreqHi>
|
||||
<MultiCoreRunAll>1</MultiCoreRunAll>
|
||||
</Simulator>
|
||||
<Jet>
|
||||
<JetConnSerialNo>73866</JetConnSerialNo>
|
||||
<JetConnFoundProbes />
|
||||
<PrevWtdReset>Hardware</PrevWtdReset>
|
||||
<OnlineReset>Software</OnlineReset>
|
||||
<DisableInterrupts>0</DisableInterrupts>
|
||||
<LeaveRunning>0</LeaveRunning>
|
||||
<MultiCoreRunAll>0</MultiCoreRunAll>
|
||||
</Jet>
|
||||
<PlDriver>
|
||||
<FirstRun>0</FirstRun>
|
||||
<MemConfigValue>C:\devtools\IAR Systems\Embedded Workbench 8.3\riscv\config\debugger\SiFive\e31arty35t.ddf</MemConfigValue>
|
||||
</PlDriver>
|
||||
<RiscvDriver>
|
||||
<EnableCache>1</EnableCache>
|
||||
</RiscvDriver>
|
||||
<TermIOLog>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
</TermIOLog>
|
||||
<LogFile>
|
||||
<LoggingEnabled>_ 0</LoggingEnabled>
|
||||
<LogFile>_ ""</LogFile>
|
||||
<Category>_ 0</Category>
|
||||
</LogFile>
|
||||
<Breakpoints2>
|
||||
<Count>0</Count>
|
||||
</Breakpoints2>
|
||||
<Aliases>
|
||||
<Count>0</Count>
|
||||
<SuppressDialog>0</SuppressDialog>
|
||||
</Aliases>
|
||||
</settings>
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue