summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile3
-rw-r--r--src/master.c175
2 files changed, 153 insertions, 25 deletions
diff --git a/makefile b/makefile
index a6914cc..6af687b 100644
--- a/makefile
+++ b/makefile
@@ -22,7 +22,6 @@ BUILD_DIR = build
######################################
# C sources for all ports
C_SOURCES = \
-src/main-rtos.c \
lib/nanopb/pb_decode.c \
lib/nanopb/pb_encode.c \
lib/nanopb/pb_common.c \
@@ -73,7 +72,7 @@ AS_INCLUDES =
C_INCLUDES = \
-Isrc \
-Ilib/cmsis \
--Ilib/freertos/include
+-Ilib/freertos/include \
-Ilib/nanopb
# Define the chip we're building for and include its makefile
diff --git a/src/master.c b/src/master.c
index c627a45..a23805b 100644
--- a/src/master.c
+++ b/src/master.c
@@ -15,6 +15,8 @@
/* Library includes */
#include <pb_encode.h>
#include <pb_decode.h>
+#include "FreeRTOS.h"
+#include "task.h"
/* Project includes */
#include "main.h"
@@ -23,6 +25,7 @@
#include "dataflow.h"
#include "handshake.pb.h"
#include "data.pb.h"
+#include "semphr.h"
/* Private Macros */
#define device_MDR s2m_MDR_response
@@ -38,6 +41,12 @@
/* Macro to toggle between master and slave firmware */
#define MASTER
+#define mainHANDSHAKE_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
+#define mainROUTING_TASK_PRIORITY (tskIDLE_PRIORITY + 2)
+#define mainDATAFLOW_TASK_PRIORITY (tskIDLE_PRIORITY + 1)
+#define mainHS_FREQUENCY_MS (2000 / portTICK_PERIOD_MS)
+#define mainQUEUE_LENGTH (1)
+
/* Private globals */
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
@@ -63,14 +72,22 @@ static void MX_USART1_UART_Init(void);
hs_status_t handshake(uint32_t i2c_addr);
dataflow_status_t device_dataflow(uint8_t i2c_addr, uint32_t SOR_code, uint8_t routing_buf_idx);
bool routing(void);
+
+static void prvHandshakeTask(void *pvParameters);
+static void prvRoutingTask(void *prvParam);
+static void prvDataflowTask(void *prvParam);
+
bool todo_hs_or_not_todo_hs(uint8_t i2c_addr);
state_t get_state_from_hs_status(uint16_t device_addr, hs_status_t hs_status);
+
bool decode_subscriptions_callback(pb_istream_t *istream, const pb_field_t *field, void **args);
bool encode_subscription_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg);
bool encode_datapoint_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg);
bool decode_data_callback(pb_istream_t *istream, const pb_field_t *field, void **args);
bool master_encode_MDR_callback(pb_ostream_t *ostream, const pb_field_t *field, void * const *arg);
+
+
/**
* @brief The application entry point.
* @retval int
@@ -99,37 +116,69 @@ int main(void)
HAL_UART_Transmit(&huart1, reset_string, sizeof(reset_string), 100);
#endif /* MASTER */
#endif /* TESTING_ENABLE */
+
uint8_t priority_counter = 0, debug_buf[128];
- /* Handshake */
- while (1) {
- if (priority_counter == 0) {
- hs_status_t hs_status;
- /* for (uint8_t curr_addr=5; curr_addr == 5; curr_addr++) { */
- for (uint8_t curr_addr=0x1; curr_addr <= BUS_DEVICE_LIMIT; curr_addr++) {
- if (todo_hs_or_not_todo_hs(curr_addr)) {
- hs_status = handshake(curr_addr);
- dev_sts[GET_IDX_FROM_ADDR(curr_addr)] = get_state_from_hs_status(curr_addr, hs_status);
- }
+ xTaskCreate(prvHandshakeTask, "handshake", configMINIMAL_STACK_SIZE, NULL,
+ mainHANDSHAKE_TASK_PRIORITY,NULL);
+
+ xTaskCreate(prvRoutingTask, "routing", configMINIMAL_STACK_SIZE, NULL,
+ mainROUTING_TASK_PRIORITY, NULL);
+
+ xTaskCreate(prvDataflowTask, "dataflow", configMINIMAL_STACK_SIZE, NULL,
+ mainDATAFLOW_TASK_PRIORITY, NULL);
+ /* Start the tasks and timer running. */
+ vTaskStartScheduler();
+ for( ;; );
+}
+
+static void prvHandshakeTask(void *pvParameters)
+{
+ TickType_t xNextWakeTime;
+ (void) pvParameters;
+ xNextWakeTime = xTaskGetTickCount();
+ for( ;; )
+ {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainHS_FREQUENCY_MS );
+ hs_status_t hs_status;
+ for (uint8_t curr_addr=0x1; curr_addr <= BUS_DEVICE_LIMIT; curr_addr++) {
+ if (todo_hs_or_not_todo_hs(curr_addr)) {
+ hs_status = handshake(curr_addr);
+ dev_sts[GET_IDX_FROM_ADDR(curr_addr)] = get_state_from_hs_status(curr_addr, hs_status);
}
- }
+ }
+ }
+}
- else if (priority_counter == 5 && routing_ptr > 0) {
+static void prvRoutingTask(void *prvParam)
+{
+ TickType_t xNextWakeTime;
+ (void) prvParam;
+ xNextWakeTime = xTaskGetTickCount();
+ for( ;; ) {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainHS_FREQUENCY_MS );
+ if (routing_ptr > 0) {
routing();
}
- else {
- for (int device_idx = 0; device_idx < BUS_DEVICE_LIMIT-1; device_idx++) {
- if (dev_sts[device_idx] == REGISTERED) {
- device_dataflow(GET_ADDR_FROM_IDX(device_idx), SLAVE_TX, 0);
- }
+ }
+}
+
+static void prvDataflowTask(void *prvParam)
+{
+ TickType_t xNextWakeTime;
+ (void) prvParam;
+ xNextWakeTime = xTaskGetTickCount();
+ for( ;; ) {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainHS_FREQUENCY_MS );
+ for (int device_idx = 0; device_idx < BUS_DEVICE_LIMIT-1; device_idx++) {
+ if (dev_sts[device_idx] == REGISTERED) {
+ device_dataflow(GET_ADDR_FROM_IDX(device_idx), SLAVE_TX, 0);
}
}
- priority_counter = ((priority_counter+1)%10);
-
- sprintf((char*)debug_buf, "routing ptr: %ld\r\n", routing_ptr);
- HAL_UART_Transmit(&huart1, debug_buf, sizeof(debug_buf), 100);
- memset(debug_buf, 0, 128);
- }
+ }
}
hs_status_t handshake(uint32_t i2c_addr)
@@ -983,3 +1032,83 @@ void assert_failed(uint8_t *file, uint32_t line)
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
+
+// Macro to use CCM (Core Coupled Memory) in STM32F4
+#define CCM_RAM __attribute__((section(".ccmram")))
+
+#define FPU_TASK_STACK_SIZE 256
+
+StackType_t fpuTaskStack[FPU_TASK_STACK_SIZE] CCM_RAM; // Put task stack in CCM
+StaticTask_t fpuTaskBuffer CCM_RAM; // Put TCB in CCM
+
+void vApplicationTickHook(void) {
+}
+
+/* vApplicationMallocFailedHook() will only be called if
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
+ function that will get called if a call to pvPortMalloc() fails.
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,
+ timer or semaphore is created. It is also called by various parts of the
+ demo application. If heap_1.c or heap_2.c are used, then the size of the
+ heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
+ FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
+ to query the size of free heap space that remains (although it does not
+ provide information on how the remaining heap might be fragmented). */
+void vApplicationMallocFailedHook(void) {
+ taskDISABLE_INTERRUPTS();
+ for(;;);
+}
+
+/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
+ task. It is essential that code added to this hook function never attempts
+ to block in any way (for example, call xQueueReceive() with a block time
+ specified, or call vTaskDelay()). If the application makes use of the
+ vTaskDelete() API function (as this demo application does) then it is also
+ important that vApplicationIdleHook() is permitted to return to its calling
+ function, because it is the responsibility of the idle task to clean up
+ memory allocated by the kernel to any task that has since been deleted. */
+void vApplicationIdleHook(void) {
+}
+
+void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName) {
+ (void) pcTaskName;
+ (void) pxTask;
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ taskDISABLE_INTERRUPTS();
+ for(;;);
+}
+
+StaticTask_t xIdleTaskTCB CCM_RAM;
+StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE] CCM_RAM;
+
+/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
+implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
+used by the Idle task. */
+void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) {
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
+ state will be stored. */
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ /* Pass out the array that will be used as the Idle task's stack. */
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
+ Note that, as the array is necessarily of type StackType_t,
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+
+static StaticTask_t xTimerTaskTCB CCM_RAM;
+static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH] CCM_RAM;
+
+/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
+application must provide an implementation of vApplicationGetTimerTaskMemory()
+to provide the memory that is used by the Timer service task. */
+void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}