From 7fdf8de7183840240095c3f24c6ff7a6d59a765c Mon Sep 17 00:00:00 2001 From: Dmitry Maylarov Date: Sun, 14 Jul 2019 16:33:15 +0300 Subject: [PATCH] config before timer setup; using mutex and notifs --- .vscode/launch.json | 16 +-- .vscode/uberdevice.code-workspace | 3 +- Core/Inc/FreeRTOSConfig.h | 3 +- Core/Src/game.c | 13 +- Core/Src/lcd.c | 2 + Core/Src/main.c | 190 +++++++++++++++--------------- 6 files changed, 109 insertions(+), 118 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c0eeae7..08d5e63 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,21 +12,7 @@ "configFiles": [ "target/stlink.cfg", "target/stm32f1x.cfg" - ], - "swoConfig": { - "source": "probe", - "enabled": true, - "swoFrequency": 4000000, - "cpuFrequency": 48000000, - "decoders": [ - { - "port": 0, - "label": "Output", - "type": "console", - "encoding":"ascii" - } - ] - } + ] } ] } \ No newline at end of file diff --git a/.vscode/uberdevice.code-workspace b/.vscode/uberdevice.code-workspace index b501710..6f65270 100644 --- a/.vscode/uberdevice.code-workspace +++ b/.vscode/uberdevice.code-workspace @@ -9,7 +9,8 @@ "task.h": "c", "music.h": "c", "usb_device.h": "c", - "main.h": "c" + "main.h": "c", + "game.h": "c" } } } \ No newline at end of file diff --git a/Core/Inc/FreeRTOSConfig.h b/Core/Inc/FreeRTOSConfig.h index 8743294..d1784a3 100644 --- a/Core/Inc/FreeRTOSConfig.h +++ b/Core/Inc/FreeRTOSConfig.h @@ -82,7 +82,7 @@ #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 #define configUSE_TASK_NOTIFICATIONS 1 -#define configUSE_MUTEXES 0 +#define configUSE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 0 #define configUSE_COUNTING_SEMAPHORES 0 @@ -110,6 +110,7 @@ to exclude the API function. */ #define INCLUDE_uxTaskPriorityGet 1 #define INCLUDE_vTaskDelete 1 #define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskNotifyGive 1 #define INCLUDE_xResumeFromISR 1 #define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelay 1 diff --git a/Core/Src/game.c b/Core/Src/game.c index f9f90ba..fc0ed85 100644 --- a/Core/Src/game.c +++ b/Core/Src/game.c @@ -7,11 +7,10 @@ void InitGameEngine() { game.countScores = true; game.activePlayers = 0; game.currentPlayer = 1; - game.turnTime = TIMER_MAX / 2; + game.turnTime = TIMER_STEP; game.timerValue = game.turnTime; for (int i=0; i 1) { - game.scores[--game.activePlayers] = -1; + game.scores[1+(--game.activePlayers)] = 999; } } @@ -51,6 +50,8 @@ void ResetTurnTimer() { } void NextPlayer() { - game.currentPlayer = ((game.currentPlayer) % (game.activePlayers+1) + 1 ); + game.currentPlayer--; + game.currentPlayer = ((game.currentPlayer + 1) % game.activePlayers); + game.currentPlayer++; ResetTurnTimer(); } \ No newline at end of file diff --git a/Core/Src/lcd.c b/Core/Src/lcd.c index d16324d..0521a56 100644 --- a/Core/Src/lcd.c +++ b/Core/Src/lcd.c @@ -81,8 +81,10 @@ HAL_StatusTypeDef LCD_SendInternal(LCD_HandleTypeDef *lcd, uint8_t data, uint8_t data_arr[2] = lo|flags|LCD_BACKLIGHT|LCD_PIN_EN; data_arr[3] = lo|flags|LCD_BACKLIGHT; + taskENTER_CRITICAL(); res = HAL_I2C_Master_Transmit(lcd->I2C_Handle, lcd->address, data_arr, sizeof(data_arr), HAL_MAX_DELAY); + taskEXIT_CRITICAL(); vTaskDelay(LCD_DELAY_MS); return res; } diff --git a/Core/Src/main.c b/Core/Src/main.c index 9265987..072536a 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -100,6 +100,7 @@ TimerHandle_t xSecondsTimerHandle = NULL; TaskHandle_t xMusicHandle = NULL; TaskHandle_t xLCDUpdaterHandle = NULL; xSemaphoreHandle xButtonPressed; +xSemaphoreHandle xLCD; asm( "tetris:\n\t" @@ -130,14 +131,18 @@ static void MX_USART1_UART_Init(void); /* USER CODE BEGIN PFP */ void PrintTime() { - LCD_MoveCursor(&hlcd, 0, 0); - sprintf( - lcdBuffer, - (game.timerValue > 0 ? " %1d:%02d " : " -%d:%02d "), - abs(game.timerValue / 60), - abs(game.timerValue % 60) - ); - LCD_SendString(&hlcd, lcdBuffer); + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) + { + sprintf( + lcdBuffer, + (game.timerValue > 0 ? " %1d:%02d " : " -%d:%02d "), + abs(game.timerValue / 60), + abs(game.timerValue % 60) + ); + LCD_MoveCursor(&hlcd, 0, 0); + LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); + } } /* USER CODE END PFP */ @@ -182,6 +187,9 @@ int main(void) /* USER CODE BEGIN 2 */ InitGameEngine(); + xLCD = xSemaphoreCreateMutex(); + xButtonPressed = xSemaphoreCreateBinary(); + xTaskCreate(vTaskPlayerSetup, "Player", configMINIMAL_STACK_SIZE, NULL, 1, NULL); xTaskCreate(vTaskButtonPoll, "Buttons", configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskStartScheduler(); @@ -494,23 +502,48 @@ void vTaskPlayerSetup(void *parameter) } } } - xTaskCreate(vTaskTimerSetup, "TaskTimerSetup", configMINIMAL_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(vTaskConfig, "Config", configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskDelete(NULL); } -void vTaskTimerSetup(void *parameter) { - if (xLCDUpdaterHandle != NULL) - { - vTaskDelete(xLCDUpdaterHandle); - xLCDUpdaterHandle = NULL; - } +void vTaskConfig(void *parameter) { LCD_MoveHome(&hlcd); LCD_SendString(&hlcd, "Settings"); while (1) { LCD_MoveCursor(&hlcd, 1, 0); - sprintf(lcdBuffer, "Turn time: %1ld:%02ld ",game.turnTime / 60, game.turnTime % 60); + sprintf(lcdBuffer, "Count scores: %3s ", game.countScores ? "yes" : "no"); + LCD_SendString(&hlcd, lcdBuffer); + vTaskDelay(1); + if (xSemaphoreTake(xButtonPressed, portMAX_DELAY) == pdPASS ) { + if (plusButton->pressed) + game.countScores = !game.countScores; + if (minusButton->pressed) + // show round number or change the way it counts + game.countScores = !game.countScores; + if (bigButton->pressed) { + break; + } + vTaskDelay(10); + } + } + xTaskCreate(vTaskTimerSetup, "TaskTimerSetup", configMINIMAL_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(vTaskTurnTimeUpdate, "TimeUpdate", configMINIMAL_STACK_SIZE, NULL, 1, &xLCDUpdaterHandle); + vTaskDelete(NULL); +} + +void vTaskTimerSetup(void *parameter) { + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) + { + LCD_MoveHome(&hlcd); + LCD_MoveCursor(&hlcd, 1, 0); + sprintf(lcdBuffer, "Setup turn time"); LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); + } + while (1) + { + xTaskNotifyGive(xLCDUpdaterHandle); vTaskDelay(1); if (xSemaphoreTake(xButtonPressed, portMAX_DELAY) == pdPASS ) { @@ -535,104 +568,70 @@ void vTaskTimerSetup(void *parameter) { pdTRUE, //auto-reload NULL, //not assigning ID vTimerCallback // function to call after timer expires - ); - - xTaskCreate(vTaskConfig, "Config", configMINIMAL_STACK_SIZE, NULL, 1, NULL); - vTaskDelete(NULL); -} + ); -void vTaskConfig(void *parameter) { - if (xLCDUpdaterHandle != NULL) - { - vTaskDelete(xLCDUpdaterHandle); - xLCDUpdaterHandle = NULL; - } - LCD_MoveHome(&hlcd); - LCD_SendString(&hlcd, "Settings"); - while (1) - { - LCD_MoveCursor(&hlcd, 1, 0); - sprintf(lcdBuffer, "Count scores: %3s ", game.countScores ? "yes" : "no"); - LCD_SendString(&hlcd, lcdBuffer); - vTaskDelay(1); - if (xSemaphoreTake(xButtonPressed, portMAX_DELAY) == pdPASS ) { - if (plusButton->pressed) - game.countScores = !game.countScores; - if (minusButton->pressed) - // show round number or change the way it counts - game.countScores = !game.countScores; - if (bigButton->pressed) { - break; - } - vTaskDelay(10); - } - } xTaskCreate(vTaskTurn, "TaskTurn", configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskDelete(NULL); } void vTaskTurnTimeUpdate(void *parameter) { - TickType_t xLastWakeTime; - xLastWakeTime = xTaskGetTickCount(); - while (1) { + ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); PrintTime(); - vTaskDelayUntil(&xLastWakeTime,1000); } } void vTaskTurn(void *parameter) { - if (xLCDUpdaterHandle == NULL) - { - xTaskCreate(vTaskTurnTimeUpdate, "TimeUpdate", configMINIMAL_STACK_SIZE, NULL, 1, &xLCDUpdaterHandle); - vTaskDelay(100); - } - TickType_t xLastWakeTime; - xLastWakeTime = xTaskGetTickCount(); - xTimerReset(xSecondsTimerHandle, 0); - LCD_MoveHome(&hlcd); + xTaskNotifyGive(xLCDUpdaterHandle); + vTaskDelay(5); if (game.countScores) { - LCD_MoveCursor(&hlcd, 2, 1); - for (int i = 1; i <= game.activePlayers; i++) + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) { - char tmp[8]; - sprintf(tmp, "%1d:%3ld|", i, game.scores[i]); - strcat(lcdBuffer, tmp); - if (strlen(lcdBuffer) > (LCD_COLS-6)) + LCD_MoveCursor(&hlcd, 2, 0); + memset(&lcdBuffer,'\0', sizeof(lcdBuffer)); + lcdBuffer[0] = ' '; + for (int i = 1; i <= game.activePlayers; i++) { - LCD_SendString(&hlcd, lcdBuffer); - LCD_MoveCursor(&hlcd, 3, 1); + char tmp[8]; + sprintf(tmp, "%1d:%3ld|", i, game.scores[i]); + strcat(lcdBuffer, tmp); + if (strlen(lcdBuffer) > (LCD_COLS-6)) + { + LCD_SendString(&hlcd, lcdBuffer); + LCD_MoveCursor(&hlcd, 3, 0); + memset(&lcdBuffer,'\0', sizeof(lcdBuffer)); + lcdBuffer[0] = ' '; + } } + LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); } + } + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) + { + sprintf(lcdBuffer, "Player: %1d Score: %3ld",game.currentPlayer, game.scores[game.currentPlayer]); + LCD_MoveCursor(&hlcd, 1, 0); LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); } - LCD_MoveCursor(&hlcd, 1, 0); - sprintf(lcdBuffer, "Player: %1d Score: %3ld",game.currentPlayer, game.scores[game.currentPlayer]); - LCD_SendString(&hlcd, lcdBuffer); - while (1) { if (xSemaphoreTake(xButtonPressed, portMAX_DELAY) == pdPASS ) { - if (plusButton->pressed) { + if (plusButton->pressed || minusButton->pressed) { xTaskCreate(vTaskTimerSetup, "TaskTimerSetup", configMINIMAL_STACK_SIZE, NULL, 1, NULL); break; } - else if (minusButton->pressed) { - xTaskCreate(vTaskConfig, "Config", configMINIMAL_STACK_SIZE, NULL, 1, NULL); - break; - } else if (bigButton->pressed) { xTaskCreate(vTaskTurnEnd, "TaskTurnEnd", configMINIMAL_STACK_SIZE, NULL, 1, NULL); break; } } - vTaskDelayUntil(&xLastWakeTime,100); // HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } xTimerStop(xSecondsTimerHandle, 0); @@ -646,22 +645,25 @@ void vTaskTurn(void *parameter) { } void vTaskTurnEnd(void *parameter) { - if (xLCDUpdaterHandle != NULL) - { - vTaskDelete(xLCDUpdaterHandle); - xLCDUpdaterHandle = NULL; - } if (game.countScores) { - int32_t delta = 0; - LCD_MoveHome(&hlcd); - PrintTime(); - LCD_MoveCursor(&hlcd, 1, 0); - sprintf(lcdBuffer, "Player: %1d Score: %3ld",game.currentPlayer, game.scores[game.currentPlayer]); - LCD_SendString(&hlcd, lcdBuffer); - while (1) { - LCD_MoveCursor(&hlcd, 2, 0); - sprintf(lcdBuffer, "Result: %+4ld", delta); + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) + { + LCD_MoveHome(&hlcd); + LCD_MoveCursor(&hlcd, 1, 0); + sprintf(lcdBuffer, "Player: %1d Score: %3ld",game.currentPlayer, game.scores[game.currentPlayer]); LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); + } + xTaskNotifyGive(xLCDUpdaterHandle); + int32_t delta = 0; + while (1) { + if( xSemaphoreTake( xLCD, portMAX_DELAY ) == pdTRUE ) + { + sprintf(lcdBuffer, "Result: %+4ld", delta); + LCD_MoveCursor(&hlcd, 2, 0); + LCD_SendString(&hlcd, lcdBuffer); + xSemaphoreGive( xLCD ); + } if (xSemaphoreTake(xButtonPressed, portMAX_DELAY) == pdPASS ) { if (bigButton->pressed) { ChangeScore(delta); @@ -677,11 +679,9 @@ void vTaskTurnEnd(void *parameter) { minusButton->pressed = false; delta--; } - vTaskDelay(10); } } } - ResetTurnTimer(); NextPlayer(); xTaskCreate(vTaskTurn, "TaskTurn", configMINIMAL_STACK_SIZE, NULL, 1, NULL); vTaskDelete(NULL); @@ -705,6 +705,7 @@ void vTaskOvertime(void *parameter) { void vTimerCallback(TimerHandle_t xTimer) { game.timerValue--; + xTaskNotifyGive(xLCDUpdaterHandle); if(game.timerValue == 0 && xMusicHandle == NULL) { xTaskCreate(vTaskOvertime, "vTaskOvertime", configMINIMAL_STACK_SIZE, NULL, 1, &xMusicHandle); @@ -712,7 +713,6 @@ void vTimerCallback(TimerHandle_t xTimer) { } void vTaskButtonPoll(void *parameter) { - xButtonPressed = xSemaphoreCreateBinary(); bool state = false; while (1) { for(int i = 0; i