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