Skip to content

Commit

Permalink
4_memory_challenge done
Browse files Browse the repository at this point in the history
  • Loading branch information
aslansq committed Dec 26, 2024
1 parent 51d5bd9 commit 6357c13
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 241 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"uart.h": "c"
}
}
13 changes: 9 additions & 4 deletions 0_base/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,26 @@ int uart0_readLine(char *ptrBuffer, int bufferLen)
{
char c = '\0';
int i;
int retVal = 0;

for (i = 0; i < bufferLen; i++)
{
UART0_RX_WAIT();
c = UART0_DATA;
if(c == '\r') {
*ptrBuffer = '\0';
ptrBuffer[i] = '\0';
break;
} else {
*ptrBuffer = c;
ptrBuffer++;
ptrBuffer[i] = c;
}
}

return i;
if((i == (bufferLen-1)) && (ptrBuffer[i] != '\0')) {
ptrBuffer[i] = '\0';
retVal = -1;
}

return retVal;
}


Expand Down
8 changes: 7 additions & 1 deletion 0_base/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
#define TX_BUFFER_MASK ( 1UL )

int uart0_read(char *ptrBuffer, int bufferLen);
/**
* @retval -1 : if does not fit into buffer
* @retval 0 to n : number of character read
*/
int uart0_readLine(char *ptrBuffer, int bufferLen);
uint8_t uart0_readU32NonBlock(uint32_t *num);
/**
* this has internal buffer of 100. not all the checks implemented since this is just demo code
*/
uint8_t uart0_readU32(uint32_t *num);
#endif // BASE_UART_H
2 changes: 1 addition & 1 deletion 3_task_scheduling_challenge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Implementation in [app.c](./app.c).

```Please ignore ledDelay global variable and serial port race conditions```
```Please ignore race conditions for now```

Challenge of [Introduction to RTOS Part 3 - Task Scheduling | Digi-Key Electronics](https://www.youtube.com/watch?v=95yUbClyf3E&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=3)

Expand Down
Binary file removed 4_memory/doc/taskPreemption.png
Binary file not shown.
33 changes: 4 additions & 29 deletions 4_memory_challenge/README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
# 4_memory
# 4_memory_challenge

Implementation in [app.c](./app.c).

[Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4)
```Please ignore race conditions for now```

This file demonstrates memory management in FreeRTOS
Explanation of demos:
```
// demo 1 : overflow stack by recursive call
#define APP_DEMO_1 1
// demo 2 : allocating huge array in stack to ovf
#define APP_DEMO_2 2
// demo 3 : ovf heap u32 at a time
#define APP_DEMO_3 3
// demo 4 : ovf heap in single shot
#define APP_DEMO_4 4
// demo 5 : properly malloc and free. this should be fine
#define APP_DEMO_5 5
// demo 6 : overflow of static stack by recursive call
#define APP_DEMO_6 6
Challenge of [Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4)

#ifndef APP_DEMO
#define APP_DEMO APP_DEMO_1
#endif
```
![Read user input in task A and print in task B](./doc/challenge.png "Read user input in task A and print in task B")

## Terminal Output
Terminal output of APP_DEMO_1:
```
rem: 0 tec: 574
rem: 0 tec: 575
re
Stack overflow in A
```

## Notes
Use app_init function in app.c to implement your demo application.
Expand Down
224 changes: 20 additions & 204 deletions 4_memory_challenge/app.c
Original file line number Diff line number Diff line change
@@ -1,246 +1,62 @@
/* This file demonstrates memory management in FreeRTOS
* define APP_DEMO macro with value APP_DEMO_[1..6] or [1..6]
* Example:
* #define APP_DEMO APP_DEMO_1
* #define APP_DEMO 1
*/
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <string.h>

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"

// demo 1 : overflow stack by recursive call
#define APP_DEMO_1 1
// demo 2 : allocating huge array in stack to ovf
#define APP_DEMO_2 2
// demo 3 : ovf heap u32 at a time
#define APP_DEMO_3 3
// demo 4 : ovf heap in single shot
#define APP_DEMO_4 4
// demo 5 : properly malloc and free. this should be fine
#define APP_DEMO_5 5
// demo 6 : overflow of static stack by recursive call
#define APP_DEMO_6 6

#ifndef APP_DEMO
#define APP_DEMO APP_DEMO_1
#endif
#include "uart.h"

#define APP_DEFAULT_PRIORITY (tskIDLE_PRIORITY + 1)
#define APP_DEFAULT_STACK_SIZE (1024u)

static void app_myTaskA( void * pvParameters );
char *app_msg = NULL;
uint8_t app_msgReadyFlag = 0;

#if APP_DEMO == APP_DEMO_2
static void app_myTaskA( void * pvParameters );
static void app_myTaskB( void * pvParameters );
#endif // APP_DEMO_2

#if APP_DEMO == APP_DEMO_6
/* Structure that will hold the TCB of the task being created. */
static StaticTask_t app_myTaskA_buffer;
static StackType_t app_myTaskA_stack[APP_DEFAULT_STACK_SIZE];
#endif // APP_DEMO_6

void app_init(void) {

#if APP_DEMO != APP_DEMO_6
xTaskCreate(app_myTaskA,
"A",
APP_DEFAULT_STACK_SIZE,
NULL,
APP_DEFAULT_PRIORITY,
NULL );
#else // APP_DEMO_6
xTaskCreateStatic(
app_myTaskA,
"A",
APP_DEFAULT_STACK_SIZE,
NULL,
APP_DEFAULT_PRIORITY,
app_myTaskA_stack,
&app_myTaskA_buffer );
#endif

#if APP_DEMO == APP_DEMO_2
xTaskCreate(app_myTaskB,
"B",
APP_DEFAULT_STACK_SIZE,
NULL,
APP_DEFAULT_PRIORITY,
NULL );
#endif // APP_DEMO_2

vTaskStartScheduler();

for( ; ; )
{
for( ; ; ) {
}
}

#if APP_DEMO == APP_DEMO_1
// demo 1 : overflow stack by recursive call
static void app_myTaskA( void * pvParameters ) {
// this made static, so it does not effect stack
static int taskEntryCount = 0;
for( ;; ) {
printf("rem: %d tec: %d\n", (int)uxTaskGetStackHighWaterMark(NULL), taskEntryCount++);
// lets ovf to see what happens to RTOS
app_myTaskA(NULL);
static char serialBuf[200];
for( ; ; ) {
uart0_readLine(serialBuf, 200);
size_t app_msgSize = (strlen(serialBuf)+1) * sizeof(char); // +1 for null
app_msg = (char *) pvPortMalloc(app_msgSize);
memcpy(app_msg, serialBuf, app_msgSize);
app_msgReadyFlag = 1;
}
}
//rem: 0 tec: 574
//rem: 0 tec: 575
//re
//
//Stack overflow in A
#endif // APP_DEMO_1

#if APP_DEMO == APP_DEMO_2
// This task survives, if there is no other task.
// demo 2 : allocating huge array in stack to ovf.
static void app_myTaskA( void * pvParameters ) {
uint32_t myHugeArray[APP_DEFAULT_STACK_SIZE+1];
printf("remStack: %d\n", (int)uxTaskGetStackHighWaterMark(NULL));
uint32_t anotherU32 = 0;
printf("remStack: %d\n", (int)uxTaskGetStackHighWaterMark(NULL));
uint32_t idx = 0;

while(1) { // to see if task survives and prints remaining stack constantly
// implementing sth so compiler does not optimize out
myHugeArray[idx] = idx;
myHugeArray[idx]++;
myHugeArray[idx]--;
anotherU32++;
idx++;
if(idx == (APP_DEFAULT_STACK_SIZE+1)) {
idx = 0;
}

int remStack = (int)uxTaskGetStackHighWaterMark(NULL);
if (remStack) {
printf("remStack: %d\n", remStack);
} else {
printf("no remStack\n");
}
}
}
// output when when app_myTaskB defined.
//no remStack
//no
//
//Stack overflow in A
// dummy task. purpose of this function: context switching happens between A and B
static void app_myTaskB( void * pvParameters ) {
uint32_t arr[APP_DEFAULT_STACK_SIZE/2];
uint32_t idx = 0;
for(;;) {
// implementing sth so compiler does not optimize out
arr[idx] = idx;
arr[idx]++;
arr[idx]--;
idx++;
if(idx == APP_DEFAULT_STACK_SIZE/2) {
idx = 0;
}
}
}
#endif // APP_DEMO_2

#if APP_DEMO == APP_DEMO_3
// demo 3 : ovf heap u32 at a time
static void app_myTaskA( void * pvParameters ) {
for(;;) {
// lets ovf heap u32 at a time
uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t));
if(ptr != NULL) { // doing sth so compiler does not complain
ptr[0]++;
}
uint32_t remHeap = xPortGetFreeHeapSize();
if(remHeap) {
printf("remHeap %d\n", (int)remHeap);
} else {
printf("no heapRem\n");
}
}
}
//remHeap 40
//remHeap 24
//no heapRem
//
//
//Malloc failed
#endif // APP_DEMO_3

#if APP_DEMO == APP_DEMO_4
// demo 4: ovf heap in single shot
static void app_myTaskA( void * pvParameters ) {
// heap ovf single shot
uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t)*UINT32_MAX);
if(ptr != NULL) { // doing sth so compiler does not complain
ptr[0]++;
}
uint32_t remHeap = xPortGetFreeHeapSize();
if(remHeap) {
printf("remHeap %d\n", (int)remHeap);
} else {
printf("no heapRem\n");
}
for(;;) {
}
}
//
//
//Malloc failed
#endif // APP_DEMO_4

#if APP_DEMO == APP_DEMO_5
// demo 5: heap alloc and free. this should be fine
static void app_myTaskA( void * pvParameters ) {
for(;;) {
// lets ovf heap u32 at a time
uint32_t *ptr = (uint32_t *)pvPortMalloc(sizeof(uint32_t));
if(ptr != NULL) { // doing sth so compiler does not complain
ptr[0]++;
}
uint32_t remHeap = xPortGetFreeHeapSize();
if(remHeap) {
printf("remHeap %d\n", (int)remHeap);
} else {
printf("no heapRem\n");
}
vPortFree(ptr);
}
}
// it is fine, it just repeats below line
//remHeap 57192
//remHeap 57192
//remHeap 57192
#endif // APP_DEMO_5

#if APP_DEMO == APP_DEMO_6
// demo 6 : overflow of static stack by recursive call
static void app_myTaskA( void * pvParameters ) {
// these made static, so it does not effect stack
static int taskEntryCount = 0;
static int remStack;
remStack = (int)uxTaskGetStackHighWaterMark(NULL);
for( ;; ) {
if(remStack) {
printf("rem: %d tec: %d\n", remStack, taskEntryCount);
} else {
printf("no remStack tec: %d\n", taskEntryCount);
for( ; ; ) {
if(app_msgReadyFlag && app_msg != NULL) {
printf("%s\n", app_msg);
vPortFree(app_msg);
app_msg = NULL;
app_msgReadyFlag = 0;
}
taskEntryCount++;
// lets ovf to see what happens to RTOS
app_myTaskA(NULL);
}
}
// it goes to hardfault instead of stack ovf hook. who knows why
//rem: 0 tec: 497
//rem: 0 tec: 498
//rem: 0 tec: 499
//Calling prvGetRegistersFromStack() from fault handle
#endif // APP_DEMO_1
}
Binary file added 4_memory_challenge/doc/challenge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed 4_memory_challenge/doc/taskPreemption.png
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This repo implements concepts from Digi-Key FreeRTOS introduction.
| Youtube | Demo | Challenge Solution |
|---------------------------------------------|-------------------|--------------------|
|[Introduction to RTOS Part 3 - Task Scheduling](https://www.youtube.com/watch?v=95yUbClyf3E&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=3)|[3_task_scheduling](./3_task_scheduling/README.md)|[3_task_scheduling_challenge](./3_task_scheduling_challenge/README.md)|
|[Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4)|[4_memory](./4_memory/README.md)||
|[Introduction to RTOS Part 4 - Memory Management ](https://www.youtube.com/watch?v=Qske3yZRW5I&list=PLEBQazB0HUyQ4hAPU1cJED6t3DU0h34bz&index=4)|[4_memory](./4_memory/README.md)|[4_memory_challenge](./4_memory_challenge/README.md)|

## Usecase
You dont have hardware and you dont care about any specific hardware but learning FreeRTOS.
Expand Down
4 changes: 3 additions & 1 deletion misc/shell/rebuild_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ do
fi
done
fi
done
done

echo "All demos rebuilt successfully!"

0 comments on commit 6357c13

Please sign in to comment.