Skip to content

Commit

Permalink
Final changes for the first round of reviews.
Browse files Browse the repository at this point in the history
  • Loading branch information
aclowmclaughlin committed Nov 9, 2024
1 parent f9654c6 commit 9d27e98
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 228 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ if(USE_RTOS)
src/core/rtos/Queue.cpp
src/core/rtos/Semaphore.cpp
src/core/rtos/Threadx.cpp
src/core/rtos/UARTTX.cpp
src/core/rtos/tsio/ThreadUART.cpp
)
endif()

Expand Down
121 changes: 64 additions & 57 deletions include/core/rtos/UARTTX.hpp → include/core/rtos/tsio/ThreadUART.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef EVT_TX_UART_H
#define EVT_TX_UART_H
#ifndef _EVT_THREAD_UART_
#define _EVT_THREAD_UART_

#include <HALf4/stm32f4xx.h>
#include <core/io/UART.hpp>
Expand All @@ -14,32 +14,32 @@

// All defines wrapped in ifndefs so we can set them externally.

#ifndef UARTTX_QUEUE_MESSAGE_SIZE
#define UARTTX_QUEUE_MESSAGE_SIZE 16
#endif // UARTTX_QUEUE_MESSAGE_SIZE
#ifndef THREADUART_QUEUE_MESSAGE_SIZE
#define THREADUART_QUEUE_MESSAGE_SIZE 16
#endif // THREADUART_QUEUE_MESSAGE_SIZE

#ifndef UARTTX_QUEUE_NUM_MESSAGES
#define UARTTX_QUEUE_NUM_MESSAGES 32
#endif // UARTTX_QUEUE_NUM_MESSAGES
#ifndef THREADUART_QUEUE_NUM_MESSAGES
#define THREADUART_QUEUE_NUM_MESSAGES 32
#endif // THREADUART_QUEUE_NUM_MESSAGES

#ifndef UARTTX_DEFAULT_STACK_SIZE
#define UARTTX_DEFAULT_STACK_SIZE 1024
#endif // UARTTX_DEFAULT_STACK_SIZE
#ifndef THREADUART_DEFAULT_STACK_SIZE
#define THREADUART_DEFAULT_STACK_SIZE 1024
#endif // THREADUART_DEFAULT_STACK_SIZE

#ifndef UARTTX_DEFAULT_PRIORITY_LEVEL
#define UARTTX_DEFAULT_PRIORITY_LEVEL 1u
#endif // UARTTX_DEFAULT_PRIORITY_LEVEL
#ifndef THREADUART_DEFAULT_PRIORITY_LEVEL
#define THREADUART_DEFAULT_PRIORITY_LEVEL 1u
#endif // THREADUART_DEFAULT_PRIORITY_LEVEL

#ifndef UARTTX_DEFAULT_PREEMPT_THRESHOLD
#define UARTTX_DEFAULT_PREEMPT_THRESHOLD 0u
#endif // UARTTX_DEFAULT_PREEMPT_THRESHOLD
#ifndef THREADUART_DEFAULT_PREEMPT_THRESHOLD
#define THREADUART_DEFAULT_PREEMPT_THRESHOLD 0u
#endif // THREADUART_DEFAULT_PREEMPT_THRESHOLD

#ifndef UARTTX_DEFAULT_TIME_SLICE
#define UARTTX_DEFAULT_TIME_SLICE MS_TO_TICKS(500)
#endif // UARTTX_DEFAULT_TIME_SLICE
#ifndef THREADUART_DEFAULT_TIME_SLICE
#define THREADUART_DEFAULT_TIME_SLICE MS_TO_TICKS(500)
#endif // THREADUART_DEFAULT_TIME_SLICE

namespace io = core::io;
namespace core::rtos::wrapper {
namespace core::rtos::tsio {

/**
* Class that represents a threadsafe implementation of UART.
Expand All @@ -50,19 +50,19 @@ namespace core::rtos::wrapper {
* the scheduler gives it priority to print the contents of the queue to UART.\n\n
*
*
* NOTE: In some cases it may be possible that UARRTX never prints if there is
* NOTE: In some cases it may be possible that ThreadUART never prints if there is
* always a higher priority thread able to run, so it should be given as high a
* priority as possible without it interfering with the normal execution of threads.\n\n
*
*
* NOTE: UARRTX's own thread must NEVER print to UARTTX. If it does this while
* NOTE: ThreadUART's own thread must NEVER print to ThreadUART. If it does this while
* the queue is full, it will suspend on the queue and since it is the only
* thread that can empty the queue, it will never stop suspending. If this occurs,
* any threads that then try to write to UARRTX will also suspend forever, which
* will lead to your code slowly shutting down for no discernable reason.
* There is no need to modify UARTTX's thread's method, so don't. Don't do it.
* any threads that then try to write to ThreadUART will also suspend forever, which
* will lead to your code slowly shutting down for no clear reason.
* There should be no need to modify ThreadUART's thread's method.
*/
class UARTTX : public Initializable, io::UART {
class ThreadUART : public Initializable, io::UART {
public:
/**
* Constructor for thread safe uart class
Expand All @@ -78,10 +78,10 @@ class UARTTX : public Initializable, io::UART {
* while it is running is likely to just cause the UART output to break immediately.
* @param[in] threadTimeSlice The default minimum timeslice of this thread
*/
explicit UARTTX(io::UART& uart, std::size_t threadStackSize = UARTTX_DEFAULT_STACK_SIZE,
uint32_t threadPriorityLevel = UARTTX_DEFAULT_PRIORITY_LEVEL,
uint32_t threadPreemptThreshold = UARTTX_DEFAULT_PREEMPT_THRESHOLD,
uint32_t threadTimeSlice = UARTTX_DEFAULT_TIME_SLICE);
explicit ThreadUART(io::UART& uart, std::size_t threadStackSize = THREADUART_DEFAULT_STACK_SIZE,
uint32_t threadPriorityLevel = THREADUART_DEFAULT_PRIORITY_LEVEL,
uint32_t threadPreemptThreshold = THREADUART_DEFAULT_PREEMPT_THRESHOLD,
uint32_t threadTimeSlice = THREADUART_DEFAULT_TIME_SLICE);

// Inherited Initializable methods

Expand All @@ -108,34 +108,57 @@ class UARTTX : public Initializable, io::UART {

void readBytes(uint8_t* bytes, size_t size) override;

/**
* Copies the given string to the Queue of messages to be sent to UART,
* splitting it into multiple Queue messages if the string is too long
* (each of the messages will be 64 bytes)
*
* @param[in] s A pointer to the string we are sending to the Queue
*/
void puts(const char* s);

void putc(char c) override;

/**
* Copies the given byte array to the Queue of messages to be sent to UART,
* splitting it into multiple Queue messages if the string is too long
* (each of the messages will be 64 bytes).
*
* @param[in] bytes pointer to the byte array we are sending to the Queue
* @param[in] size size of the byte array
*/
void writeBytes(uint8_t* bytes, size_t size) override;

void write(uint8_t byte) override;

// UARTTX Queue Informational Methods

/**
* Retrieve the number of enqueued messages in this UARTTX's Queue
* Retrieve the number of enqueued messages in this ThreadUART's Queue
*
* @param[out] numEnqueuedMessages A pointer to store the number of enqueued messages in
* @return The first error found by the function or Success if there was no error
*/
TXError getNumberOfEnqueuedMessages(uint32_t* numEnqueuedMessages);

/**
* Retrieve the number of more messages this UARTTX's Queue can fit
* Retrieve the number of more messages this ThreadUART's Queue can fit
*
* @param[out] numAvailableMessages A pointer to store the number of additional messages that the queue can fit
* @return The first error found by the function or Success if there was no error
*/
TXError getAvailableQueueStorage(uint32_t* numAvailableMessages);

/**
* Retrieve the name of the first thread suspended on sending a message to this UARTTX
* Retrieve the name of the first thread suspended on sending a message to this ThreadUART
*
* @param[out] threadName A pointer to a place to store the name of the first suspended thread
* @return The first error found by the function or Success if there was no error
*/
TXError getNameOfFirstSuspendedThread(char** threadName);

/**
* Retrieve the number of threads that are suspended on this UARTTX
* Retrieve the number of threads that are suspended on this ThreadUART
*
* @param[out] numSuspendedThreads A pointer to a place to store the number of suspended threads
* @return The first error found by the function or Success if there was no error
Expand All @@ -144,31 +167,15 @@ class UARTTX : public Initializable, io::UART {

// must be public so the static method can call it
/**
* Reads from the queue and actually sends it to UART. Called by the UARTTX Thread's entry function.
* Reads the first message from the queue and sends it to UART. Called by the ThreadUART Thread's entry function.
* Do not call this anywhere else.
*/
void readQueuart();
void sendFirstQueueMessage();

private:
void putc(char c) override;

void puts(const char* s) override;

void write(uint8_t byte) override;

void writeBytes(uint8_t* bytes, size_t size) override;

/**
* Adds the given string to the Queue of messages to be sent to UART,
* splitting it into multiple Queue messages if the string is too long
* (each of the messages will be 16 words)
*
* @param[in] buffer A pointer to the string we are sending to the Queue
*/
void addQueuart(char* buffer);

/** Pointer to store this thread's entry function */
void (*threadEntryFunction)(UARTTX*);
void (*threadEntryFunction)(ThreadUART*);

/** UART object */
io::UART& copyUART;
Expand All @@ -180,12 +187,12 @@ class UARTTX : public Initializable, io::UART {
Queue queue;

/** Thread that empties the queue and prints it's contents to uart */
Thread<UARTTX*> thread;
Thread<ThreadUART*> thread;

/** Mutex that makes sure only one thread reads from UART at a time */
Mutex readMutex;
};

} // namespace core::rtos::wrapper
} // namespace core::rtos::tsio

#endif // EVT_TX_UART_H
#endif // _EVT_THREAD_UART_
8 changes: 4 additions & 4 deletions samples/rtos/threadx-demo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <core/rtos/Queue.hpp>
#include <core/rtos/Semaphore.hpp>
#include <core/rtos/Thread.hpp>
#include <core/rtos/UARTTX.hpp>
#include <core/rtos/tsio/ThreadUART.hpp>

/// Namespaces
namespace io = core::io;
Expand Down Expand Up @@ -48,7 +48,7 @@ typedef struct counters {
typedef struct controller_thread_args {
rtos::Queue* queue;
rtos::Semaphore* semaphore;
rtos::wrapper::UARTTX* uarttx;
rtos::tsio::ThreadUART* uarttx;
counters_t* counters;
} controller_thread_args_t;

Expand All @@ -58,7 +58,7 @@ typedef struct controller_thread_args {
typedef struct worker_thread_args {
rtos::Queue* queue;
rtos::Semaphore* semaphore;
rtos::wrapper::UARTTX* uarttx;
rtos::tsio::ThreadUART* uarttx;
rtos::EventFlags* eventFlags;
uint8_t num;
counters_t* counters;
Expand All @@ -79,7 +79,7 @@ int main() {
log::LOGGER.setUART(&uart);
log::LOGGER.setLogLevel(log::Logger::LogLevel::DEBUG);

rtos::wrapper::UARTTX uarttx(uart);
rtos::tsio::ThreadUART uarttx(uart);
rtos::Queue q1((char*) "queue", 16, 20);
rtos::BytePool<TX_APP_MEM_POOL_SIZE> txPool((char*) "txBytePool");
rtos::Semaphore semaphore((char*) "Semaphore 1", 1);
Expand Down
10 changes: 5 additions & 5 deletions src/core/rtos/EventFlags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ TXError EventFlags::set(uint32_t mask, bool clearNonMaskedFlags) {
}

TXError EventFlags::get(uint32_t mask, bool waitForAllFlags, bool clear, uint32_t waitOption, uint32_t* output) {
uint32_t option = waitForAllFlags ? TX_AND : TX_OR;
// the TX_AND_CLEAR and TX_AND_OR options are respectively 1 more than their no clear versions, which is why this
// works.
option += clear;
//ThreadX packs waitForAllFlags and clear into one uint32_t option where the first bit is whether to clear,
// and the second bit is whether to wait.
uint32_t option = ((uint32_t)waitForAllFlags << 1) | ((uint32_t)clear);
return static_cast<TXError>(tx_event_flags_get(&txEventFlagsGroup, mask, option, output, waitOption));
}

Expand All @@ -45,8 +44,9 @@ TXError EventFlags::getNameOfFirstSuspendedThread(char** threadName) {
uint32_t status = tx_event_flags_info_get(&txEventFlagsGroup, nullptr, nullptr, &thread, nullptr, nullptr);

// exit early if the call failed
if (status != SUCCESS)
if (status != SUCCESS) {
return static_cast<TXError>(status);
}

// read the name off the struct
status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
Expand Down
5 changes: 2 additions & 3 deletions src/core/rtos/Mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,19 @@ TXError Mutex::getNameOfOwner(char** ownerName) {

// read the name off the struct
status = tx_thread_info_get(owner, ownerName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

return static_cast<TXError>(status);
}

TXError Mutex::getNameOfFirstSuspendedThread(char** threadName) {
TX_THREAD* thread;
uint32_t status = tx_mutex_info_get(&txMutex, nullptr, nullptr, nullptr, &thread, nullptr, nullptr);
// exit early if the call failed
if (status != SUCCESS)
if (status != SUCCESS) {
return static_cast<TXError>(status);
}

// read the name off the struct
status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

return static_cast<TXError>(status);
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/rtos/Queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ TXError Queue::getNameOfFirstSuspendedThread(char** threadName) {
TX_THREAD* thread;
uint32_t status = tx_queue_info_get(&txQueue, nullptr, nullptr, nullptr, &thread, nullptr, nullptr);
// exit early if the call failed
if (status != SUCCESS)
if (status != SUCCESS) {
return static_cast<TXError>(status);
}

// read the name off the struct
status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

return static_cast<TXError>(status);
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/rtos/Semaphore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ TXError Semaphore::getNameOfFirstSuspendedThread(char** threadName) {
TX_THREAD* thread;
uint32_t status = tx_semaphore_info_get(&txSemaphore, nullptr, nullptr, &thread, nullptr, nullptr);
// exit early if the call failed
if (status != SUCCESS)
if (status != SUCCESS) {
return static_cast<TXError>(status);
}

// read the name off the struct
status = tx_thread_info_get(thread, threadName, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);

return static_cast<TXError>(status);
}

Expand Down
6 changes: 4 additions & 2 deletions src/core/rtos/Threadx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ namespace core::rtos {

namespace {
Initializable** initializableList;
std::size_t initListLength;
size_t initListLength;
BytePoolBase* mainThreadPool;
} // namespace

TXError init(Initializable* initList[], std::size_t length, BytePoolBase& pool) {
TXError errorCode = pool.init();
Expand All @@ -24,10 +23,13 @@ extern "C" void tx_application_define(void* first_unused_memory) {
init(initializableList, initListLength, *mainThreadPool);
}

} // namespace

TXError startKernel(Initializable* initList[], std::size_t length, BytePoolBase& pool) {
initializableList = initList;
initListLength = length;
mainThreadPool = &pool;
//tx_kernel_enter calls tx_application_define, which initializes everything in initList.
tx_kernel_enter();
return SUCCESS;
}
Expand Down
Loading

0 comments on commit 9d27e98

Please sign in to comment.