From e1a17c0d3e222e069a124d6685f69264cb06fdb7 Mon Sep 17 00:00:00 2001 From: Paul Warren Date: Thu, 11 Feb 2021 11:54:39 +1100 Subject: [PATCH] Missing implementations --- TestingMakeFile2/PSDR/Src/BlinkLed.c | 30 +++ TestingMakeFile2/PSDR/Src/Trace.c | 76 ++++++++ TestingMakeFile2/PSDR/Src/trace_impl.c | 252 +++++++++++++++++++++++++ 3 files changed, 358 insertions(+) create mode 100644 TestingMakeFile2/PSDR/Src/BlinkLed.c create mode 100644 TestingMakeFile2/PSDR/Src/Trace.c create mode 100644 TestingMakeFile2/PSDR/Src/trace_impl.c diff --git a/TestingMakeFile2/PSDR/Src/BlinkLed.c b/TestingMakeFile2/PSDR/Src/BlinkLed.c new file mode 100644 index 0000000..436342d --- /dev/null +++ b/TestingMakeFile2/PSDR/Src/BlinkLed.c @@ -0,0 +1,30 @@ +// +// This file is part of the GNU ARM Eclipse distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +#include "BlinkLed.h" + +// ---------------------------------------------------------------------------- + +void +blink_led_init() +{ + // Enable GPIO Peripheral clock + RCC->AHB1ENR |= BLINK_RCC_MASKx(BLINK_PORT_NUMBER); + + GPIO_InitTypeDef GPIO_InitStructure; + + // Configure pin in output push/pull mode + GPIO_InitStructure.Pin = BLINK_PIN_MASK(BLINK_PIN_NUMBER); + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Speed = GPIO_SPEED_FAST; + GPIO_InitStructure.Pull = GPIO_PULLUP; + HAL_GPIO_Init(BLINK_GPIOx(BLINK_PORT_NUMBER), &GPIO_InitStructure); + + // Start with led turned off + blink_led_off(); +} + + +// ---------------------------------------------------------------------------- diff --git a/TestingMakeFile2/PSDR/Src/Trace.c b/TestingMakeFile2/PSDR/Src/Trace.c new file mode 100644 index 0000000..dfc2bbe --- /dev/null +++ b/TestingMakeFile2/PSDR/Src/Trace.c @@ -0,0 +1,76 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +#if defined(TRACE) + +#include +#include +#include "diag/Trace.h" +#include "string.h" + +#ifndef OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE +#define OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE (128) +#endif + +// ---------------------------------------------------------------------------- + +int +trace_printf(const char* format, ...) +{ + int ret; + va_list ap; + + va_start (ap, format); + + // TODO: rewrite it to no longer use newlib, it is way too heavy + + static char buf[OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE]; + + // Print to the local buffer + ret = vsnprintf (buf, sizeof(buf), format, ap); + if (ret > 0) + { + // Transfer the buffer to the device + ret = trace_write (buf, (size_t)ret); + } + + va_end (ap); + return ret; +} + +int +trace_puts(const char *s) +{ + trace_write(s, strlen(s)); + return trace_write("\n", 1); +} + +int +trace_putchar(int c) +{ + trace_write((const char*)&c, 1); + return c; +} + +void +trace_dump_args(int argc, char* argv[]) +{ + trace_printf("main(argc=%d, argv=[", argc); + for (int i = 0; i < argc; ++i) + { + if (i != 0) + { + trace_printf(", "); + } + trace_printf("\"%s\"", argv[i]); + } + trace_printf("]);\n"); +} + +// ---------------------------------------------------------------------------- + +#endif // TRACE diff --git a/TestingMakeFile2/PSDR/Src/trace_impl.c b/TestingMakeFile2/PSDR/Src/trace_impl.c new file mode 100644 index 0000000..6b0092a --- /dev/null +++ b/TestingMakeFile2/PSDR/Src/trace_impl.c @@ -0,0 +1,252 @@ +// +// This file is part of the µOS++ III distribution. +// Copyright (c) 2014 Liviu Ionescu. +// + +// ---------------------------------------------------------------------------- + +#if defined(TRACE) + +//#include "cmsis_device.h" +#include "diag/Trace.h" + +// ---------------------------------------------------------------------------- + +// One of these definitions must be passed via the compiler command line +// Note: small Cortex-M0/M0+ might implement a simplified debug interface. + +//#define OS_USE_TRACE_ITM +//#define OS_USE_TRACE_SEMIHOSTING_DEBUG +//#define OS_USE_TRACE_SEMIHOSTING_STDOUT + +#if !(defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) +#if defined(OS_USE_TRACE_ITM) +#undef OS_USE_TRACE_ITM +#warning "ITM unavailable" +#endif // defined(OS_USE_TRACE_ITM) +#endif // !(defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + +#if defined(OS_DEBUG_SEMIHOSTING_FAULTS) +#if defined(OS_USE_TRACE_SEMIHOSTING_STDOUT) || defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) +#error "Cannot debug semihosting using semihosting trace; use OS_USE_TRACE_ITM" +#endif +#endif + +// ---------------------------------------------------------------------------- + +// Forward definitions. + +#if defined(OS_USE_TRACE_ITM) +static ssize_t +_trace_write_itm (const char* buf, size_t nbyte); +#endif + +#if defined(OS_USE_TRACE_SEMIHOSTING_STDOUT) +static ssize_t +_trace_write_semihosting_stdout(const char* buf, size_t nbyte); +#endif + +#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) +static ssize_t +_trace_write_semihosting_debug(const char* buf, size_t nbyte); +#endif + +// ---------------------------------------------------------------------------- + +void +trace_initialize(void) +{ + // For regular ITM / semihosting, no inits required. +} + +// ---------------------------------------------------------------------------- + +// This function is called from _write() for fd==1 or fd==2 and from some +// of the trace_* functions. + +ssize_t +trace_write (const char* buf __attribute__((unused)), + size_t nbyte __attribute__((unused))) +{ +#if defined(OS_USE_TRACE_ITM) + return _trace_write_itm (buf, nbyte); +#elif defined(OS_USE_TRACE_SEMIHOSTING_STDOUT) + return _trace_write_semihosting_stdout(buf, nbyte); +#elif defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) + return _trace_write_semihosting_debug(buf, nbyte); +#endif + + return -1; +} + +// ---------------------------------------------------------------------------- + +#if defined(OS_USE_TRACE_ITM) + +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +// ITM is the ARM standard mechanism, running over SWD/SWO on Cortex-M3/M4 +// devices, and is the recommended setting, if available. +// +// The JLink probe and the GDB server fully support SWD/SWO +// and the JLink Debugging plug-in enables it by default. +// The current OpenOCD does not include support to parse the SWO stream, +// so this configuration will not work on OpenOCD (will not crash, but +// nothing will be displayed in the output console). + +#if !defined(OS_INTEGER_TRACE_ITM_STIMULUS_PORT) +#define OS_INTEGER_TRACE_ITM_STIMULUS_PORT (0) +#endif + +static ssize_t +_trace_write_itm (const char* buf, size_t nbyte) +{ + for (size_t i = 0; i < nbyte; i++) + { + // Check if ITM or the stimulus port are not enabled + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) == 0) + || ((ITM->TER & (1UL << OS_INTEGER_TRACE_ITM_STIMULUS_PORT)) == 0)) + { + return (ssize_t)i; // return the number of sent characters (may be 0) + } + + // Wait until STIMx is ready... + while (ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u32 == 0) + ; + // then send data, one byte at a time + ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u8 = (uint8_t) (*buf++); + } + + return (ssize_t)nbyte; // all characters successfully sent +} + +#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + +#endif // OS_USE_TRACE_ITM + +// ---------------------------------------------------------------------------- + +#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) || defined(OS_USE_TRACE_SEMIHOSTING_STDOUT) + +#include "arm/semihosting.h" + +// Semihosting is the other output channel that can be used for the trace +// messages. It comes in two flavours: STDOUT and DEBUG. The STDOUT channel +// is the equivalent of the stdout in POSIX and in most cases it is forwarded +// to the GDB server stdout stream. The debug channel is a separate +// channel. STDOUT is buffered, so nothing is displayed until a \n; +// DEBUG is not buffered, but can be slow. +// +// Choosing between semihosting stdout and debug depends on the capabilities +// of your GDB server, and also on specific needs. It is recommended to test +// DEBUG first, and if too slow, try STDOUT. +// +// The JLink GDB server fully support semihosting, and both configurations +// are available; to activate it, use "monitor semihosting enable" or check +// the corresponding button in the JLink Debugging plug-in. +// In OpenOCD, support for semihosting can be enabled using +// "monitor arm semihosting enable". +// +// Note: Applications built with semihosting output active normally cannot +// be executed without the debugger connected and active, since they use +// BKPT to communicate with the host. However, with a carefully written +// HardFault_Handler, the semihosting BKPT calls can be processed, making +// possible to run semihosting applications as standalone, without being +// terminated with hardware faults. + +#endif // OS_USE_TRACE_SEMIHOSTING_DEBUG_* + +// ---------------------------------------------------------------------------- + +#if defined(OS_USE_TRACE_SEMIHOSTING_STDOUT) + +static ssize_t +_trace_write_semihosting_stdout (const char* buf, size_t nbyte) +{ + static int handle; + void* block[3]; + int ret; + + if (handle == 0) + { + // On the first call get the file handle from the host + block[0] = ":tt"; // special filename to be used for stdin/out/err + block[1] = (void*) 4; // mode "w" + // length of ":tt", except null terminator + block[2] = (void*) (sizeof(":tt") - 1); + + ret = call_host (SEMIHOSTING_SYS_OPEN, (void*) block); + if (ret == -1) + return -1; + + handle = ret; + } + + block[0] = (void*) handle; + block[1] = (void*) buf; + block[2] = (void*) nbyte; + // send character array to host file/device + ret = call_host (SEMIHOSTING_SYS_WRITE, (void*) block); + // this call returns the number of bytes NOT written (0 if all ok) + + // -1 is not a legal value, but SEGGER seems to return it + if (ret == -1) + return -1; + + // The compliant way of returning errors + if (ret == (int) nbyte) + return -1; + + // Return the number of bytes written + return (ssize_t) (nbyte) - (ssize_t) ret; +} + +#endif // OS_USE_TRACE_SEMIHOSTING_STDOUT + +// ---------------------------------------------------------------------------- + +#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) + +#define OS_INTEGER_TRACE_TMP_ARRAY_SIZE (16) + +static ssize_t +_trace_write_semihosting_debug (const char* buf, size_t nbyte) +{ + // Since the single character debug channel is quite slow, try to + // optimise and send a null terminated string, if possible. + if (buf[nbyte] == '\0') + { + // send string + call_host (SEMIHOSTING_SYS_WRITE0, (void*) buf); + } + else + { + // If not, use a local buffer to speed things up + char tmp[OS_INTEGER_TRACE_TMP_ARRAY_SIZE]; + size_t togo = nbyte; + while (togo > 0) + { + unsigned int n = ((togo < sizeof(tmp)) ? togo : sizeof(tmp)); + unsigned int i = 0; + for (; i < n; ++i, ++buf) + { + tmp[i] = *buf; + } + tmp[i] = '\0'; + + call_host (SEMIHOSTING_SYS_WRITE0, (void*) tmp); + + togo -= n; + } + } + + // All bytes written + return (ssize_t) nbyte; +} + +#endif // OS_USE_TRACE_SEMIHOSTING_DEBUG + +#endif // TRACE + +// ---------------------------------------------------------------------------- +