diff --git a/CMSIS-DAP/RTOS2/Include/cmsis_os2.h b/CMSIS-DAP/RTOS2/Include/cmsis_os2.h new file mode 100644 index 0000000..76612e2 --- /dev/null +++ b/CMSIS-DAP/RTOS2/Include/cmsis_os2.h @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2013-2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 12. June 2020 + * $Revision: V2.1.3 + * + * Project: CMSIS-RTOS2 API + * Title: cmsis_os2.h header file + * + * Version 2.1.3 + * Additional functions allowed to be called from Interrupt Service Routines: + * - osThreadGetId + * Version 2.1.2 + * Additional functions allowed to be called from Interrupt Service Routines: + * - osKernelGetInfo, osKernelGetState + * Version 2.1.1 + * Additional functions allowed to be called from Interrupt Service Routines: + * - osKernelGetTickCount, osKernelGetTickFreq + * Changed Kernel Tick type to uint32_t: + * - updated: osKernelGetTickCount, osDelayUntil + * Version 2.1.0 + * Support for critical and uncritical sections (nesting safe): + * - updated: osKernelLock, osKernelUnlock + * - added: osKernelRestoreLock + * Updated Thread and Event Flags: + * - changed flags parameter and return type from int32_t to uint32_t + * Version 2.0.0 + * Initial Release + *---------------------------------------------------------------------------*/ + +#ifndef CMSIS_OS2_H_ +#define CMSIS_OS2_H_ + +#ifndef __NO_RETURN +#if defined(__CC_ARM) +#define __NO_RETURN __declspec(noreturn) +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +#define __NO_RETURN __attribute__((__noreturn__)) +#elif defined(__GNUC__) +#define __NO_RETURN __attribute__((__noreturn__)) +#elif defined(__ICCARM__) +#define __NO_RETURN __noreturn +#else +#define __NO_RETURN +#endif +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + +// ==== Enumerations, structures, defines ==== + +/// Version information. +typedef struct { + uint32_t api; ///< API version (major.minor.rev: mmnnnrrrr dec). + uint32_t kernel; ///< Kernel version (major.minor.rev: mmnnnrrrr dec). +} osVersion_t; + +/// Kernel state. +typedef enum { + osKernelInactive = 0, ///< Inactive. + osKernelReady = 1, ///< Ready. + osKernelRunning = 2, ///< Running. + osKernelLocked = 3, ///< Locked. + osKernelSuspended = 4, ///< Suspended. + osKernelError = -1, ///< Error. + osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osKernelState_t; + +/// Thread state. +typedef enum { + osThreadInactive = 0, ///< Inactive. + osThreadReady = 1, ///< Ready. + osThreadRunning = 2, ///< Running. + osThreadBlocked = 3, ///< Blocked. + osThreadTerminated = 4, ///< Terminated. + osThreadError = -1, ///< Error. + osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osThreadState_t; + +/// Priority values. +typedef enum { + osPriorityNone = 0, ///< No priority (not initialized). + osPriorityIdle = 1, ///< Reserved for Idle thread. + osPriorityLow = 8, ///< Priority: low + osPriorityLow1 = 8+1, ///< Priority: low + 1 + osPriorityLow2 = 8+2, ///< Priority: low + 2 + osPriorityLow3 = 8+3, ///< Priority: low + 3 + osPriorityLow4 = 8+4, ///< Priority: low + 4 + osPriorityLow5 = 8+5, ///< Priority: low + 5 + osPriorityLow6 = 8+6, ///< Priority: low + 6 + osPriorityLow7 = 8+7, ///< Priority: low + 7 + osPriorityBelowNormal = 16, ///< Priority: below normal + osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1 + osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2 + osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3 + osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4 + osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5 + osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6 + osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7 + osPriorityNormal = 24, ///< Priority: normal + osPriorityNormal1 = 24+1, ///< Priority: normal + 1 + osPriorityNormal2 = 24+2, ///< Priority: normal + 2 + osPriorityNormal3 = 24+3, ///< Priority: normal + 3 + osPriorityNormal4 = 24+4, ///< Priority: normal + 4 + osPriorityNormal5 = 24+5, ///< Priority: normal + 5 + osPriorityNormal6 = 24+6, ///< Priority: normal + 6 + osPriorityNormal7 = 24+7, ///< Priority: normal + 7 + osPriorityAboveNormal = 32, ///< Priority: above normal + osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1 + osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2 + osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3 + osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4 + osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5 + osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6 + osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7 + osPriorityHigh = 40, ///< Priority: high + osPriorityHigh1 = 40+1, ///< Priority: high + 1 + osPriorityHigh2 = 40+2, ///< Priority: high + 2 + osPriorityHigh3 = 40+3, ///< Priority: high + 3 + osPriorityHigh4 = 40+4, ///< Priority: high + 4 + osPriorityHigh5 = 40+5, ///< Priority: high + 5 + osPriorityHigh6 = 40+6, ///< Priority: high + 6 + osPriorityHigh7 = 40+7, ///< Priority: high + 7 + osPriorityRealtime = 48, ///< Priority: realtime + osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1 + osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2 + osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3 + osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4 + osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5 + osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6 + osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7 + osPriorityISR = 56, ///< Reserved for ISR deferred thread. + osPriorityError = -1, ///< System cannot determine priority or illegal priority. + osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osPriority_t; + +/// Entry point of a thread. +typedef void (*osThreadFunc_t) (void *argument); + +/// Timer callback function. +typedef void (*osTimerFunc_t) (void *argument); + +/// Timer type. +typedef enum { + osTimerOnce = 0, ///< One-shot timer. + osTimerPeriodic = 1 ///< Repeating timer. +} osTimerType_t; + +// Timeout value. +#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. + +// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait). +#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). +#define osFlagsWaitAll 0x00000001U ///< Wait for all flags. +#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. + +// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). +#define osFlagsError 0x80000000U ///< Error indicator. +#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). +#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2). +#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). +#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). +#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). + +// Thread attributes (attr_bits in \ref osThreadAttr_t). +#define osThreadDetached 0x00000000U ///< Thread created in detached mode (default) +#define osThreadJoinable 0x00000001U ///< Thread created in joinable mode + +// Mutex attributes (attr_bits in \ref osMutexAttr_t). +#define osMutexRecursive 0x00000001U ///< Recursive mutex. +#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol. +#define osMutexRobust 0x00000008U ///< Robust mutex. + +/// Status code values returned by CMSIS-RTOS functions. +typedef enum { + osOK = 0, ///< Operation completed successfully. + osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits. + osErrorTimeout = -2, ///< Operation not completed within the timeout period. + osErrorResource = -3, ///< Resource not available. + osErrorParameter = -4, ///< Parameter error. + osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. + osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. + osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osStatus_t; + + +/// \details Thread ID identifies the thread. +typedef void *osThreadId_t; + +/// \details Timer ID identifies the timer. +typedef void *osTimerId_t; + +/// \details Event Flags ID identifies the event flags. +typedef void *osEventFlagsId_t; + +/// \details Mutex ID identifies the mutex. +typedef void *osMutexId_t; + +/// \details Semaphore ID identifies the semaphore. +typedef void *osSemaphoreId_t; + +/// \details Memory Pool ID identifies the memory pool. +typedef void *osMemoryPoolId_t; + +/// \details Message Queue ID identifies the message queue. +typedef void *osMessageQueueId_t; + + +#ifndef TZ_MODULEID_T +#define TZ_MODULEID_T +/// \details Data type that identifies secure software modules called by a process. +typedef uint32_t TZ_ModuleId_t; +#endif + + +/// Attributes structure for thread. +typedef struct { + const char *name; ///< name of the thread + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block + void *stack_mem; ///< memory for stack + uint32_t stack_size; ///< size of stack + osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) + TZ_ModuleId_t tz_module; ///< TrustZone module identifier + uint32_t reserved; ///< reserved (must be 0) +} osThreadAttr_t; + +/// Attributes structure for timer. +typedef struct { + const char *name; ///< name of the timer + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osTimerAttr_t; + +/// Attributes structure for event flags. +typedef struct { + const char *name; ///< name of the event flags + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osEventFlagsAttr_t; + +/// Attributes structure for mutex. +typedef struct { + const char *name; ///< name of the mutex + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osMutexAttr_t; + +/// Attributes structure for semaphore. +typedef struct { + const char *name; ///< name of the semaphore + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osSemaphoreAttr_t; + +/// Attributes structure for memory pool. +typedef struct { + const char *name; ///< name of the memory pool + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block + void *mp_mem; ///< memory for data storage + uint32_t mp_size; ///< size of provided memory for data storage +} osMemoryPoolAttr_t; + +/// Attributes structure for message queue. +typedef struct { + const char *name; ///< name of the message queue + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block + void *mq_mem; ///< memory for data storage + uint32_t mq_size; ///< size of provided memory for data storage +} osMessageQueueAttr_t; + + +// ==== Kernel Management Functions ==== + +/// Initialize the RTOS Kernel. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelInitialize (void); + +/// Get RTOS Kernel Information. +/// \param[out] version pointer to buffer for retrieving version information. +/// \param[out] id_buf pointer to buffer for retrieving kernel identification string. +/// \param[in] id_size size of buffer for kernel identification string. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size); + +/// Get the current RTOS Kernel state. +/// \return current RTOS Kernel state. +osKernelState_t osKernelGetState (void); + +/// Start the RTOS Kernel scheduler. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelStart (void); + +/// Lock the RTOS Kernel scheduler. +/// \return previous lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelLock (void); + +/// Unlock the RTOS Kernel scheduler. +/// \return previous lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelUnlock (void); + +/// Restore the RTOS Kernel scheduler lock state. +/// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock. +/// \return new lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelRestoreLock (int32_t lock); + +/// Suspend the RTOS Kernel scheduler. +/// \return time in ticks, for how long the system can sleep or power-down. +uint32_t osKernelSuspend (void); + +/// Resume the RTOS Kernel scheduler. +/// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode. +void osKernelResume (uint32_t sleep_ticks); + +/// Get the RTOS kernel tick count. +/// \return RTOS kernel current tick count. +uint32_t osKernelGetTickCount (void); + +/// Get the RTOS kernel tick frequency. +/// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second. +uint32_t osKernelGetTickFreq (void); + +/// Get the RTOS kernel system timer count. +/// \return RTOS kernel current system timer count as 32-bit value. +uint32_t osKernelGetSysTimerCount (void); + +/// Get the RTOS kernel system timer frequency. +/// \return frequency of the system timer in hertz, i.e. timer ticks per second. +uint32_t osKernelGetSysTimerFreq (void); + + +// ==== Thread Management Functions ==== + +/// Create a thread and add it to Active Threads. +/// \param[in] func thread function. +/// \param[in] argument pointer that is passed to the thread function as start argument. +/// \param[in] attr thread attributes; NULL: default values. +/// \return thread ID for reference by other functions or NULL in case of error. +osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); + +/// Get name of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return name as null-terminated string. +const char *osThreadGetName (osThreadId_t thread_id); + +/// Return the thread ID of the current running thread. +/// \return thread ID for reference by other functions or NULL in case of error. +osThreadId_t osThreadGetId (void); + +/// Get current thread state of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return current thread state of the specified thread. +osThreadState_t osThreadGetState (osThreadId_t thread_id); + +/// Get stack size of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return stack size in bytes. +uint32_t osThreadGetStackSize (osThreadId_t thread_id); + +/// Get available stack space of a thread based on stack watermark recording during execution. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return remaining stack space in bytes. +uint32_t osThreadGetStackSpace (osThreadId_t thread_id); + +/// Change priority of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \param[in] priority new priority value for the thread function. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority); + +/// Get current priority of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return current priority value of the specified thread. +osPriority_t osThreadGetPriority (osThreadId_t thread_id); + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadYield (void); + +/// Suspend execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadSuspend (osThreadId_t thread_id); + +/// Resume execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadResume (osThreadId_t thread_id); + +/// Detach a thread (thread storage can be reclaimed when thread terminates). +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadDetach (osThreadId_t thread_id); + +/// Wait for specified thread to terminate. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadJoin (osThreadId_t thread_id); + +/// Terminate execution of current running thread. +__NO_RETURN void osThreadExit (void); + +/// Terminate execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadTerminate (osThreadId_t thread_id); + +/// Get number of active threads. +/// \return number of active threads. +uint32_t osThreadGetCount (void); + +/// Enumerate active threads. +/// \param[out] thread_array pointer to array for retrieving thread IDs. +/// \param[in] array_items maximum number of items in array for retrieving thread IDs. +/// \return number of enumerated threads. +uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items); + + +// ==== Thread Flags Functions ==== + +/// Set the specified Thread Flags of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \param[in] flags specifies the flags of the thread that shall be set. +/// \return thread flags after setting or error code if highest bit set. +uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags); + +/// Clear the specified Thread Flags of current running thread. +/// \param[in] flags specifies the flags of the thread that shall be cleared. +/// \return thread flags before clearing or error code if highest bit set. +uint32_t osThreadFlagsClear (uint32_t flags); + +/// Get the current Thread Flags of current running thread. +/// \return current thread flags. +uint32_t osThreadFlagsGet (void); + +/// Wait for one or more Thread Flags of the current running thread to become signaled. +/// \param[in] flags specifies the flags to wait for. +/// \param[in] options specifies flags options (osFlagsXxxx). +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return thread flags before clearing or error code if highest bit set. +uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout); + + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay). +/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value +/// \return status code that indicates the execution status of the function. +osStatus_t osDelay (uint32_t ticks); + +/// Wait until specified time. +/// \param[in] ticks absolute time in ticks +/// \return status code that indicates the execution status of the function. +osStatus_t osDelayUntil (uint32_t ticks); + + +// ==== Timer Management Functions ==== + +/// Create and Initialize a timer. +/// \param[in] func function pointer to callback function. +/// \param[in] type \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic behavior. +/// \param[in] argument argument to the timer callback function. +/// \param[in] attr timer attributes; NULL: default values. +/// \return timer ID for reference by other functions or NULL in case of error. +osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr); + +/// Get name of a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return name as null-terminated string. +const char *osTimerGetName (osTimerId_t timer_id); + +/// Start or restart a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks); + +/// Stop a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerStop (osTimerId_t timer_id); + +/// Check if a timer is running. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return 0 not running, 1 running. +uint32_t osTimerIsRunning (osTimerId_t timer_id); + +/// Delete a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerDelete (osTimerId_t timer_id); + + +// ==== Event Flags Management Functions ==== + +/// Create and Initialize an Event Flags object. +/// \param[in] attr event flags attributes; NULL: default values. +/// \return event flags ID for reference by other functions or NULL in case of error. +osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr); + +/// Get name of an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return name as null-terminated string. +const char *osEventFlagsGetName (osEventFlagsId_t ef_id); + +/// Set the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be set. +/// \return event flags after setting or error code if highest bit set. +uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags); + +/// Clear the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be cleared. +/// \return event flags before clearing or error code if highest bit set. +uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags); + +/// Get the current Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return current event flags. +uint32_t osEventFlagsGet (osEventFlagsId_t ef_id); + +/// Wait for one or more Event Flags to become signaled. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags to wait for. +/// \param[in] options specifies flags options (osFlagsXxxx). +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return event flags before clearing or error code if highest bit set. +uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout); + +/// Delete an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id); + + +// ==== Mutex Management Functions ==== + +/// Create and Initialize a Mutex object. +/// \param[in] attr mutex attributes; NULL: default values. +/// \return mutex ID for reference by other functions or NULL in case of error. +osMutexId_t osMutexNew (const osMutexAttr_t *attr); + +/// Get name of a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return name as null-terminated string. +const char *osMutexGetName (osMutexId_t mutex_id); + +/// Acquire a Mutex or timeout if it is locked. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout); + +/// Release a Mutex that was acquired by \ref osMutexAcquire. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexRelease (osMutexId_t mutex_id); + +/// Get Thread which owns a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return thread ID of owner thread or NULL when mutex was not acquired. +osThreadId_t osMutexGetOwner (osMutexId_t mutex_id); + +/// Delete a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexDelete (osMutexId_t mutex_id); + + +// ==== Semaphore Management Functions ==== + +/// Create and Initialize a Semaphore object. +/// \param[in] max_count maximum number of available tokens. +/// \param[in] initial_count initial number of available tokens. +/// \param[in] attr semaphore attributes; NULL: default values. +/// \return semaphore ID for reference by other functions or NULL in case of error. +osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr); + +/// Get name of a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return name as null-terminated string. +const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id); + +/// Acquire a Semaphore token or timeout if no tokens are available. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout); + +/// Release a Semaphore token up to the initial maximum count. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id); + +/// Get current Semaphore token count. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return number of tokens available. +uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id); + +/// Delete a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id); + + +// ==== Memory Pool Management Functions ==== + +/// Create and Initialize a Memory Pool object. +/// \param[in] block_count maximum number of memory blocks in memory pool. +/// \param[in] block_size memory block size in bytes. +/// \param[in] attr memory pool attributes; NULL: default values. +/// \return memory pool ID for reference by other functions or NULL in case of error. +osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr); + +/// Get name of a Memory Pool object. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return name as null-terminated string. +const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id); + +/// Allocate a memory block from a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return address of the allocated memory block or NULL in case of no memory is available. +void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout); + +/// Return an allocated memory block back to a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \param[in] block address of the allocated memory block to be returned to the memory pool. +/// \return status code that indicates the execution status of the function. +osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block); + +/// Get maximum number of memory blocks in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return maximum number of memory blocks. +uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id); + +/// Get memory block size in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return memory block size in bytes. +uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id); + +/// Get number of memory blocks used in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return number of memory blocks used. +uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id); + +/// Get number of memory blocks available in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return number of memory blocks available. +uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id); + +/// Delete a Memory Pool object. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id); + + +// ==== Message Queue Management Functions ==== + +/// Create and Initialize a Message Queue object. +/// \param[in] msg_count maximum number of messages in queue. +/// \param[in] msg_size maximum message size in bytes. +/// \param[in] attr message queue attributes; NULL: default values. +/// \return message queue ID for reference by other functions or NULL in case of error. +osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); + +/// Get name of a Message Queue object. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return name as null-terminated string. +const char *osMessageQueueGetName (osMessageQueueId_t mq_id); + +/// Put a Message into a Queue or timeout if Queue is full. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \param[in] msg_ptr pointer to buffer with message to put into a queue. +/// \param[in] msg_prio message priority. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout); + +/// Get a Message from a Queue or timeout if Queue is empty. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \param[out] msg_ptr pointer to buffer for message to get from a queue. +/// \param[out] msg_prio pointer to buffer for message priority or NULL. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout); + +/// Get maximum number of messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return maximum number of messages. +uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id); + +/// Get maximum message size in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return maximum message size in bytes. +uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id); + +/// Get number of queued messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return number of queued messages. +uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id); + +/// Get number of available slots for messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return number of available slots for messages. +uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id); + +/// Reset a Message Queue to initial empty state. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id); + +/// Delete a Message Queue object. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id); + + +#ifdef __cplusplus +} +#endif + +#endif // CMSIS_OS2_H_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5459631..b620639 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Firmware/Source/DAP_vendor.c ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Firmware/Source/SWO.c ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Firmware/Source/SW_DP.c + ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Firmware/Source/UART.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/unique.c ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/alloc.c @@ -80,6 +81,7 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/m_sump/_sump.c ${CMAKE_CURRENT_SOURCE_DIR}/src/m_sump/cdc_sump.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/cdc_uart.c + ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_uart.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/dap_swo.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/i2c_tinyusb.c ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_default/spi_serprog.c @@ -98,6 +100,7 @@ target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Firmware/Include/ ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Core/Include/ ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/Driver/Include/ + ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS-DAP/RTOS2/Include/ ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/ ${CMAKE_CURRENT_SOURCE_DIR}/bsp/default/ ) diff --git a/bsp/rp2040/DAP_config.h b/bsp/rp2040/DAP_config.h index acfb9c3..1dc3f89 100644 --- a/bsp/rp2040/DAP_config.h +++ b/bsp/rp2040/DAP_config.h @@ -150,10 +150,10 @@ This information includes: /// Indicate that UART Communication Port is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define DAP_UART 0 ///< DAP UART: 1 = available, 0 = not available. +#define DAP_UART 1 ///< DAP UART: 1 = available, 0 = not available. /// USART Driver instance number for the UART Communication Port. -#define DAP_UART_DRIVER 0 ///< USART Driver instance number (Driver_USART#). +#define DAP_UART_DRIVER _DAPFAKE ///< USART Driver instance number (Driver_USART#). /// UART Receive Buffer Size. #define DAP_UART_RX_BUFFER_SIZE 64U ///< Uart Receive Buffer Size in bytes (must be 2^n). diff --git a/bsp/rp2040/m_default/cdc_uart.c b/bsp/rp2040/m_default/cdc_uart.c index 7850efe..f9e760e 100644 --- a/bsp/rp2040/m_default/cdc_uart.c +++ b/bsp/rp2040/m_default/cdc_uart.c @@ -61,6 +61,8 @@ void cdc_uart_deinit(void) { } void cdc_uart_task(void) { + if (cdc_uart_dap_override) return; + // Consume uart fifo regardless even if not connected uint rx_len = 0; while (uart_is_readable(PINOUT_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) { diff --git a/bsp/rp2040/m_default/dap_uart.c b/bsp/rp2040/m_default/dap_uart.c new file mode 100644 index 0000000..6dc52c9 --- /dev/null +++ b/bsp/rp2040/m_default/dap_uart.c @@ -0,0 +1,290 @@ +// vim: set et: + +#include "DAP_config.h" +#include "DAP.h" + +#include +#include +#include +#include + +#include "Driver_USART.h" + +#include "m_default/bsp-feature.h" +#include "m_default/pinout.h" +#include "m_default/cdc.h" + +bool cdc_uart_dap_override = false; + +static int rxdmach = -1, txdmach = -1; +static ARM_USART_SignalEvent_t irq_callback = NULL; + +static void dap_uart_dma_isr() { + uint32_t ints = dma_hw->ints0; + uint32_t events = 0; + + if (ints & (1u << rxdmach)) { + dma_hw->ints0 = 1u << rxdmach; + events |= ARM_USART_EVENT_RECEIVE_COMPLETE; + } + if (ints & (1u << txdmach)) { + dma_hw->ints0 = 1u << txdmach; + events |= ARM_USART_EVENT_SEND_COMPLETE; + } + + if (events && irq_callback) irq_callback(events); +} + +static void dap_uart_err_isr() { + uint32_t mis = uart_get_hw(PINOUT_UART_INTERFACE)->mis; + uint32_t events = 0; + + if (mis & UART_UARTMIS_OEMIS_BITS) { + uart_get_hw(PINOUT_UART_INTERFACE)->icr = UART_UARTICR_OEIC_BITS; + events |= ARM_USART_EVENT_RX_OVERFLOW; + } + if (mis & UART_UARTMIS_PEMIS_BITS) { + uart_get_hw(PINOUT_UART_INTERFACE)->icr = UART_UARTICR_PEIC_BITS; + events |= ARM_USART_EVENT_RX_PARITY_ERROR; + } + if (mis & UART_UARTMIS_FEMIS_BITS) { + uart_get_hw(PINOUT_UART_INTERFACE)->icr = UART_UARTICR_FEIC_BITS; + events |= ARM_USART_EVENT_RX_FRAMING_ERROR; + } + + if (events && irq_callback) irq_callback(events); +} + +static int32_t dap_uart_initialize(ARM_USART_SignalEvent_t cb) { + if (cdc_uart_dap_override) return ARM_DRIVER_ERROR; + + cdc_uart_dap_override = true; + irq_callback = cb; + // TODO: do anything? + // cdc_uart.c probably has already inited (otherwise stuff is broken), + // so we don't really have to do anything else here + // TODO: cb needs to be called on: + // * send() complete + // * receive() complete + // * rx overflow + // * rx framing error + // * rx parity error + // + // USB timeout is one second. for a good implementation, we'd want to use + // DMA to do the UART transfers in the background, but, laziness. so we do + // it in a blocking way in send/receive, and then immediately afterwards do + // the callback (instead of requiring irq stuff). gettxcount and getrxcount + // then always return the last num values + // ... except that doesn't work for receive FIFOs... welp + + rxdmach = dma_claim_unused_channel(false); + if (rxdmach == -1) return ARM_DRIVER_ERROR; + txdmach = dma_claim_unused_channel(false); + if (txdmach == -1) { + dma_channel_unclaim(rxdmach); + rxdmach = -1; + return ARM_DRIVER_ERROR; + } + + // make DMAing to/from UART possible + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->dmacr, + UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS + ); + // set error interrupt bits CMSIS-DAP wants + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->imsc, + UART_UARTIMSC_OEIM_BITS | UART_UARTIMSC_PEIM_BITS + | UART_UARTIMSC_FEIM_BITS + ); + + // start disabled + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, + UART_UARTCR_RXE_BITS | UART_UARTCR_TXE_BITS + ); + + irq_set_enabled(DMA_IRQ_0, false); + irq_set_enabled(UART1_IRQ, false); + irq_add_shared_handler(DMA_IRQ_0, dap_uart_dma_isr, + PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_add_shared_handler(UART1_IRQ, dap_uart_err_isr, + PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); + irq_set_enabled(UART1_IRQ, true); + irq_set_enabled(DMA_IRQ_0, true); + + return ARM_DRIVER_OK; +} +static int32_t dap_uart_uninitialize(void) { + // Control() may have disabled some stuff, so were going to reenable it now + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, + UART_UARTCR_RXE_BITS | UART_UARTCR_TXE_BITS + ); + + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->imsc, + UART_UARTIMSC_OEIM_BITS | UART_UARTIMSC_PEIM_BITS + | UART_UARTIMSC_FEIM_BITS + ); + + irq_set_enabled(UART1_IRQ, false); + irq_set_enabled(DMA_IRQ_0, false); + irq_remove_handler(UART1_IRQ, dap_uart_err_isr); + irq_remove_handler(DMA_IRQ_0, dap_uart_dma_isr); + + dma_channel_abort(rxdmach); + dma_channel_abort(txdmach); + + dma_channel_unclaim(rxdmach); + dma_channel_unclaim(txdmach); + + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->dmacr, + UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS + ); + + cdc_uart_dap_override = false; + return ARM_DRIVER_OK; +} +static int32_t dap_uart_powercontrol(ARM_POWER_STATE state) { + (void)state; // let's ignore that + return ARM_DRIVER_OK; +} + +// DAP/Firmware/Source/UART.c doesn't use these, so let's not implement them +static ARM_DRIVER_VERSION dap_uart_getversion(void) { + panic("dap_uart: GetVersion: not impl"); + __builtin_unreachable(); +} +static ARM_USART_CAPABILITIES dap_uart_getcapabilities(void) { + panic("dap_uart: GetCapabilities: not impl"); + __builtin_unreachable(); +} +static int32_t dap_uart_transfer(const void* out, void* in, uint32_t n) { + (void)out; (void)in; (void)n; + panic("dap_uart: Transfer: not impl"); + __builtin_unreachable(); +} +static ARM_USART_STATUS dap_uart_getstatus(void) { + panic("dap_uart: GetStatus: not impl"); + __builtin_unreachable(); +} +static int32_t dap_uart_setmodemcontrol(ARM_USART_MODEM_CONTROL mctl) { + (void)mctl; + panic("dap_uart: SetModemControl: not impl"); + __builtin_unreachable(); +} +static ARM_USART_MODEM_STATUS dap_uart_getmodemstatus(void) { + panic("dap_uart: GetModemStatus: not impl"); + __builtin_unreachable(); +} + +// actual useful stuff now +int32_t dap_uart_send(const void* data, uint32_t num) { + dma_channel_config dcfg = dma_channel_get_default_config(txdmach); + channel_config_set_read_increment(&dcfg, true); + channel_config_set_write_increment(&dcfg, false); + channel_config_set_dreq(&dcfg, DREQ_UART1_TX); + channel_config_set_transfer_data_size(&dcfg, DMA_SIZE_8); + dma_irqn_set_channel_enabled(0, txdmach, true); + dma_channel_configure(txdmach, &dcfg, + &uart_get_hw(PINOUT_UART_INTERFACE)->dr, data, num, true); + + return ARM_DRIVER_OK; +} +int32_t dap_uart_receive(void* data, uint32_t num) { + dma_channel_config dcfg = dma_channel_get_default_config(rxdmach); + channel_config_set_read_increment(&dcfg, false); + channel_config_set_write_increment(&dcfg, true); + channel_config_set_dreq(&dcfg, DREQ_UART1_RX); + channel_config_set_transfer_data_size(&dcfg, DMA_SIZE_8); + dma_irqn_set_channel_enabled(0, rxdmach, true); + dma_channel_configure(rxdmach, &dcfg, data, + &uart_get_hw(PINOUT_UART_INTERFACE)->dr, num, true); + + return ARM_DRIVER_OK; +} +uint32_t dap_uart_gettxcount(void) { // gets number of bytes transmitted of send() call + return dma_channel_hw_addr(txdmach)->transfer_count; +} +uint32_t dap_uart_getrxcount(void) { // gets number of bytes received of receive() call + return dma_channel_hw_addr(rxdmach)->transfer_count; +} + +int32_t dap_uart_control(uint32_t control, uint32_t arg) { + // ARM_USART_CONTROL_RX 1/0 + // ARM_USART_CONTROL_TX 1/0 + // ARM_USART_ABORT_RECEIVE x + // ARM_USART_ABORT_SEND x + // control ARM_USART_MODE_ASYNCHRONOUS, ARM_USART_FLOW_CONTROL_NONE (ignore this) baudrate! + // control: + // Bit 3..0: Data bits: 5 = 5 Data bits, 6 = 6 Data bits, 7 = 7 Data bits, 0 = 8 Data bits + // Bit 5..4: Parity: 0 = None, 1 = Even, 2 = Odd + // Bit 7..6: Stop bits: 0 = 1 Stop bit, 1 = 2 Stop bits + + if (control == ARM_USART_CONTROL_RX) { + if (arg) + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, UART_UARTCR_RXE_BITS); + else + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, UART_UARTCR_RXE_BITS); + } else if (control == ARM_USART_CONTROL_TX) { + if (arg) + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, UART_UARTCR_TXE_BITS); + else + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, UART_UARTCR_TXE_BITS); + } else if (control == ARM_USART_ABORT_SEND) { + dma_channel_abort(txdmach); + } else if (control == ARM_USART_ABORT_RECEIVE) { + dma_channel_abort(rxdmach); + } else if (control & ARM_USART_MODE_ASYNCHRONOUS) { + // for now, don't set some stuff as it can sometimes be a bit borked + // with the rp2040 uart(?): parity, stop, data bits + + uint32_t crv = uart_get_hw(PINOUT_UART_INTERFACE)->cr + & (UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS | UART_UARTCR_UARTEN_BITS); + + // disable interrupts for a moment so that flushing the FIFOs won't + // suddenly cause spurious interrupts + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->imsc, + UART_UARTIMSC_OEIM_BITS | UART_UARTIMSC_PEIM_BITS + | UART_UARTIMSC_FEIM_BITS + ); + + // disable momentarily + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, crv); + hw_clear_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->lcr_h, UART_UARTLCR_H_FEN_BITS); // clears the FIFO(?) + + uart_set_baudrate(PINOUT_UART_INTERFACE, arg); + + // reenable + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->lcr_h, UART_UARTLCR_H_FEN_BITS); + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->cr, crv); + hw_set_bits(&uart_get_hw(PINOUT_UART_INTERFACE)->imsc, + UART_UARTIMSC_OEIM_BITS | UART_UARTIMSC_PEIM_BITS + | UART_UARTIMSC_FEIM_BITS + ); + } + + return ARM_DRIVER_OK; +} + +extern ARM_DRIVER_USART Driver_USART_DAPFAKE; +ARM_DRIVER_USART Driver_USART_DAPFAKE = { + .GetVersion = dap_uart_getversion, // nop + .GetCapabilities = dap_uart_getcapabilities, // nop + + .Initialize = dap_uart_initialize, + .Uninitialize = dap_uart_uninitialize, + .PowerControl = dap_uart_powercontrol, + + .Send = dap_uart_send, + .Receive = dap_uart_receive, + .Transfer = dap_uart_transfer, // nop + + .GetTxCount = dap_uart_gettxcount, + .GetRxCount = dap_uart_getrxcount, + + .Control = dap_uart_control, + .GetStatus = dap_uart_getstatus, // nop + .SetModemControl = dap_uart_setmodemcontrol, // nop + .GetModemStatus = dap_uart_getmodemstatus // nop +}; + +// USB-CDC stuff +uint8_t USB_COM_PORT_Activate(uint32_t _) { (void)_; return 0; } + diff --git a/bsp/rp2040/m_default/pinout.h b/bsp/rp2040/m_default/pinout.h index ebfcd0c..a21da43 100644 --- a/bsp/rp2040/m_default/pinout.h +++ b/bsp/rp2040/m_default/pinout.h @@ -1,4 +1,4 @@ -// vim: set et: +// vim: set et ts=8: #ifndef PINOUT_H_ #define PINOUT_H_ @@ -47,5 +47,33 @@ #endif #endif /* PICOPROBE_LED */ +/* + * HARDWARE RESOURCE USAGE: + * + * IRQ: + * DMA0 DAP-UART + * UART1 DAP-UART + * + * DMA: (max. 12) + * DAP-UART 2 + * SWO-UART 1 + * SWO-MC 1 + * + * PIO: + * + * UART0: stdio + * + * UART1: USB-CDC/DAP-UART + * + * SPI: + * 1: SPI access + * + * I2C: + * 0: I2C access + * + * ADC: + * + */ + #endif diff --git a/src/m_default/cdc.h b/src/m_default/cdc.h index 75b3d54..cf0cd96 100644 --- a/src/m_default/cdc.h +++ b/src/m_default/cdc.h @@ -6,6 +6,9 @@ /* BSP function prototypes for various USB-CDC interfaces */ #ifdef DBOARD_HAS_UART +// if true, communicating thru CMSIS-DAP instead, so don't do USB stuff +extern bool cdc_uart_dap_override; + void cdc_uart_init(void); void cdc_uart_deinit(void); void cdc_uart_task(void);