6.1 minor release

This commit is contained in:
Scott Larson
2020-09-30 15:42:41 -07:00
parent 7287542cc8
commit 1b5816a206
3038 changed files with 377204 additions and 8606 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<workspace>
<project>
<path>$WS_DIR$\sample_threadx.ewp</path>
</project>
<project>
<path>$WS_DIR$\tx.ewp</path>
</project>
<batchBuild />
</workspace>

View File

@@ -0,0 +1,395 @@
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
threads of different priorities, using a message queue, semaphore, mutex, event flags group,
byte pool, and block pool. Please refer to Chapter 6 of the ThreadX User Guide for a complete
description of this demonstration. */
#include "tx_api.h"
#define DEMO_STACK_SIZE 1024
#define DEMO_BYTE_POOL_SIZE 9120
#define DEMO_BLOCK_POOL_SIZE 100
#define DEMO_QUEUE_SIZE 100
/* Define the ThreadX object control blocks... */
TX_THREAD thread_0;
TX_THREAD thread_1;
TX_THREAD thread_2;
TX_THREAD thread_3;
TX_THREAD thread_4;
TX_THREAD thread_5;
TX_THREAD thread_6;
TX_THREAD thread_7;
TX_QUEUE queue_0;
TX_SEMAPHORE semaphore_0;
TX_MUTEX mutex_0;
TX_EVENT_FLAGS_GROUP event_flags_0;
TX_BYTE_POOL byte_pool_0;
TX_BLOCK_POOL block_pool_0;
/* Define byte pool memory. */
UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
/* Define event buffer. */
#ifdef TX_ENABLE_EVENT_TRACE
UCHAR trace_buffer[0x10000];
#endif
/* Define the counters used in the demo application... */
ULONG thread_0_counter;
ULONG thread_1_counter;
ULONG thread_1_messages_sent;
ULONG thread_2_counter;
ULONG thread_2_messages_received;
ULONG thread_3_counter;
ULONG thread_4_counter;
ULONG thread_5_counter;
ULONG thread_6_counter;
ULONG thread_7_counter;
/* Define thread prototypes. */
void thread_0_entry(ULONG thread_input);
void thread_1_entry(ULONG thread_input);
void thread_2_entry(ULONG thread_input);
void thread_3_and_4_entry(ULONG thread_input);
void thread_5_entry(ULONG thread_input);
void thread_6_and_7_entry(ULONG thread_input);
/* Define main entry point. */
int main()
{
/* Please refer to Chapter 6 of the ThreadX User Guide for a complete
description of this demonstration. */
/* Enter the ThreadX kernel. */
tx_kernel_enter();
}
/* Define what the initial system looks like. */
void tx_application_define(void *first_unused_memory)
{
CHAR *pointer;
#ifdef TX_ENABLE_EVENT_TRACE
tx_trace_enable(trace_buffer, sizeof(trace_buffer), 32);
#endif
/* Create a byte memory pool from which to allocate the thread stacks. */
tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, DEMO_BYTE_POOL_SIZE);
/* Put system definition stuff in here, e.g. thread creates and other assorted
create information. */
/* Allocate the stack for thread 0. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
/* Create the main thread. */
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
pointer, DEMO_STACK_SIZE,
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the stack for thread 1. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
/* Create threads 1 and 2. These threads pass information through a ThreadX
message queue. It is also interesting to note that these threads have a time
slice. */
tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
pointer, DEMO_STACK_SIZE,
16, 16, 4, TX_AUTO_START);
/* Allocate the stack for thread 2. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
pointer, DEMO_STACK_SIZE,
16, 16, 4, TX_AUTO_START);
/* Allocate the stack for thread 3. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
/* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
An interesting thing here is that both threads share the same instruction area. */
tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
pointer, DEMO_STACK_SIZE,
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the stack for thread 4. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
pointer, DEMO_STACK_SIZE,
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the stack for thread 5. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
/* Create thread 5. This thread simply pends on an event flag which will be set
by thread_0. */
tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
pointer, DEMO_STACK_SIZE,
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the stack for thread 6. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
/* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
pointer, DEMO_STACK_SIZE,
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the stack for thread 7. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
pointer, DEMO_STACK_SIZE,
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
/* Allocate the message queue. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
/* Create the message queue shared by threads 1 and 2. */
tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
/* Create the semaphore used by threads 3 and 4. */
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
/* Create the event flags group used by threads 1 and 5. */
tx_event_flags_create(&event_flags_0, "event flags 0");
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
/* Allocate the memory for a small block pool. */
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
/* Create a block memory pool to allocate a message buffer from. */
tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
/* Allocate a block and release the block memory. */
tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
/* Release the block back to the pool. */
tx_block_release(pointer);
}
/* Define the test threads. */
void thread_0_entry(ULONG thread_input)
{
UINT status;
/* This thread simply sits in while-forever-sleep loop. */
while(1)
{
/* Increment the thread counter. */
thread_0_counter++;
/* Sleep for 10 ticks. */
tx_thread_sleep(10);
/* Set event flag 0 to wakeup thread 5. */
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
/* Check status. */
if (status != TX_SUCCESS)
break;
}
}
void thread_1_entry(ULONG thread_input)
{
UINT status;
/* This thread simply sends messages to a queue shared by thread 2. */
while(1)
{
/* Increment the thread counter. */
thread_1_counter++;
/* Send message to queue 0. */
status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
/* Check completion status. */
if (status != TX_SUCCESS)
break;
/* Increment the message sent. */
thread_1_messages_sent++;
}
}
void thread_2_entry(ULONG thread_input)
{
ULONG received_message;
UINT status;
/* This thread retrieves messages placed on the queue by thread 1. */
while(1)
{
/* Increment the thread counter. */
thread_2_counter++;
/* Retrieve a message from the queue. */
status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
/* Check completion status and make sure the message is what we
expected. */
if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
break;
/* Otherwise, all is okay. Increment the received message count. */
thread_2_messages_received++;
}
}
void thread_3_and_4_entry(ULONG thread_input)
{
UINT status;
/* This function is executed from thread 3 and thread 4. As the loop
below shows, these function compete for ownership of semaphore_0. */
while(1)
{
/* Increment the thread counter. */
if (thread_input == 3)
thread_3_counter++;
else
thread_4_counter++;
/* Get the semaphore with suspension. */
status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
/* Check status. */
if (status != TX_SUCCESS)
break;
/* Sleep for 2 ticks to hold the semaphore. */
tx_thread_sleep(2);
/* Release the semaphore. */
status = tx_semaphore_put(&semaphore_0);
/* Check status. */
if (status != TX_SUCCESS)
break;
}
}
void thread_5_entry(ULONG thread_input)
{
UINT status;
ULONG actual_flags;
/* This thread simply waits for an event in a forever loop. */
while(1)
{
/* Increment the thread counter. */
thread_5_counter++;
/* Wait for event flag 0. */
status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
&actual_flags, TX_WAIT_FOREVER);
/* Check status. */
if ((status != TX_SUCCESS) || (actual_flags != 0x1))
break;
}
}
void thread_6_and_7_entry(ULONG thread_input)
{
UINT status;
/* This function is executed from thread 6 and thread 7. As the loop
below shows, these function compete for ownership of mutex_0. */
while(1)
{
/* Increment the thread counter. */
if (thread_input == 6)
thread_6_counter++;
else
thread_7_counter++;
/* Get the mutex with suspension. */
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
/* Check status. */
if (status != TX_SUCCESS)
break;
/* Get the mutex again with suspension. This shows
that an owning thread may retrieve the mutex it
owns multiple times. */
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
/* Check status. */
if (status != TX_SUCCESS)
break;
/* Sleep for 2 ticks to hold the mutex. */
tx_thread_sleep(2);
/* Release the mutex. */
status = tx_mutex_put(&mutex_0);
/* Check status. */
if (status != TX_SUCCESS)
break;
/* Release the mutex again. This will actually
release ownership since it was obtained twice. */
status = tx_mutex_put(&mutex_0);
/* Check status. */
if (status != TX_SUCCESS)
break;
}
}
#pragma vector = 3
__interrupt void test()
{
thread_6_and_7_entry(1);
}

View File

@@ -0,0 +1,848 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<fileVersion>3</fileVersion>
<configuration>
<name>Debug</name>
<toolchain>
<name>RISCV</name>
</toolchain>
<debug>1</debug>
<settings>
<name>C-SPY</name>
<archiveVersion>3</archiveVersion>
<data>
<version>1</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>CSPYInput</name>
<state>1</state>
</option>
<option>
<name>CSPYProcessor</name>
<state>0</state>
</option>
<option>
<name>CSPYDynDriver</name>
<state>SIMRISCV</state>
</option>
<option>
<name>CSPYRunToEnable</name>
<state>1</state>
</option>
<option>
<name>CSPYRunoToName</name>
<state>main</state>
</option>
<option>
<name>CSPYMacOverride</name>
<state>1</state>
</option>
<option>
<name>CSPYMacFile</name>
<state>$PROJ_DIR$/config/debugger/timer.mac</state>
</option>
<option>
<name>CSPYMemOverride</name>
<state>1</state>
</option>
<option>
<name>CSPYMemFile</name>
<state>$PROJ_DIR$/config/debugger/ioriscv.ddf</state>
</option>
<option>
<name>CSPYMandatory</name>
<state>1</state>
</option>
<option>
<name>CSPYDDFileSlave</name>
<state>1</state>
</option>
<option>
<name>CSPYImagesSuppressCheck1</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath1</name>
<state></state>
</option>
<option>
<name>CSPYImagesSuppressCheck2</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath2</name>
<state></state>
</option>
<option>
<name>CSPYImagesSuppressCheck3</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath3</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset1</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset2</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset3</name>
<state></state>
</option>
<option>
<name>CSPYImagesUse1</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesUse2</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesUse3</name>
<state>0</state>
</option>
<option>
<name>CSPYExtraOptionsCheck</name>
<state>0</state>
</option>
<option>
<name>CSPYExtraOptions</name>
<state></state>
</option>
<option>
<name>OCDownloadSuppressDownload</name>
<state>0</state>
</option>
<option>
<name>OCDownloadVerifyAll</name>
<state>0</state>
</option>
<option>
<name>UseFlashLoader</name>
<state>1</state>
</option>
<option>
<name>OverrideDefFlashBoard</name>
<state>0</state>
</option>
<option>
<name>FlashLoaders</name>
<state></state>
</option>
<option>
<name>MassEraseBeforeFlashing</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreNrOfCores</name>
<state>1</state>
</option>
<option>
<name>OCMulticoreWorkspace</name>
<state></state>
</option>
<option>
<name>OCMulticoreSlaveProject</name>
<state></state>
</option>
<option>
<name>OCMulticoreSlaveConfiguration</name>
<state></state>
</option>
<option>
<name>OCAttachSlave</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreNrOfCoresSlave</name>
<state>1</state>
</option>
<option>
<name>OCMulticoreAMPConfigType</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreSessionFile</name>
<state></state>
</option>
</data>
</settings>
<settings>
<name>IJETRISCV</name>
<archiveVersion>2</archiveVersion>
<data>
<version>1</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>OCDriverInfo</name>
<state>1</state>
</option>
<option>
<name>OCIarProbeScriptFile</name>
<state>1</state>
</option>
<option>
<name>OCProbeCfgOverride</name>
<state>0</state>
</option>
<option>
<name>OCProbeConfig</name>
<state></state>
</option>
<option>
<name>IjetProbeConfigRadio</name>
<state>0</state>
</option>
<option>
<name>IjetSelectedCPUBehaviour</name>
<state>0</state>
</option>
<option>
<name>ICpuName</name>
<state></state>
</option>
<option>
<name>IjetResetList</name>
<version>0</version>
<state>5</state>
</option>
<option>
<name>IjetHWResetDuration</name>
<state>300</state>
</option>
<option>
<name>IjetHWResetDelay</name>
<state>200</state>
</option>
<option>
<name>IjetPowerFromProbe</name>
<state>0</state>
</option>
<option>
<name>IjetPowerRadio</name>
<state>0</state>
</option>
<option>
<name>CCIjetUsbSerialNo</name>
<state></state>
</option>
<option>
<name>CCIjetUsbSerialNoSelect</name>
<state>0</state>
</option>
<option>
<name>IjetDoLogfile</name>
<state>0</state>
</option>
<option>
<name>IjetLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>IjetInterfaceRadio</name>
<state>0</state>
</option>
<option>
<name>IjetInterfaceCmdLine</name>
<state>0</state>
</option>
<option>
<name>IjetMultiTargetEnable</name>
<state>0</state>
</option>
<option>
<name>IjetMultiTarget</name>
<state>0</state>
</option>
<option>
<name>IjetScanChainNonRISCVDevices</name>
<state>0</state>
</option>
<option>
<name>IjetIRLength</name>
<state>0</state>
</option>
<option>
<name>IjetMultiCPUEnable</name>
<state>0</state>
</option>
<option>
<name>IjetMultiCPUNumber</name>
<state>0</state>
</option>
<option>
<name>IjetJtagSpeedList</name>
<version>0</version>
<state>0</state>
</option>
<option>
<name>IjetBreakpointRadio</name>
<state>0</state>
</option>
<option>
<name>IjetRestoreBreakpointsCheck</name>
<state>0</state>
</option>
<option>
<name>IjetUpdateBreakpointsEdit</name>
<state>_call_main</state>
</option>
<option>
<name>RDICatchReset</name>
<state>0</state>
</option>
<option>
<name>CatchDummy</name>
<state>0</state>
</option>
<option>
<name>OCJetEmuParams</name>
<state>1</state>
</option>
<option>
<name>FlashBoardPathSlave</name>
<state>0</state>
</option>
<option>
<name>RDICatchNmi</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrMis</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrFault</name>
<state>0</state>
</option>
<option>
<name>RDICatchIllegalInstr</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadMis</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadFault</name>
<state>0</state>
</option>
<option>
<name>RDICatchStoreAddr</name>
<state>0</state>
</option>
<option>
<name>RDICatchStoreAccess</name>
<state>0</state>
</option>
<option>
<name>RDICatchEnvironment</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrPage</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadPage</name>
<state>0</state>
</option>
<option>
<name>RDICatchStorePage</name>
<state>0</state>
</option>
<option>
<name>RDICatchExternal</name>
<state>0</state>
</option>
<option>
<name>RDICatchTimer</name>
<state>0</state>
</option>
<option>
<name>RDICatchSoftware</name>
<state>0</state>
</option>
<option>
<name>RDICatchModeM</name>
<state>1</state>
</option>
<option>
<name>RDICatchModeS</name>
<state>1</state>
</option>
<option>
<name>RDICatchModeU</name>
<state>1</state>
</option>
<option>
<name>GDelayAfterOverride</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>SIMRISCV</name>
<archiveVersion>3</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>1</debug>
<option>
<name>SIMMandatory</name>
<state>0</state>
</option>
</data>
</settings>
<debuggerPlugins>
<plugin>
<file>$TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
</debuggerPlugins>
</configuration>
<configuration>
<name>Release</name>
<toolchain>
<name>RISCV</name>
</toolchain>
<debug>0</debug>
<settings>
<name>C-SPY</name>
<archiveVersion>3</archiveVersion>
<data>
<version>1</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>CSPYInput</name>
<state>1</state>
</option>
<option>
<name>CSPYProcessor</name>
<state>0</state>
</option>
<option>
<name>CSPYDynDriver</name>
<state>SIMRISCV</state>
</option>
<option>
<name>CSPYRunToEnable</name>
<state>1</state>
</option>
<option>
<name>CSPYRunoToName</name>
<state>main</state>
</option>
<option>
<name>CSPYMacOverride</name>
<state>0</state>
</option>
<option>
<name>CSPYMacFile</name>
<state></state>
</option>
<option>
<name>CSPYMemOverride</name>
<state>0</state>
</option>
<option>
<name>CSPYMemFile</name>
<state></state>
</option>
<option>
<name>CSPYMandatory</name>
<state>1</state>
</option>
<option>
<name>CSPYDDFileSlave</name>
<state>1</state>
</option>
<option>
<name>CSPYImagesSuppressCheck1</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath1</name>
<state></state>
</option>
<option>
<name>CSPYImagesSuppressCheck2</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath2</name>
<state></state>
</option>
<option>
<name>CSPYImagesSuppressCheck3</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesPath3</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset1</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset2</name>
<state></state>
</option>
<option>
<name>CSPYImagesOffset3</name>
<state></state>
</option>
<option>
<name>CSPYImagesUse1</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesUse2</name>
<state>0</state>
</option>
<option>
<name>CSPYImagesUse3</name>
<state>0</state>
</option>
<option>
<name>CSPYExtraOptionsCheck</name>
<state>0</state>
</option>
<option>
<name>CSPYExtraOptions</name>
<state></state>
</option>
<option>
<name>OCDownloadSuppressDownload</name>
<state>0</state>
</option>
<option>
<name>OCDownloadVerifyAll</name>
<state>0</state>
</option>
<option>
<name>UseFlashLoader</name>
<state>1</state>
</option>
<option>
<name>OverrideDefFlashBoard</name>
<state>0</state>
</option>
<option>
<name>FlashLoaders</name>
<state></state>
</option>
<option>
<name>MassEraseBeforeFlashing</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreNrOfCores</name>
<state></state>
</option>
<option>
<name>OCMulticoreWorkspace</name>
<state></state>
</option>
<option>
<name>OCMulticoreSlaveProject</name>
<state></state>
</option>
<option>
<name>OCMulticoreSlaveConfiguration</name>
<state></state>
</option>
<option>
<name>OCAttachSlave</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreNrOfCoresSlave</name>
<state>1</state>
</option>
<option>
<name>OCMulticoreAMPConfigType</name>
<state>0</state>
</option>
<option>
<name>OCMulticoreSessionFile</name>
<state></state>
</option>
</data>
</settings>
<settings>
<name>IJETRISCV</name>
<archiveVersion>2</archiveVersion>
<data>
<version>1</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>OCDriverInfo</name>
<state>1</state>
</option>
<option>
<name>OCIarProbeScriptFile</name>
<state>1</state>
</option>
<option>
<name>OCProbeCfgOverride</name>
<state>0</state>
</option>
<option>
<name>OCProbeConfig</name>
<state></state>
</option>
<option>
<name>IjetProbeConfigRadio</name>
<state>0</state>
</option>
<option>
<name>IjetSelectedCPUBehaviour</name>
<state>0</state>
</option>
<option>
<name>ICpuName</name>
<state></state>
</option>
<option>
<name>IjetResetList</name>
<version>0</version>
<state>5</state>
</option>
<option>
<name>IjetHWResetDuration</name>
<state>300</state>
</option>
<option>
<name>IjetHWResetDelay</name>
<state>###uninitialized###</state>
</option>
<option>
<name>IjetPowerFromProbe</name>
<state>0</state>
</option>
<option>
<name>IjetPowerRadio</name>
<state>0</state>
</option>
<option>
<name>CCIjetUsbSerialNo</name>
<state></state>
</option>
<option>
<name>CCIjetUsbSerialNoSelect</name>
<state>0</state>
</option>
<option>
<name>IjetDoLogfile</name>
<state>0</state>
</option>
<option>
<name>IjetLogFile</name>
<state>$PROJ_DIR$\cspycomm.log</state>
</option>
<option>
<name>IjetInterfaceRadio</name>
<state>0</state>
</option>
<option>
<name>IjetInterfaceCmdLine</name>
<state>0</state>
</option>
<option>
<name>IjetMultiTargetEnable</name>
<state>0</state>
</option>
<option>
<name>IjetMultiTarget</name>
<state>0</state>
</option>
<option>
<name>IjetScanChainNonRISCVDevices</name>
<state>0</state>
</option>
<option>
<name>IjetIRLength</name>
<state>0</state>
</option>
<option>
<name>IjetMultiCPUEnable</name>
<state>0</state>
</option>
<option>
<name>IjetMultiCPUNumber</name>
<state>0</state>
</option>
<option>
<name>IjetJtagSpeedList</name>
<version>0</version>
<state>0</state>
</option>
<option>
<name>IjetBreakpointRadio</name>
<state>0</state>
</option>
<option>
<name>IjetRestoreBreakpointsCheck</name>
<state>0</state>
</option>
<option>
<name>IjetUpdateBreakpointsEdit</name>
<state>_call_main</state>
</option>
<option>
<name>RDICatchReset</name>
<state>0</state>
</option>
<option>
<name>CatchDummy</name>
<state>0</state>
</option>
<option>
<name>OCJetEmuParams</name>
<state>1</state>
</option>
<option>
<name>FlashBoardPathSlave</name>
<state>0</state>
</option>
<option>
<name>RDICatchNmi</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrMis</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrFault</name>
<state>0</state>
</option>
<option>
<name>RDICatchIllegalInstr</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadMis</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadFault</name>
<state>0</state>
</option>
<option>
<name>RDICatchStoreAddr</name>
<state>0</state>
</option>
<option>
<name>RDICatchStoreAccess</name>
<state>0</state>
</option>
<option>
<name>RDICatchEnvironment</name>
<state>0</state>
</option>
<option>
<name>RDICatchInstrPage</name>
<state>0</state>
</option>
<option>
<name>RDICatchLoadPage</name>
<state>0</state>
</option>
<option>
<name>RDICatchStorePage</name>
<state>0</state>
</option>
<option>
<name>RDICatchExternal</name>
<state>0</state>
</option>
<option>
<name>RDICatchTimer</name>
<state>0</state>
</option>
<option>
<name>RDICatchSoftware</name>
<state>0</state>
</option>
<option>
<name>RDICatchModeM</name>
<state>1</state>
</option>
<option>
<name>RDICatchModeS</name>
<state>1</state>
</option>
<option>
<name>RDICatchModeU</name>
<state>1</state>
</option>
<option>
<name>GDelayAfterOverride</name>
<state>0</state>
</option>
</data>
</settings>
<settings>
<name>SIMRISCV</name>
<archiveVersion>3</archiveVersion>
<data>
<version>0</version>
<wantNonLocal>1</wantNonLocal>
<debug>0</debug>
<option>
<name>SIMMandatory</name>
<state>0</state>
</option>
</data>
</settings>
<debuggerPlugins>
<plugin>
<file>$TOOLKIT_DIR$\plugins\rtos\OpenRTOS\OpenRTOSPlugin.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$TOOLKIT_DIR$\plugins\rtos\SafeRTOS\SafeRTOSPlugin.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\TargetAccessServer\TargetAccessServer.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
<plugin>
<file>$EW_DIR$\common\plugins\uCProbe\uCProbePlugin.ENU.ewplugin</file>
<loadFlag>0</loadFlag>
</plugin>
</debuggerPlugins>
</configuration>
</project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
///////////////////////////////////////////////////////////////////////////////
// RISC-V ilink configuration file.
//
define exported symbol _link_file_version_2 = 1;
define exported symbol _auto_vector_setup = 1;
define exported symbol _max_vector = 16;
define exported symbol _CLINT = 1;
define memory mem with size = 4G;
define region RAM_region32 = mem:[from 0x80000000 to 0x8003FFFF];
define region ROM_region32 = mem:[from 0x20000000 to 0x3FFFFFFF];
initialize by copy { rw };
do not initialize { section *.noinit };
define block CSTACK with alignment = 16, size = CSTACK_SIZE { };
define block HEAP with alignment = 16, size = HEAP_SIZE { };
define block MVECTOR with alignment = 128 { ro section .mintvec };
if (isdefinedsymbol(_uses_clic))
{
define block MINTERRUPT with alignment = 128 { ro section .mtext };
define block MINTERRUPTS { block MVECTOR,
block MINTERRUPT };
}
else
{
define block MINTERRUPTS with maximum size = 64k { ro section .mtext,
midway block MVECTOR };
}
define block RW_DATA with static base GPREL { rw data };
keep { symbol __iar_cstart_init_gp }; // defined in cstartup.s
"CSTARTUP32" : place at start of ROM_region32 { ro section .cstartup };
"ROM32":place in ROM_region32 { ro,
block MINTERRUPTS };
"RAM32":place in RAM_region32 { block RW_DATA,
block HEAP,
block CSTACK };
"RAM32":place in RAM_region32 { last section FREE_MEM};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,275 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Port Specific */
/** */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/* */
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h RISC-V32/IAR */
/* 6.1 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This file contains data type definitions that make the ThreadX */
/* real-time kernel function identically on a variety of different */
/* processor architectures. For example, the size or number of bits */
/* in an "int" data type vary between microprocessor architectures and */
/* even C compilers for the same microprocessor. ThreadX does not */
/* directly use native C data types. Instead, ThreadX creates its */
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
#ifndef TX_PORT_H
#define TX_PORT_H
/* Include prototypes for memset. */
#include <string.h>
#include <intrinsics.h>
/* Determine if the optional ThreadX user define file should be used. */
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
#endif
/* Define compiler library include files. */
/* Define ThreadX basic types for this port. */
#define VOID void
typedef char CHAR;
typedef unsigned char UCHAR;
typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef short SHORT;
typedef unsigned short USHORT;
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
#ifndef TX_MAX_PRIORITIES
#define TX_MAX_PRIORITIES 32
#endif
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
thread creation is less than this value, the thread create call will return an error. */
#ifndef TX_MINIMUM_STACK
#define TX_MINIMUM_STACK 512 /* Minimum stack size for this port */
#endif
/* Define the system timer thread's default stack size and priority. These are only applicable
if TX_TIMER_PROCESS_IN_ISR is not defined. */
#ifndef TX_TIMER_THREAD_STACK_SIZE
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
#endif
#ifndef TX_TIMER_THREAD_PRIORITY
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
#endif
/* Define various constants for the ThreadX RISC-V port. */
#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */
#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
*/
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
/* Define the in-line initialization constant so that modules with in-line
initialization capabilities can prevent their initialization from being
a function call. */
#define TX_INLINE_INITIALIZATION
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
define is negated, thereby forcing the stack fill which is necessary for the stack checking
logic. */
#ifdef TX_ENABLE_STACK_CHECKING
#undef TX_DISABLE_STACK_FILLING
#endif
/* Define the TX_THREAD control block extensions for this port. The main reason
for the multiple macros is so that backward compatibility can be maintained with
existing ThreadX kernel awareness modules. */
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
#define TX_BLOCK_POOL_EXTENSION
#define TX_BYTE_POOL_EXTENSION
#define TX_EVENT_FLAGS_GROUP_EXTENSION
#define TX_MUTEX_EXTENSION
#define TX_QUEUE_EXTENSION
#define TX_SEMAPHORE_EXTENSION
#define TX_TIMER_EXTENSION
/* Define the user extension field of the thread control block. Nothing
additional is needed for this port so it is defined as white space. */
#ifndef TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
tx_thread_shell_entry, and tx_thread_terminate. */
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
/* Define the ThreadX object creation extensions for the remaining objects. */
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
/* Define the ThreadX object deletion extensions for the remaining objects. */
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define ThreadX interrupt lockout and restore macros for protection on
access of critical kernel information. The restore interrupt macro must
restore the interrupt posture of the running thread prior to the value
present prior to the disable macro. In most cases, the save area macro
is used to define a local function save area for the disable and restore
macros. */
#ifdef TX_DISABLE_INLINE
unsigned int _tx_thread_interrupt_control(unsigned int new_posture);
#define TX_INTERRUPT_SAVE_AREA register int interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
#else
#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save;
#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
#endif
/* Define the interrupt lockout macros for each ThreadX object. */
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
#define TX_BYTE_POOL_DISABLE TX_DISABLE
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
#define TX_MUTEX_DISABLE TX_DISABLE
#define TX_QUEUE_DISABLE TX_DISABLE
#define TX_SEMAPHORE_DISABLE TX_DISABLE
/* Define the version ID of ThreadX. This may be utilized by the application. */
#ifdef TX_THREAD_INIT
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX RISC-V32/IAR Version G6.1 *";
#else
extern CHAR _tx_version_id[];
#endif
#endif

View File

@@ -0,0 +1,243 @@
Microsoft's Azure RTOS ThreadX for RISC-V
32-bit Mode
Using the IAR Tools
1. Building the ThreadX run-time Library
Building the ThreadX library is easy. First, open the Azure RTOS workspace
azure_rtos.eww. Next, make the tx.ewp project the "active project" in the
IAR Embedded Workbench and select the "Make" button. You should observe
assembly and compilation of a series of ThreadX source files. This
results in the ThreadX run-time library file tx.a, which is needed by
the application.
2. Demonstration System
The ThreadX demonstration is designed to execute under the IAR
Windows-based RISC-V simulator.
Building the demonstration is easy; simply make the sample_threadx.ewp project
the "active project" in the IAR Embedded Workbench and select the
"Make" button.
You should observe the compilation of sample_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file sample_threadx.out is a
binary file that can be downloaded and executed on IAR's RISC-V simulator.
3. System Initialization
The entry point in ThreadX for the RISC-V using IAR tools is at label
__iar_program_start. This is defined within the IAR compiler's startup code. In
addition, this is where all static and global preset C variable
initialization processing takes place.
The ThreadX tx_initialize_low_level.s file is responsible for setting up
various system data structures, and a periodic timer interrupt source.
The _tx_initialize_low_level function inside of tx_initialize_low_level.s
also determines the first available address for use by the application, which
is supplied as the sole input parameter to your application definition function,
tx_application_define. To accomplish this, a section is created in
tx_initialize_low_level.s called FREE_MEM, which must be located after all
other RAM sections in memory.
4. Register Usage and Stack Frames
The IAR RISC-V compiler assumes that registers t0-t6 and a0-a7 are scratch
registers for each function. All other registers used by a C function must
be preserved by the function. ThreadX takes advantage of this in situations
where a context switch happens as a result of making a ThreadX service call
(which is itself a C function). In such cases, the saved context of a thread
is only the non-scratch registers.
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have one of these two types of stack frames. The top
of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
associated thread control block TX_THREAD.
Offset Interrupted Stack Frame Non-Interrupt Stack Frame
0x00 1 0
0x04 s11 (x27) s11 (x27)
0x08 s10 (x26) s10 (x26)
0x0C s9 (x25) s9 (x25)
0x10 s8 (x24) s8 (x24)
0x14 s7 (x23) s7 (x23)
0x18 s6 (x22) s6 (x22)
0x1C s5 (x21) s5 (x21)
0x20 s4 (x20) s4 (x20)
0x24 s3 (x19) s3 (x19)
0x28 s2 (x18) s2 (x18)
0x2C s1 (x9) s1 (x9)
0x30 s0 (x8) s0 (x8)
0x34 t6 (x31) ra (x1)
0x38 t5 (x30) mstatus
0x3C t4 (x29) fs0
0x40 t3 (x28) fs1
0x44 t2 (x7) fs2
0x48 t1 (x6) fs3
0x4C t0 (x5) fs4
0x50 a7 (x17) fs5
0x54 a6 (x16) fs6
0x58 a5 (x15) fs7
0x5C a4 (x14) fs8
0x60 a3 (x13) fs9
0x64 a2 (x12) fs10
0x68 a1 (x11) fs11
0x6C a0 (x10) fcsr
0x70 ra (x1)
0x74 reserved
0x78 mepc
#if __iar_riscv_base_isa == rv32e
0x7C ft0
0x80 ft1
0x84 ft2
0x88 ft3
0x8C ft4
0x90 ft5
0x94 ft6
0x98 ft7
0x9C fs0
0xA0 fs1
0xA4 fa0
0xA8 fa1
0xAC fa2
0xB0 fa3
0xB4 fa4
0xB8 fa5
0xBC fa6
0xC0 fa7
0xC4 fs2
0xC8 fs3
0xCC fs4
0xD0 fs5
0xD4 fs6
0xD8 fs7
0xDC fs8
0xE0 fs9
0xE4 fs10
0xE8 fs11
0xEC ft8
0xF0 ft9
0xF4 ft10
0xF8 ft11
0xFC fcsr
#endif
5. Improving Performance
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make ThreadX run faster, you can change the project
options to disable debug information and enable the desired
compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
defined before tx_api.h is included.
6. Interrupt Handling
ThreadX provides complete and high-performance interrupt handling for RISC-V
targets.The ThreadX general exception handler sample is defined as follows,
where "*" represents the interrupt vector number:
PUBLIC _sample_interrupt_handler
PUBLIC __minterrupt_00000*
EXTWEAK __require_minterrupt_vector_table
_sample_interrupt_handler:
__minterrupt_00000*:
REQUIRE __require_minterrupt_vector_table
/* Before calling _tx_thread_context_save, we have to allocate an interrupt
stack frame and save the current value of x1 (ra). */
#if __iar_riscv_base_isa == rv32e
addi sp, sp, -260 ; Allocate space for all registers - with floating point enabled
#else
addi sp, sp, -128 ; Allocate space for all registers - without floating point enabled
#endif
sw x1, 0x70(sp) ; Store RA
call _tx_thread_context_save ; Call ThreadX context save
/* Call your ISR processing here! */
call your_ISR_processing
/* Timer interrupt processing is done, jump to ThreadX context restore. */
j _tx_thread_context_restore ; Jump to ThreadX context restore function. Note: this does not return!
Some additional conditions:
1. In the project settings Linker -> Extra Options, --auto_vector_setup should be defined.
2. The project linker control file should have the following sections to include the vector table:
define block MVECTOR with alignment = 128 { ro section .mintvec };
if (isdefinedsymbol(_uses_clic))
{
define block MINTERRUPT with alignment = 128 { ro section .mtext };
define block MINTERRUPTS { block MVECTOR,
block MINTERRUPT };
}
else
{
define block MINTERRUPTS with maximum size = 64k { ro section .mtext,
midway block MVECTOR };
}
6.1 Sample Timer ISR
The following sample timer ISR using vector 7 is defined in tx_initialize_low_level.s such that timer
functionality is available under IAR simulation:
PUBLIC _tx_timer_interrupt_handler
PUBLIC __minterrupt_000007
EXTWEAK __require_minterrupt_vector_table
_tx_timer_interrupt_handler:
__minterrupt_000007:
REQUIRE __require_minterrupt_vector_table
/* Before calling _tx_thread_context_save, we have to allocate an interrupt
stack frame and save the current value of x1 (ra). */
#if __iar_riscv_base_isa == rv32e
addi sp, sp, -260 ; Allocate space for all registers - with floating point enabled
#else
addi sp, sp, -128 ; Allocate space for all registers - without floating point enabled
#endif
sw x1, 0x70(sp) ; Store RA
call _tx_thread_context_save ; Call ThreadX context save
/* Call the ThreadX timer routine. */
call _tx_timer_interrupt ; Call timer interrupt handler
/* Timer interrupt processing is done, jump to ThreadX context restore. */
j _tx_thread_context_restore ; Jump to ThreadX context restore function. Note: this does not return!
7. Revision History
For generic code revision information, please refer to the readme_threadx_generic.txt
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
08/09/2020 Initial ThreadX version for RISC-V using IAR Tools.
Copyright(c) 1996-2020 Microsoft Corporation
https://azure.com/rtos

View File

@@ -0,0 +1,130 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Initialize */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_timer.h" */
EXTERN _tx_thread_system_stack_ptr
EXTERN _tx_initialize_unused_memory
EXTERN _tx_thread_context_save
EXTERN _tx_thread_context_restore
EXTERN _tx_timer_interrupt
RSEG FREE_MEM:DATA
PUBLIC __tx_free_memory_start
__tx_free_memory_start:
DS32 4
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_initialize_low_level RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for any low-level processor */
/* initialization, including setting up interrupt vectors, setting */
/* up a periodic timer interrupt source, saving the system stack */
/* pointer for use in ISR processing later, and finding the first */
/* available RAM memory address for tx_application_define. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_initialize_low_level(VOID)
{ */
PUBLIC _tx_initialize_low_level
_tx_initialize_low_level:
sw sp, _tx_thread_system_stack_ptr, t0 ; Save system stack pointer
la t0, __tx_free_memory_start ; Pickup first free address
sw t0, _tx_initialize_unused_memory, t1 ; Save unused memory address
ret
/* Define the actual timer interrupt/exception handler. */
PUBLIC _tx_timer_interrupt_handler
PUBLIC __minterrupt_000007
EXTWEAK __require_minterrupt_vector_table
_tx_timer_interrupt_handler:
__minterrupt_000007:
REQUIRE __require_minterrupt_vector_table
/* Before calling _tx_thread_context_save, we have to allocate an interrupt
stack frame and save the current value of x1 (ra). */
#if __iar_riscv_base_isa == rv32e
addi sp, sp, -260 ; Allocate space for all registers - with floating point enabled
#else
addi sp, sp, -128 ; Allocate space for all registers - without floating point enabled
#endif
sw x1, 0x70(sp) ; Store RA
call _tx_thread_context_save ; Call ThreadX context save
/* Call the ThreadX timer routine. */
call _tx_timer_interrupt ; Call timer interrupt handler
/* Timer interrupt processing is done, jump to ThreadX context restore. */
j _tx_thread_context_restore ; Jump to ThreadX context restore function. Note: this does not return!
END

View File

@@ -0,0 +1,344 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h"
#include "tx_timer.h" */
EXTERN _tx_thread_execute_ptr
EXTERN _tx_thread_current_ptr
EXTERN _tx_timer_time_slice
EXTERN _tx_thread_preempt_disable
EXTERN _tx_thread_schedule
EXTERN _tx_thread_system_state
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
EXTERN _tx_execution_isr_exit
#endif
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_restore RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function restores the interrupt context if it is processing a */
/* nested interrupt. If not, it returns to the interrupt thread if no */
/* preemption is necessary. Otherwise, if preemption is necessary or */
/* if no thread was running, the function returns to the scheduler. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling routine */
/* */
/* CALLED BY */
/* */
/* ISRs Interrupt Service Routines */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_thread_context_restore(VOID)
{ */
PUBLIC _tx_thread_context_restore
_tx_thread_context_restore:
/* Lockout interrupts. */
csrci mstatus, 0x08 ; Disable interrupts
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_isr_exit ; Call the ISR execution exit function
#endif
/* Determine if interrupts are nested. */
/* if (--_tx_thread_system_state)
{ */
la t0, _tx_thread_system_state ; Pickup addr of nested interrupt count
lw t1, 0(t0) ; Pickup nested interrupt count
addi t1, t1, -1 ; Decrement the nested interrupt counter
sw t1, 0(t0) ; Store new nested count
beqz t1, _tx_thread_not_nested_restore ; If 0, not nested restore
/* Interrupts are nested. */
/* Just recover the saved registers and return to the point of
interrupt. */
#if __iar_riscv_base_isa == rv32e
/* Recover floating point registers. */
flw f0, 0x7C(sp) ; Recover ft0
flw f1, 0x80(sp) ; Recover ft1
flw f2, 0x84(sp) ; Recover ft2
flw f3, 0x88(sp) ; Recover ft3
flw f4, 0x8C(sp) ; Recover ft4
flw f5, 0x90(sp) ; Recover ft5
flw f6, 0x94(sp) ; Recover ft6
flw f7, 0x98(sp) ; Recover ft7
flw f10,0xA4(sp) ; Recover fa0
flw f11,0xA8(sp) ; Recover fa1
flw f12,0xAC(sp) ; Recover fa2
flw f13,0xB0(sp) ; Recover fa3
flw f14,0xB4(sp) ; Recover fa4
flw f15,0xB8(sp) ; Recover fa5
flw f16,0xBC(sp) ; Recover fa6
flw f17,0xC0(sp) ; Recover fa7
flw f28,0xEC(sp) ; Recover ft8
flw f29,0xF0(sp) ; Recover ft9
flw f30,0xF4(sp) ; Recover ft10
flw f31,0xF8(sp) ; Recover ft11
lw t0, 0xFC(sp) ; Recover fcsr
csrw fcsr, t0 ;
#endif
/* Recover standard registers. */
/* Restore registers,
Skip global pointer because that does not change
Also skip the saved registers since they have been restored by any function we called.
Except s0 since we use it ourselves. */
lw t0, 0x78(sp) ; Recover mepc
csrw mepc, t0 ; Setup mepc
li t0, 0x1880 ; Prepare MPIP
csrw mstatus, t0 ; Enable MPIP
lw x1, 0x70(sp) ; Recover RA
lw x5, 0x4C(sp) ; Recover t0
lw x6, 0x48(sp) ; Recover t1
lw x7, 0x44(sp) ; Recover t2
lw x8, 0x30(sp) ; Recover s0
lw x10, 0x6C(sp) ; Recover a0
lw x11, 0x68(sp) ; Recover a1
lw x12, 0x64(sp) ; Recover a2
lw x13, 0x60(sp) ; Recover a3
lw x14, 0x5C(sp) ; Recover a4
lw x15, 0x58(sp) ; Recover a5
lw x16, 0x54(sp) ; Recover a6
lw x17, 0x50(sp) ; Recover a7
lw x28, 0x40(sp) ; Recover t3
lw x29, 0x3C(sp) ; Recover t4
lw x30, 0x38(sp) ; Recover t5
lw x31, 0x34(sp) ; Recover t6
#if __iar_riscv_base_isa == rv32e
addi sp, sp, 260 ; Recover stack frame - with floating point enabled
#else
addi sp, sp, 128 ; Recover stack frame - without floating point enabled
#endif
mret ; Return to point of interrupt
/* } */
_tx_thread_not_nested_restore:
/* Determine if a thread was interrupted and no preemption is required. */
/* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|| (_tx_thread_preempt_disable))
{ */
lw t1, _tx_thread_current_ptr ; Pickup current thread pointer
beqz t1, _tx_thread_idle_system_restore ; If NULL, idle system restore
lw t2, _tx_thread_preempt_disable ; Pickup preempt disable flag
bgtz t2, _tx_thread_no_preempt_restore ; If set, restore interrupted thread
lw t2, _tx_thread_execute_ptr ; Pickup thread execute pointer
bne t1, t2, _tx_thread_preempt_restore ; If higher-priority thread is ready, preempt
_tx_thread_no_preempt_restore:
/* Restore interrupted thread or ISR. */
/* Pickup the saved stack pointer. */
/* SP = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
lw sp, 8(t1) ; Switch back to thread's stack
#if __iar_riscv_base_isa == rv32e
/* Recover floating point registers. */
flw f0, 0x7C(sp) ; Recover ft0
flw f1, 0x80(sp) ; Recover ft1
flw f2, 0x84(sp) ; Recover ft2
flw f3, 0x88(sp) ; Recover ft3
flw f4, 0x8C(sp) ; Recover ft4
flw f5, 0x90(sp) ; Recover ft5
flw f6, 0x94(sp) ; Recover ft6
flw f7, 0x98(sp) ; Recover ft7
flw f10,0xA4(sp) ; Recover fa0
flw f11,0xA8(sp) ; Recover fa1
flw f12,0xAC(sp) ; Recover fa2
flw f13,0xB0(sp) ; Recover fa3
flw f14,0xB4(sp) ; Recover fa4
flw f15,0xB8(sp) ; Recover fa5
flw f16,0xBC(sp) ; Recover fa6
flw f17,0xC0(sp) ; Recover fa7
flw f28,0xEC(sp) ; Recover ft8
flw f29,0xF0(sp) ; Recover ft9
flw f30,0xF4(sp) ; Recover ft10
flw f31,0xF8(sp) ; Recover ft11
lw t0, 0xFC(sp) ; Recover fcsr
csrw fcsr, t0 ;
#endif
/* Recover the saved context and return to the point of interrupt. */
/* Recover standard registers. */
/* Restore registers,
Skip global pointer because that does not change */
lw t0, 0x78(sp) ; Recover mepc
csrw mepc, t0 ; Setup mepc
li t0, 0x1880 ; Prepare MPIP
csrw mstatus, t0 ; Enable MPIP
lw x1, 0x70(sp) ; Recover RA
lw x5, 0x4C(sp) ; Recover t0
lw x6, 0x48(sp) ; Recover t1
lw x7, 0x44(sp) ; Recover t2
lw x8, 0x30(sp) ; Recover s0
lw x10, 0x6C(sp) ; Recover a0
lw x11, 0x68(sp) ; Recover a1
lw x12, 0x64(sp) ; Recover a2
lw x13, 0x60(sp) ; Recover a3
lw x14, 0x5C(sp) ; Recover a4
lw x15, 0x58(sp) ; Recover a5
lw x16, 0x54(sp) ; Recover a6
lw x17, 0x50(sp) ; Recover a7
lw x28, 0x40(sp) ; Recover t3
lw x29, 0x3C(sp) ; Recover t4
lw x30, 0x38(sp) ; Recover t5
lw x31, 0x34(sp) ; Recover t6
#if __iar_riscv_base_isa == rv32e
addi sp, sp, 260 ; Recover stack frame - with floating point enabled
#else
addi sp, sp, 128 ; Recover stack frame - without floating point enabled
#endif
mret ; Return to point of interrupt
/* }
else
{ */
_tx_thread_preempt_restore:
/* Instead of directly activating the thread again, ensure we save the
entire stack frame by saving the remaining registers. */
lw t0, 8(t1) ; Pickup thread's stack pointer
ori t3, x0, 1 ; Build interrupt stack type
sw t3, 0(t0) ; Store stack type
#if __iar_riscv_base_isa == rv32e
/* Store floating point preserved registers. */
fsw f8, 0x9C(t0) ; Store fs0
fsw f9, 0xA0(t0) ; Store fs1
fsw f18, 0xC4(t0) ; Store fs2
fsw f19, 0xC8(t0) ; Store fs3
fsw f20, 0xCC(t0) ; Store fs4
fsw f21, 0xD0(t0) ; Store fs5
fsw f22, 0xD4(t0) ; Store fs6
fsw f23, 0xD8(t0) ; Store fs7
fsw f24, 0xDC(t0) ; Store fs8
fsw f25, 0xE0(t0) ; Store fs9
fsw f26, 0xE4(t0) ; Store fs10
fsw f27, 0xE8(t0) ; Store fs11
#endif
/* Store standard preserved registers. */
sw x9, 0x2C(t0) ; Store s1
sw x18, 0x28(t0) ; Store s2
sw x19, 0x24(t0) ; Store s3
sw x20, 0x20(t0) ; Store s4
sw x21, 0x1C(t0) ; Store s5
sw x22, 0x18(t0) ; Store s6
sw x23, 0x14(t0) ; Store s7
sw x24, 0x10(t0) ; Store s8
sw x25, 0x0C(t0) ; Store s9
sw x26, 0x08(t0) ; Store s10
sw x27, 0x04(t0) ; Store s11
; Note: s0 is already stored!
/* Save the remaining time-slice and disable it. */
/* if (_tx_timer_time_slice)
{ */
la t0, _tx_timer_time_slice ; Pickup time slice variable address
lw t2, 0(t0) ; Pickup time slice
beqz t2, _tx_thread_dont_save_ts ; If 0, skip time slice processing
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice
_tx_timer_time_slice = 0; */
sw t2, 24(t1) ; Save current time slice
sw x0, 0(t0) ; Clear global time slice
/* } */
_tx_thread_dont_save_ts:
/* Clear the current task pointer. */
/* _tx_thread_current_ptr = TX_NULL; */
/* Return to the scheduler. */
/* _tx_thread_schedule(); */
sw x0, _tx_thread_current_ptr, t0 ; Clear current thread pointer*/
/* } */
_tx_thread_idle_system_restore:
/* Just return back to the scheduler! */
j _tx_thread_schedule ; Return to scheduler
/* } */
END

View File

@@ -0,0 +1,263 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h"
#include "tx_timer.h" */
EXTERN _tx_thread_current_ptr
EXTERN _tx_thread_system_state
EXTERN _tx_thread_system_stack_ptr
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
EXTERN _tx_execution_isr_enter
#endif
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_save RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function saves the context of an executing thread in the */
/* beginning of interrupt processing. The function also ensures that */
/* the system stack is used upon return to the calling ISR. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* ISRs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_thread_context_save(VOID)
{ */
PUBLIC _tx_thread_context_save
_tx_thread_context_save:
/* Upon entry to this routine, it is assumed that interrupts are locked
out and the interrupt stack fame has been allocated and x1 (ra) has
been saved on the stack. */
sw x5, 0x4C(sp) ; First store t0 and t1
sw x6, 0x48(sp)
la x5, _tx_thread_system_state ; Pickup address of system state
lw x6, 0(x5) ; Pickup system state
/* Check for a nested interrupt condition. */
/* if (_tx_thread_system_state++)
{ */
beqz x6, _tx_thread_not_nested_save ; If 0, first interrupt condition
addi x6, x6, 1 ; Increment the interrupt counter
sw x6, 0(x5) ; Store the interrupt counter
/* Nested interrupt condition.
Save the reset of the scratch registers on the stack and return to the
calling ISR. */
sw x7, 0x44(sp) ; Store t2
sw x8, 0x30(sp) ; Store s0
sw x10, 0x6C(sp) ; Store a0
sw x11, 0x68(sp) ; Store a1
sw x12, 0x64(sp) ; Store a2
sw x13, 0x60(sp) ; Store a3
sw x14, 0x5C(sp) ; Store a4
sw x15, 0x58(sp) ; Store a5
sw x16, 0x54(sp) ; Store a6
sw x17, 0x50(sp) ; Store a7
sw x28, 0x40(sp) ; Store t3
sw x29, 0x3C(sp) ; Store t4
sw x30, 0x38(sp) ; Store t5
sw x31, 0x34(sp) ; Store t6
csrr t0, mepc ; Load exception program counter
sw t0, 0x78(sp) ; Save it on the stack
#if __iar_riscv_base_isa == rv32e
/* Save floating point scratch registers. */
fsw f0, 0x7C(sp) ; Store ft0
fsw f1, 0x80(sp) ; Store ft1
fsw f2, 0x84(sp) ; Store ft2
fsw f3, 0x88(sp) ; Store ft3
fsw f4, 0x8C(sp) ; Store ft4
fsw f5, 0x90(sp) ; Store ft5
fsw f6, 0x94(sp) ; Store ft6
fsw f7, 0x98(sp) ; Store ft7
fsw f10,0xA4(sp) ; Store fa0
fsw f11,0xA8(sp) ; Store fa1
fsw f12,0xAC(sp) ; Store fa2
fsw f13,0xB0(sp) ; Store fa3
fsw f14,0xB4(sp) ; Store fa4
fsw f15,0xB8(sp) ; Store fa5
fsw f16,0xBC(sp) ; Store fa6
fsw f17,0xC0(sp) ; Store fa7
fsw f28,0xEC(sp) ; Store ft8
fsw f29,0xF0(sp) ; Store ft9
fsw f30,0xF4(sp) ; Store ft10
fsw f31,0xF8(sp) ; Store ft11
csrr t0, fcsr
sw t0, 0xFC(sp) ; Store fcsr
#endif
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_isr_enter ; Call the ISR execution enter function
#endif
ret ; Return to calling ISR
_tx_thread_not_nested_save:
/* } */
/* Otherwise, not nested, check to see if a thread was running. */
/* else if (_tx_thread_current_ptr)
{ */
addi x6, x6, 1 ; Increment the interrupt counter
sw x6, 0(x5) ; Store the interrupt counter
/* Not nested: Find the user thread that was running and load our SP */
lw x5, _tx_thread_current_ptr ; Pickup current thread pointer
beqz x5, _tx_thread_idle_system_save ; If NULL, idle system was interrupted
/* Save the standard scratch registers. */
sw x7, 0x44(sp) ; Store t2
sw x8, 0x30(sp) ; Store s0
sw x10, 0x6C(sp) ; Store a0
sw x11, 0x68(sp) ; Store a1
sw x12, 0x64(sp) ; Store a2
sw x13, 0x60(sp) ; Store a3
sw x14, 0x5C(sp) ; Store a4
sw x15, 0x58(sp) ; Store a5
sw x16, 0x54(sp) ; Store a6
sw x17, 0x50(sp) ; Store a7
sw x28, 0x40(sp) ; Store t3
sw x29, 0x3C(sp) ; Store t4
sw x30, 0x38(sp) ; Store t5
sw x31, 0x34(sp) ; Store t6
csrr t0, mepc ; Load exception program counter
sw t0, 0x78(sp) ; Save it on the stack
#if __iar_riscv_base_isa == rv32e
/* Save floating point scratch registers. */
fsw f0, 0x7C(sp) ; Store ft0
fsw f1, 0x80(sp) ; Store ft1
fsw f2, 0x84(sp) ; Store ft2
fsw f3, 0x88(sp) ; Store ft3
fsw f4, 0x8C(sp) ; Store ft4
fsw f5, 0x90(sp) ; Store ft5
fsw f6, 0x94(sp) ; Store ft6
fsw f7, 0x98(sp) ; Store ft7
fsw f10,0xA4(sp) ; Store fa0
fsw f11,0xA8(sp) ; Store fa1
fsw f12,0xAC(sp) ; Store fa2
fsw f13,0xB0(sp) ; Store fa3
fsw f14,0xB4(sp) ; Store fa4
fsw f15,0xB8(sp) ; Store fa5
fsw f16,0xBC(sp) ; Store fa6
fsw f17,0xC0(sp) ; Store fa7
fsw f28,0xEC(sp) ; Store ft8
fsw f29,0xF0(sp) ; Store ft9
fsw f30,0xF4(sp) ; Store ft10
fsw f31,0xF8(sp) ; Store ft11
csrr t0, fcsr
sw t0, 0xFC(sp) ; Store fcsr
#endif
/* Save the current stack pointer in the thread's control block. */
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
/* Switch to the system stack. */
/* sp = _tx_thread_system_stack_ptr; */
lw t1, _tx_thread_current_ptr ; Pickup current thread pointer
sw sp, 8(t1) ; Save stack pointer*/
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/* _tx_execution_isr_enter is called with thread stack pointer */
call _tx_execution_isr_enter ; Call the ISR execution enter function
#endif
lw sp, _tx_thread_system_stack_ptr ; Switch to system stack
ret ; Return to calling ISR
/* }
else
{ */
_tx_thread_idle_system_save:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_isr_enter ; Call the ISR execution enter function
#endif
/* Interrupt occurred in the scheduling loop. */
/* }
} */
#if __iar_riscv_base_isa == rv32e
addi sp, sp, 260 ; Recover stack frame - with floating point enabled
#else
addi sp, sp, 128 ; Recover the reserved stack space
#endif
ret ; Return to calling ISR
END

View File

@@ -0,0 +1,94 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h" */
RETURN_MASK DEFINE 0x0000000F
SET_SR_MASK DEFINE 0xFFFFFFF0
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* UINT _tx_thread_interrupt_control(UINT new_posture)
{ */
PUBLIC _tx_thread_interrupt_control
_tx_thread_interrupt_control:
/* Pickup current interrupt lockout posture. */
csrr t0, mstatus
mv t1, t0 ; Save original mstatus for return
/* Apply the new interrupt posture. */
li t2, SET_SR_MASK ; Build set SR mask
and t0, t0, t2 ; Isolate interrupt lockout bits
or t0, t0, a0 ; Put new lockout bits in
csrw mstatus, t0
andi a0, t1, RETURN_MASK ; Return original mstatus.
ret
/* } */
END

View File

@@ -0,0 +1,274 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h"
#include "tx_timer.h" */
EXTERN _tx_thread_execute_ptr
EXTERN _tx_thread_current_ptr
EXTERN _tx_timer_time_slice
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
EXTERN _tx_execution_thread_enter
#endif
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_schedule RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function waits for a thread control block pointer to appear in */
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
/* in the variable, the corresponding thread is resumed. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* _tx_thread_system_return Return to system from thread */
/* _tx_thread_context_restore Restore thread's context */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_thread_schedule(VOID)
{ */
PUBLIC _tx_thread_schedule
_tx_thread_schedule:
/* Enable interrupts. */
csrsi mstatus, 0x08 ; Enable interrupts
/* Wait for a thread to execute. */
/* do
{ */
la t0, _tx_thread_execute_ptr ; Pickup address of execute ptr
_tx_thread_schedule_loop:
lw t1, 0(t0) ; Pickup next thread to execute
beqz t1, _tx_thread_schedule_loop ; If NULL, wait for thread to execute
/* }
while(_tx_thread_execute_ptr == TX_NULL); */
/* Yes! We have a thread to execute. Lockout interrupts and
transfer control to it. */
csrci mstatus, 0x08 ; Lockout interrupts
/* Setup the current thread pointer. */
/* _tx_thread_current_ptr = _tx_thread_execute_ptr; */
la t0, _tx_thread_current_ptr ; Pickup current thread pointer address
sw t1, 0(t0) ; Set current thread pointer
/* Increment the run count for this thread. */
/* _tx_thread_current_ptr -> tx_thread_run_count++; */
lw t2, 4(t1) ; Pickup run count
lw t3, 24(t1) ; Pickup time slice value
addi t2, t2, 1 ; Increment run count
sw t2, 4(t1) ; Store new run count
/* Setup time-slice, if present. */
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */
la t2, _tx_timer_time_slice ; Pickup time-slice variable address
/* Switch to the thread's stack. */
/* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */
lw sp, 8(t1) ; Switch to thread's stack
sw t3, 0(t2) ; Store new time-slice*/
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_thread_enter ; Call the thread execution enter function
#endif
/* Determine if an interrupt frame or a synchronous task suspension frame
is present. */
lw t2, 0(sp) ; Pickup stack type
beqz t2, _tx_thread_synch_return ; If 0, solicited thread return
/* Determine if floating point registers need to be recovered. */
#if __iar_riscv_base_isa == rv32e
flw f0, 0x7C(sp) ; Recover ft0
flw f1, 0x80(sp) ; Recover ft1
flw f2, 0x84(sp) ; Recover ft2
flw f3, 0x88(sp) ; Recover ft3
flw f4, 0x8C(sp) ; Recover ft4
flw f5, 0x90(sp) ; Recover ft5
flw f6, 0x94(sp) ; Recover ft6
flw f7, 0x98(sp) ; Recover ft7
flw f8, 0x9C(sp) ; Recover fs0
flw f9, 0xA0(sp) ; Recover fs1
flw f10,0xA4(sp) ; Recover fa0
flw f11,0xA8(sp) ; Recover fa1
flw f12,0xAC(sp) ; Recover fa2
flw f13,0xB0(sp) ; Recover fa3
flw f14,0xB4(sp) ; Recover fa4
flw f15,0xB8(sp) ; Recover fa5
flw f16,0xBC(sp) ; Recover fa6
flw f17,0xC0(sp) ; Recover fa7
flw f18,0xC4(sp) ; Recover fs2
flw f19,0xC8(sp) ; Recover fs3
flw f20,0xCC(sp) ; Recover fs4
flw f21,0xD0(sp) ; Recover fs5
flw f22,0xD4(sp) ; Recover fs6
flw f23,0xD8(sp) ; Recover fs7
flw f24,0xDC(sp) ; Recover fs8
flw f25,0xE0(sp) ; Recover fs9
flw f26,0xE4(sp) ; Recover fs10
flw f27,0xE8(sp) ; Recover fs11
flw f28,0xEC(sp) ; Recover ft8
flw f29,0xF0(sp) ; Recover ft9
flw f30,0xF4(sp) ; Recover ft10
flw f31,0xF8(sp) ; Recover ft11
lw t0, 0xFC(sp) ; Recover fcsr
csrw fcsr, t0 ;
#endif
/* Recover standard registers. */
lw t0, 0x78(sp) ; Recover mepc
csrw mepc, t0 ; Store mepc
li t0, 0x1880 ; Prepare MPIP
csrw mstatus, t0 ; Enable MPIP
lw x1, 0x70(sp) ; Recover RA
lw x5, 0x4C(sp) ; Recover t0
lw x6, 0x48(sp) ; Recover t1
lw x7, 0x44(sp) ; Recover t2
lw x8, 0x30(sp) ; Recover s0
lw x9, 0x2C(sp) ; Recover s1
lw x10, 0x6C(sp) ; Recover a0
lw x11, 0x68(sp) ; Recover a1
lw x12, 0x64(sp) ; Recover a2
lw x13, 0x60(sp) ; Recover a3
lw x14, 0x5C(sp) ; Recover a4
lw x15, 0x58(sp) ; Recover a5
lw x16, 0x54(sp) ; Recover a6
lw x17, 0x50(sp) ; Recover a7
lw x18, 0x28(sp) ; Recover s2
lw x19, 0x24(sp) ; Recover s3
lw x20, 0x20(sp) ; Recover s4
lw x21, 0x1C(sp) ; Recover s5
lw x22, 0x18(sp) ; Recover s6
lw x23, 0x14(sp) ; Recover s7
lw x24, 0x10(sp) ; Recover s8
lw x25, 0x0C(sp) ; Recover s9
lw x26, 0x08(sp) ; Recover s10
lw x27, 0x04(sp) ; Recover s11
lw x28, 0x40(sp) ; Recover t3
lw x29, 0x3C(sp) ; Recover t4
lw x30, 0x38(sp) ; Recover t5
lw x31, 0x34(sp) ; Recover t6
#if __iar_riscv_base_isa == rv32e
addi sp, sp, 260 ; Recover stack frame - with floating point registers
#else
addi sp, sp, 128 ; Recover stack frame - without floating point registers
#endif
mret ; Return to point of interrupt
_tx_thread_synch_return:
#if __iar_riscv_base_isa == rv32e
flw f8, 0x3C(sp) ; Recover fs0
flw f9, 0x40(sp) ; Recover fs1
flw f18,0x44(sp) ; Recover fs2
flw f19,0x48(sp) ; Recover fs3
flw f20,0x4C(sp) ; Recover fs4
flw f21,0x50(sp) ; Recover fs5
flw f22,0x54(sp) ; Recover fs6
flw f23,0x58(sp) ; Recover fs7
flw f24,0x5C(sp) ; Recover fs8
flw f25,0x60(sp) ; Recover fs9
flw f26,0x64(sp) ; Recover fs10
flw f27,0x68(sp) ; Recover fs11
lw t0, 0x6C(sp) ; Recover fcsr
csrw fcsr, t0 ;
#endif
/* Recover standard preserved registers. */
/* Recover standard registers. */
lw x1, 0x34(sp) ; Recover RA
lw x8, 0x30(sp) ; Recover s0
lw x9, 0x2C(sp) ; Recover s1
lw x18, 0x28(sp) ; Recover s2
lw x19, 0x24(sp) ; Recover s3
lw x20, 0x20(sp) ; Recover s4
lw x21, 0x1C(sp) ; Recover s5
lw x22, 0x18(sp) ; Recover s6
lw x23, 0x14(sp) ; Recover s7
lw x24, 0x10(sp) ; Recover s8
lw x25, 0x0C(sp) ; Recover s9
lw x26, 0x08(sp) ; Recover s10
lw x27, 0x04(sp) ; Recover s11
lw t0, 0x38(sp) ; Recover mstatus
csrw mstatus, t0 ; Store mstatus, enables interrupt
#if __iar_riscv_base_isa == rv32e
addi sp, sp, 116 ; Recover stack frame
#else
addi sp, sp, 64 ; Recover stack frame
#endif
ret ; Return to thread
/* } */
END

View File

@@ -0,0 +1,240 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h" */
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_stack_build RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function builds a stack frame on the supplied thread's stack. */
/* The stack frame results in a fake interrupt return to the supplied */
/* function pointer. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread control blk */
/* function_ptr Pointer to return function */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_thread_create Create thread service */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
{ */
PUBLIC _tx_thread_stack_build
_tx_thread_stack_build:
/* Build a fake interrupt frame. The form of the fake interrupt stack
on the RISC-V RV32 should look like the following after it is built:
Stack Top: 1 (00) Interrupt stack frame type
x27 (04) Initial s11
x26 (08) Initial s10
x25 (12) Initial s9
x24 (16) Initial s8
x23 (20) Initial s7
x22 (24) Initial s6
x21 (28) Initial s5
x20 (32) Initial s4
x19 (36) Initial s3
x18 (40) Initial s2
x9 (44) Initial s1
x8 (48) Initial s0
x31 (52) Initial t6
x30 (56) Initial t5
x29 (60) Initial t4
x28 (64) Initial t3
x7 (68) Initial t2
x6 (72) Initial t1
x5 (76) Initial t0
x17 (80) Initial a7
x16 (84) Initial a6
x15 (88) Initial a5
x14 (92) Initial a4
x13 (96) Initial a3
x12 (100) Initial a2
x11 (104) Initial a1
x10 (108) Initial a0
x1 (112) Initial ra
mepc (120) Initial mepc
If floating point support:
f0 (124) Inital ft0
f1 (128) Inital ft1
f2 (132) Inital ft2
f3 (136) Inital ft3
f4 (140) Inital ft4
f5 (144) Inital ft5
f6 (148) Inital ft6
f7 (152) Inital ft7
f8 (156) Inital fs0
f9 (160) Inital fs1
f10 (164) Inital fa0
f11 (168) Inital fa1
f12 (172) Inital fa2
f13 (176) Inital fa3
f14 (180) Inital fa4
f15 (184) Inital fa5
f16 (188) Inital fa6
f17 (192) Inital fa7
f18 (196) Inital fs2
f19 (200) Inital fs3
f20 (204) Inital fs4
f21 (208) Inital fs5
f22 (212) Inital fs6
f23 (216) Inital fs7
f24 (220) Inital fs8
f25 (224) Inital fs9
f26 (228) Inital fs10
f27 (232) Inital fs11
f28 (236) Inital ft8
f29 (240) Inital ft9
f30 (244) Inital ft10
f31 (248) Inital ft11
fscr (252) Inital fscr
Stack Bottom: (higher memory address) */
lw t0, 16(a0) ; Pickup end of stack area
li t1, ~15 ; Build 16-byte alignment mask
and t0, t0, t1 ; Make sure 16-byte alignment
/* Actually build the stack frame. */
#if __iar_riscv_base_isa == rv32e
addi t0, t0, -260
#else
addi t0, t0, -128 ; Allocate space for the stack frame
#endif
li t1, 1 ; Build stack type
sw t1, 0(t0) ; Place stack type on the top
sw x0, 4(t0) ; Initial s11
sw x0, 8(t0) ; Initial s10
sw x0, 12(t0) ; Initial s9
sw x0, 16(t0) ; Initial s8
sw x0, 20(t0) ; Initial s7
sw x0, 24(t0) ; Initial s6
sw x0, 28(t0) ; Initial s5
sw x0, 32(t0) ; Initial s4
sw x0, 36(t0) ; Initial s3
sw x0, 40(t0) ; Initial s2
sw x0, 44(t0) ; Initial s1
sw x0, 48(t0) ; Initial s0
sw x0, 52(t0) ; Initial t6
sw x0, 56(t0) ; Initial t5
sw x0, 60(t0) ; Initial t4
sw x0, 64(t0) ; Initial t3
sw x0, 68(t0) ; Initial t2
sw x0, 72(t0) ; Initial t1
sw x0, 76(t0) ; Initial t0
sw x0, 80(t0) ; Initial a7
sw x0, 84(t0) ; Initial a6
sw x0, 88(t0) ; Initial a5
sw x0, 92(t0) ; Initial a4
sw x0, 96(t0) ; Initial a3
sw x0, 100(t0) ; Initial a2
sw x0, 104(t0) ; Initial a1
sw x0, 108(t0) ; Initial a0
sw x0, 112(t0) ; Initial ra
sw a1, 120(t0) ; Initial mepc
#if __iar_riscv_base_isa == rv32e
sw x0, 124(t0) ; Inital ft0
sw x0, 128(t0) ; Inital ft1
sw x0, 132(t0) ; Inital ft2
sw x0, 136(t0) ; Inital ft3
sw x0, 140(t0) ; Inital ft4
sw x0, 144(t0) ; Inital ft5
sw x0, 148(t0) ; Inital ft6
sw x0, 152(t0) ; Inital ft7
sw x0, 156(t0) ; Inital fs0
sw x0, 160(t0) ; Inital fs1
sw x0, 164(t0) ; Inital fa0
sw x0, 168(t0) ; Inital fa1
sw x0, 172(t0) ; Inital fa2
sw x0, 176(t0) ; Inital fa3
sw x0, 180(t0) ; Inital fa4
sw x0, 184(t0) ; Inital fa5
sw x0, 188(t0) ; Inital fa6
sw x0, 192(t0) ; Inital fa7
sw x0, 196(t0) ; Inital fs2
sw x0, 200(t0) ; Inital fs3
sw x0, 204(t0) ; Inital fs4
sw x0, 208(t0) ; Inital fs5
sw x0, 212(t0) ; Inital fs6
sw x0, 216(t0) ; Inital fs7
sw x0, 220(t0) ; Inital fs8
sw x0, 224(t0) ; Inital fs9
sw x0, 228(t0) ; Inital fs10
sw x0, 232(t0) ; Inital fs11
sw x0, 236(t0) ; Inital ft8
sw x0, 240(t0) ; Inital ft9
sw x0, 244(t0) ; Inital ft10
sw x0, 248(t0) ; Inital ft11
csrr a1, fcsr ; Read fcsr and use it for initial value for each thread
sw a1, 252(t0) ; Initial fscr
sw x0, 256(t0) ; Reserved word (0)
#else
sw x0, 124(t0) ; Reserved word (0)
#endif
/* Setup stack pointer. */
/* thread_ptr -> tx_thread_stack_ptr = t0; */
sw t0, 8(a0) ; Save stack pointer in thread's
ret ; control block and return
/* } */
END

View File

@@ -0,0 +1,184 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_thread.h"
#include "tx_timer.h" */
EXTERN _tx_thread_execute_ptr
EXTERN _tx_thread_current_ptr
EXTERN _tx_timer_time_slice
EXTERN _tx_thread_system_stack_ptr
EXTERN _tx_thread_schedule
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
EXTERN _tx_execution_thread_exit
#endif
SECTION `.text`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_system_return RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function is target processor specific. It is used to transfer */
/* control from a thread back to the system. Only a minimal context */
/* is saved since the compiler assumes temp registers are going to get */
/* slicked by a function call anyway. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling loop */
/* */
/* CALLED BY */
/* */
/* ThreadX components */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_thread_system_return(VOID)
{ */
PUBLIC _tx_thread_system_return
_tx_thread_system_return:
/* Save minimal context on the stack. */
#if __iar_riscv_base_isa == rv32e
addi sp, sp, -116 ; Allocate space on the stack - with floating point enabled
#else
addi sp, sp, -64 ; Allocate space on the stack - without floating point enabled
#endif
#if __iar_riscv_base_isa == rv32e
/* Store floating point preserved registers. */
fsw f8, 0x3C(sp) ; Store fs0
fsw f9, 0x40(sp) ; Store fs1
fsw f18, 0x44(sp) ; Store fs2
fsw f19, 0x48(sp) ; Store fs3
fsw f20, 0x4C(sp) ; Store fs4
fsw f21, 0x50(sp) ; Store fs5
fsw f22, 0x54(sp) ; Store fs6
fsw f23, 0x58(sp) ; Store fs7
fsw f24, 0x5C(sp) ; Store fs8
fsw f25, 0x60(sp) ; Store fs9
fsw f26, 0x64(sp) ; Store fs10
fsw f27, 0x68(sp) ; Store fs11
csrr t0, fcsr
sw t0, 0x6C(sp) ; Store fcsr
#endif
sw x0, 0(sp) ; Solicited stack type
sw x1, 0x34(sp) ; Save RA
sw x8, 0x30(sp) ; Save s0
sw x9, 0x2C(sp) ; Save s1
sw x18, 0x28(sp) ; Save s2
sw x19, 0x24(sp) ; Save s3
sw x20, 0x20(sp) ; Save s4
sw x21, 0x1C(sp) ; Save s5
sw x22, 0x18(sp) ; Save s6
sw x23, 0x14(sp) ; Save s7
sw x24, 0x10(sp) ; Save s8
sw x25, 0x0C(sp) ; Save s9
sw x26, 0x08(sp) ; Save s10
sw x27, 0x04(sp) ; Save s11
csrr t0, mstatus ; Pickup mstatus
sw t0, 0x38(sp) ; Save mstatus
/* Lockout interrupts. - will be enabled in _tx_thread_schedule */
csrci mstatus, 0xF
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
call _tx_execution_thread_exit ; Call the thread execution exit function
#endif
la t0, _tx_thread_current_ptr ; Pickup address of pointer
lw t1, 0(t0) ; Pickup current thread pointer
la t2,_tx_thread_system_stack_ptr ; Pickup stack pointer address
/* Save current stack and switch to system stack. */
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = SP;
SP = _tx_thread_system_stack_ptr; */
sw sp, 8(t1) ; Save stack pointer
lw sp, 0(t2) ; Switch to system stack
/* Determine if the time-slice is active. */
/* if (_tx_timer_time_slice)
{ */
la t4, _tx_timer_time_slice ; Pickup time slice variable addr
lw t3, 0(t4) ; Pickup time slice value
la t2, _tx_thread_schedule ; Pickup address of scheduling loop
beqz t3, _tx_thread_dont_save_ts ; If no time-slice, don't save it
/* Save time-slice for the thread and clear the current time-slice. */
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
_tx_timer_time_slice = 0; */
sw t3, 24(t1) ; Save current time-slice for thread
sw x0, 0(t4) ; Clear time-slice variable
/* } */
_tx_thread_dont_save_ts:
/* Clear the current thread pointer. */
/* _tx_thread_current_ptr = TX_NULL; */
sw x0, 0(t0) ; Clear current thread pointer
jr t2 ; Return to thread scheduler
/* } */
END

View File

@@ -0,0 +1,234 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
/* #define TX_SOURCE_CODE */
/* Include necessary system files. */
/* #include "tx_api.h"
#include "tx_timer.h"
#include "tx_thread.h" */
EXTERN _tx_timer_system_clock
EXTERN _tx_timer_time_slice
EXTERN _tx_timer_expired_time_slice
EXTERN _tx_timer_current_ptr
EXTERN _tx_timer_expired
EXTERN _tx_timer_list_end
EXTERN _tx_timer_list_start
EXTERN _tx_timer_expiration_process
EXTERN _tx_thread_time_slice
SECTION `.mtext`:CODE:REORDER:NOROOT(2)
CODE
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt RISC-V32/IAR */
/* 6.1 */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Tom van Leeuwen, Technolution B.V. */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* interrupt context save/restore functions are called along with the */
/* expiration functions. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* */
/**************************************************************************/
/* VOID _tx_timer_interrupt(VOID)
{ */
PUBLIC _tx_timer_interrupt
_tx_timer_interrupt:
/* Increment the system clock. */
/* _tx_timer_system_clock++; */
la t0, _tx_timer_system_clock ; Pickup address of system clock
lw t1, 0(t0) ; Pickup system clock
la t2, _tx_timer_time_slice ; Pickup address of time slice
lw t3, 0(t2) ; Pickup time slice
addi t1, t1, 1 ; Increment system clock
sw t1, 0(t0) ; Store new system clock
li t6, 0 ; Clear local expired flag
/* Test for time-slice expiration. */
/* if (_tx_timer_time_slice)
{ */
beqz t3, _tx_timer_no_time_slice ; If 0, skip time slice processing
addi t3, t3, -1 ; Decrement the time slice
/* Decrement the time_slice. */
/* _tx_timer_time_slice--; */
sw t3, 0(t2) ; Store new time slice
/* Check for expiration. */
/* if (__tx_timer_time_slice == 0) */
bgtz t3, _tx_timer_no_time_slice ; If not 0, has not expired yet
li t1, 1 ; Build expired flag
/* Set the time-slice expired flag. */
/* _tx_timer_expired_time_slice = TX_TRUE; */
la t4, _tx_timer_expired_time_slice ; Get address of expired flag
sw t1, 0(t4) ; Set expired flag
ori t6, t6, 1 ; Set local expired flag
/* } */
_tx_timer_no_time_slice:
/* Test for timer expiration. */
/* if (*_tx_timer_current_ptr)
{ */
la t0, _tx_timer_current_ptr ; Pickup address of current ptr
lw t1, 0(t0) ; Pickup current pointer
lw t3, 0(t1) ; Pickup the current timer entry
la t2, _tx_timer_expired ; Pickup address of timer expired flag
li t4, 1 ; Build TX_TRUE flag
beqz t3, _tx_timer_no_timer ; If NULL, no timer has expired
/* Set expiration flag. */
/* _tx_timer_expired = TX_TRUE; */
ori t6, t6, 2 ; Set local expired flag
sw t4, 0(t2) ; Set expired flag in memory
j _tx_timer_done ; Finished timer processing
/* }
else
{ */
_tx_timer_no_timer:
/* No timer expired, increment the timer pointer. */
/* _tx_timer_current_ptr++; */
/* Check for wrap-around. */
/* if (_tx_timer_current_ptr == _tx_timer_list_end) */
la t2, _tx_timer_list_end ; Pickup address of list end pointer
lw t3, 0(t2) ; Pickup actual list end
addi t1, t1, 4 ; Point to next timer entry
sw t1, 0(t0) ; Store new timer pointer
bne t1, t3, _tx_timer_skip_wrap ; If not same, good pointer
/* Wrap to beginning of list. */
/* _tx_timer_current_ptr = _tx_timer_list_start; */
la t2, _tx_timer_list_start ; Pickup address of list start pointer
lw t4, 0(t2) ; Pickup start of the list
sw t4, 0(t0) ; Store new timer pointer*/
_tx_timer_skip_wrap:
/* } */
_tx_timer_done:
/* See if anything has expired. */
/* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
{ */
beqz t6, _tx_timer_nothing_expired ; If nothing expired skip the rest
and t2, t6, 2 ; Isolate the timer expired bit
addi sp, sp, -16 ; Allocate some storage on the stack
sw t6, 0(sp) ; Save local expired flag
sw ra, 4(sp) ; Save ra
/* Did a timer expire? */
/* if (_tx_timer_expired)
{ */
beqz t2, _tx_timer_dont_activate ; No, timer not expired
/* Call the timer expiration processing. */
/* _tx_timer_expiration_process(void); */
call _tx_timer_expiration_process ; Call _tx_timer_expiration_process
lw t6, 0(sp) ; Recover local expired flag
/* } */
_tx_timer_dont_activate:
/* Did time slice expire? */
/* if (_tx_timer_expired_time_slice)
{ */
and t2, t6, 1 ; Is the timer expired bit set?
beqz t2, _tx_timer_not_ts_expiration ; If not, skip time slice processing
/* Time slice interrupted thread. */
/* _tx_thread_time_slice(); */
call _tx_thread_time_slice ; Call time slice
/* } */
_tx_timer_not_ts_expiration:
lw ra, 4(sp) ; Recover ra
addi sp, sp, 16 ; Recover stack space
/* } */
_tx_timer_nothing_expired:
ret
/* } */
END