From 32162a2ec4c2d42da8d9f3403760cf56615b4176 Mon Sep 17 00:00:00 2001 From: Thomas Kuschel Date: Fri, 15 Jul 2022 12:42:42 +0200 Subject: [PATCH] integration commandinterpreter, ringbuffer --- .cproject | 8 +- .project | 2 +- Core/Inc/at1_defines.h | 2 +- Core/Inc/commands.h | 10 +- Core/Inc/stm32_si5351.h | 5 +- Core/Inc/stm32l4xx_it.h | 1 + Core/Src/commands.c | 157 ++++++++++++++++- Core/Src/main.c | 244 ++++++++++++++++++++------ Core/Src/stm32_si5351.c | 10 +- Core/Src/stm32l4xx_hal_msp.c | 22 +++ Core/Src/stm32l4xx_hal_timebase_tim.c | 49 ++++-- Core/Src/stm32l4xx_it.c | 15 ++ stm32l4a6zg-f0x.at1.ioc | 62 ++++--- 13 files changed, 471 insertions(+), 116 deletions(-) diff --git a/.cproject b/.cproject index 9c8f411..6da7c60 100644 --- a/.cproject +++ b/.cproject @@ -185,11 +185,7 @@ - - - - - - + + \ No newline at end of file diff --git a/.project b/.project index 8834554..a8753ad 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - stm32l4a6zg-freertos + stm32l4a6zg-f0x.at1 diff --git a/Core/Inc/at1_defines.h b/Core/Inc/at1_defines.h index 819a27e..9675402 100644 --- a/Core/Inc/at1_defines.h +++ b/Core/Inc/at1_defines.h @@ -26,7 +26,7 @@ extern "C" { #define STR(x) STR_HELPER(x) #endif #define VERSION_MAJOR 0 -#define VERSION_MINOR 1 +#define VERSION_MINOR 2 #define PROGRAM_ID "f0x.at1 Version " STR(VERSION_MAJOR) "." STR(VERSION_MINOR) #define VERSION_STRING STR(VERSION_MAJOR) "." STR(VERION_MINOR) //#define DATE __DATE__ diff --git a/Core/Inc/commands.h b/Core/Inc/commands.h index 9ede63e..98a9606 100644 --- a/Core/Inc/commands.h +++ b/Core/Inc/commands.h @@ -16,10 +16,16 @@ extern "C" { #endif //struct command_ctx_s *command_inst; -typedef struct command_ctx_s *command_inst_t; +//typedef struct command_ctx_s *command_inst_t; +extern RTC_HandleTypeDef hrtc; /* function prototypes */ -int not_implemented(command_inst_t inst, char *args); +int do_help(char *args); +int do_devid(char *args); +int do_test(/*command_inst_t inst,*/ char *args); +int do_time(char *args); + +int cmd_interpreter(char * cmdline); #ifdef __cplusplus diff --git a/Core/Inc/stm32_si5351.h b/Core/Inc/stm32_si5351.h index a3659c8..c0fbecf 100644 --- a/Core/Inc/stm32_si5351.h +++ b/Core/Inc/stm32_si5351.h @@ -94,13 +94,14 @@ typedef struct __SI5351_HandleTypeDef *si5351_inst_t; /* Exported constants --------------------------------------------------------*/ /** @enum errno_t Error Number Constants, @TODO could also errno.h included!! */ -#if !defined _SYS_ERRNO_H_ || !defined __ERRNO_H__ +#if !defined _SYS_ERRNO_H_ && !defined __ERRNO_H__ typedef enum { EPERM = 1, /*!< Operation not permitted */ EIO = 5, /*!< I/O error */ ENOMEM = 12, /*!< Out of memory */ - ENODEV = 19, /*!< No such device */ + EFAULT = 14, /*!< Bad address */ EBUSY = 16, /*!< Device or resource busy */ + ENODEV = 19, /*!< No such device */ EINVAL = 22, /*!< Invalid argument */ EADDRINUSE = 98,/*!< Address already in use */ ETIMEDOUT = 116 /*!< Connection timed out */ diff --git a/Core/Inc/stm32l4xx_it.h b/Core/Inc/stm32l4xx_it.h index 13dc2e9..c56ebdf 100644 --- a/Core/Inc/stm32l4xx_it.h +++ b/Core/Inc/stm32l4xx_it.h @@ -53,6 +53,7 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); void TIM6_DAC_IRQHandler(void); +void DMA2_Channel7_IRQHandler(void); void LPUART1_IRQHandler(void); /* USER CODE BEGIN EFP */ diff --git a/Core/Src/commands.c b/Core/Src/commands.c index d5bc8e4..4346614 100644 --- a/Core/Src/commands.c +++ b/Core/Src/commands.c @@ -7,43 +7,182 @@ * created 2022-06-04 * ******************************************************************************/ +#include "main.h" #include "cmsis_os.h" #include +#include +#include +#include //strchr +#include //bsearch +#include "helper.h" //ltrim #include "commands.h" -typedef struct command_ctx_s { +/* + typedef struct command_ctx_s { osThreadId_t thread_id; osMutexId_t mutex; char *last_cmd; size_t last_cmd_size; } command_ctx_t; - +*/ typedef enum { + CMD_NO_FLAG = 0x00, CMD_HIDDEN = 0x01, /*!< Not shown in help but listed with "help all" or with "?" */ CMD_SECRET = 0x02, /*!< Not shown in help - hidden and secret commands */ CMD_ADMIN = 0x04, /*!< Only an administrator or privileged person can use this command */ CMD_NOT_IMPLEMENTED = 0x80 /*!< A command which is not implemented yet */ } cmd_flags_t; -#define CMD_LENGTH 16 +#define CMD_LENGTH 16 +#define MAXLINELENGTH 40 -typedef struct{ +typedef struct { const char name[CMD_LENGTH]; /*!< command name */ const uint8_t significantlength; /*!< length of command for the compare function */ const uint8_t flag; /*!< command flags, i.e. CMD_HIDDEN, CMD_SECRET, CMD_ADMIN, etc. */ - int(*func)(command_ctx_t *ctx, char *args); + int (*func)(/*command_ctx_t *ctx,*/ char *args); } cmd_table_t; static const cmd_table_t cmd_table[] = { - {"altitude", 1, CMD_NOT_IMPLEMENTED, not_implemented }, - {"date", 1, CMD_NOT_IMPLEMENTED, not_implemented }, + {"admin", 2, CMD_ADMIN, do_test }, + {"altitude", 1, CMD_NO_FLAG, do_test }, + {"date", 1, CMD_NO_FLAG, do_time }, + {"devid", 3, CMD_HIDDEN, do_devid }, + {"help", 1, CMD_NO_FLAG, do_help }, + {"hidden", 2, CMD_HIDDEN, do_test }, + {"secret", 1, CMD_SECRET, do_test }, + {"time", 1, CMD_NO_FLAG, do_time }, }; -int not_implemented(command_ctx_t *ctx, char *args) { - (void) *ctx; +int do_test(char *args) { (void) *args; + printf("not implemented.\n"); return 0; } +/*! + * @brief compares two strings up to n characters, and next gets the pointer to the 2nd word in the string s1 + * + * @pre s1, s2 and n not allowed to be 0 + * + * @param s1 + * @param next + * @param s2 + * @param n + * @return int if the s1 and s2 are the same till n characters its 0, if s1 > s2 it becomes 1, else -1 + */ +int cmdncasecmp(const char *s1, char **next, const char *s2, size_t n) +{ + if (n == 0 || s1 == NULL || s2 == NULL) { + if (next) *next = NULL; + if (s2 == NULL && s1 != NULL) return 1; + if (s1 == NULL && s2 != NULL) return -1; + return 0; + } + int ret; + while ((ret = ((unsigned char)tolower(*s1) - (unsigned char)tolower(*s2))) == 0 + && *s1 != ' ' && *s1 && *s2) { + if (n) n--; + s1++; + s2++; + } + if (next) *next = (char *) s1; + if (n == 0 && (*s1 == ' ' || !*s1)) + return 0; + return ret; +} + +static int compar(const void *a, const void *b) +{ + cmd_table_t * cmd = (cmd_table_t *)b; + return cmdncasecmp(a, NULL, cmd->name, cmd->significantlength); +} + + +int cmd_interpreter(char * cmdline) { + char * ptr; + const cmd_table_t *entry; + int rv = 0; + + ptr = strchr(cmdline, ' '); + if (ptr) { + *ptr = '\0'; + ptr++; + ptr = ltrim(ptr); + } + entry = bsearch(cmdline, cmd_table, sizeof(cmd_table)/sizeof(cmd_table[0]), sizeof(cmd_table[0]), compar); + if (entry == NULL) { + printf("command \"%s\" not found.\n", cmdline); + } else { + printf("command: \"%s\" ...\n", entry->name ); + if (*ptr != '\0') + printf("with parameter: %s\n", ptr ); + rv = entry->func(ptr); + } + return rv; +} + +int do_devid(char *args) { + + (void)args; + union myUnion { + uint32_t myint[2]; + char mychar[8]; + } my; + + printf("DEVID: 0x%08lx\n", HAL_GetDEVID()); + printf("REVID: 0x%08lx\n", HAL_GetREVID()); + printf("UID: 0x%08lx %08lx %08lx\n", HAL_GetUIDw2(), HAL_GetUIDw1(), HAL_GetUIDw0()); + + my.myint[1] = HAL_GetUIDw2(); + my.myint[0] = HAL_GetUIDw1(); + my.mychar[8] = '\0'; + + printf("=> Lot Number: %s\n", my.mychar); + printf("=> Wafer Number: %u\n", (uint8_t)(HAL_GetUIDw1() & 0xff)); + return 0; +} + +int do_time(char *args) { + + HAL_StatusTypeDef status; + RTC_TimeTypeDef time; + RTC_DateTypeDef date; + + if (!args) { + status = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); + if (status != HAL_OK) + puts("HAL_RTC_GetTime problem..."); + + status = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN); + printf("%02d%02d-%02d-%02d %02d:%02d:%02d\n", (date.Year < 22) ? 21 : 20, date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds); + } + return 0; +} + +int do_help(char *args) { + + int all = cmdncasecmp(args, NULL, "all", 1); + const cmd_table_t *cmd = cmd_table; + int j = 0; + int n = 0; + int rv = 0; + + puts("Commands:"); + + for (size_t i = 0; i < (sizeof(cmd_table)/sizeof(cmd_table[0])); i++, cmd++) { + if (cmd->flag != CMD_SECRET && (cmd->flag != CMD_HIDDEN || !all)) { + if (n >= MAXLINELENGTH) { + puts(","); + n = 0; + } + // n += printf("%s%s (%.*s)", n?", ":"", cmd->name, cmd->significantlength, cmd->name); + n += printf("%s(%.*s)%s", n?", ":"", cmd->significantlength, cmd->name, cmd->name + cmd->significantlength); + j++; + } + } + printf("\n%d commands found.\n", j); + return rv; +} diff --git a/Core/Src/main.c b/Core/Src/main.c index 4ab0ea7..8feebfe 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -26,6 +26,10 @@ #include "at1_defines.h" #include "stm32_si5351.h" #include "commands.h" +#include +#include "ringbuf.h" +#include "ringbuf_test.h" // test the ringbuffer +#include "helper.h" // my toolbox for strings, etc. /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -35,6 +39,7 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ + /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -43,9 +48,10 @@ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ - I2C_HandleTypeDef hi2c1; +I2C_HandleTypeDef hi2c1; UART_HandleTypeDef hlpuart1; +DMA_HandleTypeDef hdma_lpuart_rx; RTC_HandleTypeDef hrtc; @@ -60,8 +66,8 @@ const osThreadAttr_t defaultTask_attributes = { osThreadId_t terminalTaskHandle; const osThreadAttr_t terminalTask_attributes = { .name = "terminalTask", - .stack_size = 128 * 4, - .priority = (osPriority_t) osPriorityBelowNormal, + .stack_size = 256 * 4, + .priority = (osPriority_t) osPriorityNormal, }; /* Definitions for morseTask */ osThreadId_t morseTaskHandle; @@ -82,30 +88,63 @@ osSemaphoreId_t si5351Handle; const osSemaphoreAttr_t si5351_attributes = { .name = "si5351" }; +/* Definitions for command */ +osSemaphoreId_t commandHandle; +const osSemaphoreAttr_t command_attributes = { + .name = "command" +}; /* USER CODE BEGIN PV */ int leds_on = 1; uint8_t UART1_rxBuffer[12] = {0}; +uint8_t UART1_txBuffer[12]; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); +static void MX_I2C1_Init(void); static void MX_LPUART1_UART_Init(void); static void MX_RTC_Init(void); -static void MX_I2C1_Init(void); void StartDefaultTask(void *argument); void start_terminal_task(void *argument); void start_morse_task(void *argument); void start_clk2_task(void *argument); /* USER CODE BEGIN PFP */ -// redirect the output of the printf function to the USART print function -// is calling fputc to transmit the output via the USART. -#define PUTCHAR_PROTOTYPE +void print_system_info(void); +void ringbuffer_callback(uint16_t delimiterfound, void * cb_data); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ +#define rxbuf_size 64 +#define mainbuf_size 64 + +uint8_t rxbuf[rxbuf_size]; +uint8_t done = 0; +hring ring; + +void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { + if (huart->Instance == LPUART1) { + ringbuf_push(ring, rxbuf, Size); + //ringbuf_dump(ring); + HAL_UARTEx_ReceiveToIdle_DMA(huart, rxbuf, rxbuf_size); + //__HAL_DMA_DISABLE_IT(&hdma_lpuart_rx, DMA_IT_HT); + } else { + __NOP(); + } +} + +// void (*ringbuf_rcv_cb_t)(uint16_t delimiterfound, void* cb_data); +void ringbuffer_callback(uint16_t delimiterfound, void * cb_data) { + + (void)cb_data; + (void)delimiterfound; + + HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); + osSemaphoreRelease(commandHandle); +} /* USER CODE END 0 */ @@ -118,7 +157,6 @@ int main(void) /* USER CODE BEGIN 1 */ /* int status = 0; */ - /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ @@ -139,13 +177,30 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); + MX_I2C1_Init(); MX_LPUART1_UART_Init(); MX_RTC_Init(); - MX_I2C1_Init(); /* USER CODE BEGIN 2 */ - si5351_inst_t si5351_inst = 0; + print_system_info(); + + + // do some tests for ringbuf.h library + + //struct ringbuf * ring; + + ring = ringbuf_create(mainbuf_size, RINGBUF_ALLOWOVERWRITE); + if (ring == NULL) + puts("Can't create memory for ringbuffer"); + HAL_UARTEx_ReceiveToIdle_DMA(&hlpuart1, rxbuf, rxbuf_size); + __HAL_DMA_DISABLE_IT(&hdma_lpuart_rx, DMA_IT_HT); + + (void)ringbuf_callback_register(ring, ringbuffer_callback, NULL); +// #define NDEBUG + // ringbuf_test(); + // 1st SI5351 chip at the I2C bus "hi2c1", address line A0 = 0 si5351_inst = si5351_init(&hi2c1, 25000000, 0x60, 0); { @@ -216,7 +271,7 @@ int main(void) #endif - HAL_Delay(20000); + HAL_Delay(1000); #if 0 while (1) { @@ -265,15 +320,13 @@ int main(void) // si5351_enable_output(si5351_inst,1); // HAL_Delay(1000); -#if 1 +#if 0 si5351_set_clk0(si5351_inst, 3550000); si5351_set_clk(si5351_inst, 3570000, 2, SI5351_PLLB); si5351_enable_output(NULL,2); #endif - - /* USER CODE END 2 */ /* Init scheduler */ @@ -287,6 +340,9 @@ int main(void) /* creation of si5351 */ si5351Handle = osSemaphoreNew(1, 1, &si5351_attributes); + /* creation of command */ + commandHandle = osSemaphoreNew(1, 1, &command_attributes); + /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ @@ -301,16 +357,16 @@ int main(void) /* Create the thread(s) */ /* creation of defaultTask */ - //defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); + defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); /* creation of terminalTask */ terminalTaskHandle = osThreadNew(start_terminal_task, NULL, &terminalTask_attributes); /* creation of morseTask */ - //morseTaskHandle = osThreadNew(start_morse_task, (void*) si5351_inst, &morseTask_attributes); + morseTaskHandle = osThreadNew(start_morse_task, (void*) si5351_inst, &morseTask_attributes); /* creation of clk2Task */ - //clk2TaskHandle = osThreadNew(start_clk2_task, (void*) si5351_inst, &clk2Task_attributes); + clk2TaskHandle = osThreadNew(start_clk2_task, (void*) si5351_inst, &clk2Task_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ @@ -469,7 +525,9 @@ static void MX_LPUART1_UART_Init(void) hlpuart1.Init.Mode = UART_MODE_TX_RX; hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; - hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT; + hlpuart1.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE; + hlpuart1.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR; if (HAL_UART_Init(&hlpuart1) != HAL_OK) { Error_Handler(); @@ -544,6 +602,22 @@ static void MX_RTC_Init(void) } +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA2_Channel7_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Channel7_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA2_Channel7_IRQn); + +} + /** * @brief GPIO Initialization Function * @param None @@ -699,12 +773,28 @@ static void MX_GPIO_Init(void) } /* USER CODE BEGIN 4 */ -void HAL_UART_RxCpltCallback(UART_HandleTypeDef *hlpuart) { - HAL_UART_Transmit(&hlpuart1, UART1_rxBuffer, 1, 100); - HAL_UART_Receive_IT(&hlpuart1, UART1_rxBuffer, 1); -} +/** + * @brief UART error callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback can be implemented in the user file. + */ + printf("UART error %ld\n", huart->ErrorCode); + if (HAL_UART_Init(&hlpuart1) != HAL_OK) + { + Error_Handler(); + } +} + /** * @brief Retargets the C library printf function to the USART. * @param None @@ -715,25 +805,41 @@ int __io_putchar(int ch) /* Place your implementation of fputc here */ /* e.g. write a character to the USART1 and Loop until the end of transmission */ uint8_t xch = (uint8_t)ch; + volatile HAL_StatusTypeDef hstat; /* - * Only for Windows PCs: + * Only for Windows PCs or Eclipse Terminal: */ -#if 0 - if(ch=='\n') - putchar('\r'); +#if 1 + if(ch=='\n') /* 0xA, 10, LF */ + __io_putchar('\r'); /* 0xD, 13, CR */ #endif - HAL_UART_Transmit(&hlpuart1, &xch, 1, HAL_MAX_DELAY); + // HAL_UART_Transmit(&hlpuart1, &xch, 1, HAL_MAX_DELAY); + do { + hstat = HAL_UART_Transmit_IT(&hlpuart1, &xch, 1); + } while (hstat == HAL_BUSY); return ch; } int _write(int fd, unsigned char *p, int len) { + int l = len; (void)fd; - while (len--) + while (l--) __io_putchar(*p++); return len; } +//int _write_r(void *reent, int fd, char *p, size_t len) +//{ +// return _write(fd, p, len); +//} + +void print_system_info(void) { + puts("\n**************************************"); + puts(PROGRAM_ID " " AUTHOR_STRING); + puts("Compiled: " __DATE__ " " __TIME__); +} + void make_di_dah(si5351_inst_t inst, unsigned int dah, uint32_t delay, uint8_t clk) { #define SEMAPHORE 0 /* inner function, no need to check inst, clk, nor delay */ @@ -782,9 +888,9 @@ void morse(si5351_inst_t inst, char * s, uint32_t delay, uint8_t clk) { return; while ((ch = *s++)) { - /* ascii code: numbers b/w 0x30 - 0x39 chars b/w 0x41 - 0x5A and 0x61 - 0x7A */ + /* ASCII code: numbers b/w 0x30 - 0x39 chars b/w 0x41 - 0x5A and 0x61 - 0x7A */ if ((ch > 0x40 && ch < 0x5B) || (ch > 0x60 && ch < 0x7B)) { - ch &= 0xDF; // make uppercase + ch &= 0xDF; // make upper case ch = mcode[ch - 0x41]; // index 0 for 'A' } else if (ch > 0x2F && ch < 0x3A) { ch = mcode[ch - 22]; @@ -853,6 +959,7 @@ void morse(si5351_inst_t inst, char * s, uint32_t delay, uint8_t clk) { osDelay(3 * delay); //word inter character space (gap b/w the characters of a word) 3 units } } + /* USER CODE END 4 */ /* USER CODE BEGIN Header_StartDefaultTask */ @@ -869,29 +976,38 @@ void StartDefaultTask(void *argument) int sw, sw_last = GPIO_PIN_RESET; - int counter = 10; + int counter = 6; /* Infinite loop */ for(;;) { - // HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); - HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); + HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); + //HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); osDelay(100); - HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); + HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); + //HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET); sw = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); if (sw_last == GPIO_PIN_RESET && sw == GPIO_PIN_SET) { leds_on = !leds_on; counter--; } sw_last = sw; - osDelay(2000); - if (!counter) - break; + osDelay(5000); + if (counter == 4) { + vTaskSuspend(morseTaskHandle); + } + if (counter == 2) { + vTaskSuspend(clk2TaskHandle); + } + if (!counter) { + vTaskSuspend(NULL); + } } /* USER CODE END 5 */ } /* USER CODE BEGIN Header_start_terminal_task */ + /** * @brief Function implementing the terminalTask thread. * @param argument: Not used @@ -903,22 +1019,39 @@ void start_terminal_task(void *argument) /* USER CODE BEGIN start_terminal_task */ (void)argument; - HAL_StatusTypeDef status; - RTC_TimeTypeDef time; - RTC_DateTypeDef date; - uint8_t LPUART1_rxBuffer[100]; + + char data[128]; + char *tdata = data; + int bytes; + int rv; /* Infinite loop */ for(;;) { - HAL_UART_Receive_IT(&hlpuart1, UART1_rxBuffer, 1); - - status = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); - if (status != HAL_OK) - puts("HAL_RTC_GetTime problem..."); - status = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN); - printf("%02d%02d-%02d-%02d %02d:%02d:%02d\n", (date.Year < 22) ? 21 : 20, date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds); - - osDelay(999); + //HAL_UART_Receive_IT(&hlpuart1, UART1_rxBuffer, 1); + // osSemaphoreRelease is in the callback function when a command is entered + osSemaphoreAcquire(commandHandle, osWaitForever); +// status = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); +// if (status != HAL_OK) +// puts("HAL_RTC_GetTime problem..."); +// status = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN); +// printf("%02d%02d-%02d-%02d %02d:%02d:%02d\n", (date.Year < 22) ? 21 : 20, date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds); + //ringbuf_dump(ring); + do { + bytes = ringbuf_read(ring, data); + printf("READ (%d): %s\n",bytes, data); + if (bytes) { + ringbuf_dump(ring); + tdata = trim(data); + printf("TRIMMED (%d): %s\n",strlen(tdata), tdata); + rv = cmd_interpreter(tdata); + if (rv) { + printf("ERROR: %d\n", -rv); + } + } + if (ringbuf_is_empty(ring)) + break; + } while (bytes); + //osDelay(9999); } /* USER CODE END start_terminal_task */ } @@ -943,7 +1076,7 @@ void start_morse_task(void *argument) /* Infinite loop */ for (;;) { // check clock RTC for e.g. cycle of 1 minutes TX with 4 minutes pause period - if(++i % 16) { /* do this for 7 of 8 times, ones morse in high speed my call */ + if(++i % 32) { /* do this 31 times, then Morse my callsign once at high speed */ morse(inst, "MO", morsedelay, clk); } else { morsedelay = delay/3; @@ -970,12 +1103,12 @@ void start_clk2_task(void *argument) si5351_inst_t inst = argument; int i = 0; uint32_t morsedelay = delay; - si5351_set_clk (inst, 3550000, clk, SI5351_PLLB); + si5351_set_clk (inst, 3582000, clk, SI5351_PLLB); /* Infinite loop */ for (;;) { // check clock RTC for e.g. cycle of 1 minutes TX with 4 minutes pause period - if(++i % 16) { /* do this for 7 of 8 times, ones morse in high speed my call */ + if(++i % 32) { /* do this 31 times, then Morse my callsign once at high speed */ morse(inst, "MOe", morsedelay, clk); } else { morsedelay = delay/3; @@ -1000,7 +1133,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) /* USER CODE BEGIN Callback 0 */ /* USER CODE END Callback 0 */ -if (htim->Instance == TIM6) { + if (htim->Instance == TIM6) { HAL_IncTick(); } /* USER CODE BEGIN Callback 1 */ @@ -1017,6 +1150,7 @@ void Error_Handler(void) /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); + puts("ERROR HANDLER"); while (1) { } @@ -1036,7 +1170,7 @@ void assert_failed(uint8_t *file, uint32_t line) /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - printf("Wrong parameters value: file %s on line %d\r\n", file, line); + printf("Wrong parameters value: file %s on line %u\r\n", file, line); /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ diff --git a/Core/Src/stm32_si5351.c b/Core/Src/stm32_si5351.c index 626066a..3122056 100644 --- a/Core/Src/stm32_si5351.c +++ b/Core/Src/stm32_si5351.c @@ -22,10 +22,10 @@ /* Includes ------------------------------------------------------------------*/ #include +#include #ifdef DEBUG #define SI5351_DEBUG 0 #include -#include #endif #include @@ -45,7 +45,7 @@ typedef struct __SI5351_HandleTypeDef { size_t datasize; /*!< size of data, set to 0 if not used */ struct __SI5351_HandleTypeDef *next; /*!< next pointer to the following structure when there are several instances */ #ifdef SI5351_DEBUG - char debug_msg[1000]; /*!< debugging messages for extesive tests of the Si5351 chip, not required */ + char debug_msg[1000]; /*!< debugging messages for extensive tests of the Si5351 chip, not required */ #endif uint8_t clk_is_pllb; /*!< assignment of PLLA or PLLB per CLK #, if bit set to 1 ...PLLB */ uint8_t clk_is_disabled; /*!< assignment of Output Enable Control, app. Register 3 */ @@ -115,7 +115,9 @@ si5351_HandleTypeDef * first_handle = NULL; /* pointer to the first instance */ int si5351_errno = 0; /* error_number for functions whith return == NULL */ /* Private function prototypes -----------------------------------------------*/ +#ifdef DEBUG int __fprintb(FILE *stream, void *value, size_t size); +#endif int si5351_read(si5351_inst_t instance, uint8_t regaddr, uint8_t *data, uint16_t size); int si5351_write(si5351_inst_t instance, uint8_t regaddr, uint8_t *data, uint16_t size); int calculation(uint32_t frequency, uint32_t xtal, synthesis_t *synth); @@ -665,6 +667,7 @@ int si5351_set_clk_phase(si5351_inst_t inst, uint32_t frequency, double phase, u //pll_frequency = ((double)synth.pll_multiplier + (double)(synth.pll_numerator / synth.pll_denominator)) * (double)inst->xtal_frequency; //phaseoff = 4.0 * pll_frequency; (void)phaseoff; + (void)pll_frequency; } else { inst->clk_has_phase_shift &= (uint8_t)~(1u << clk); /* reset phase shift */ @@ -870,6 +873,7 @@ int si5351_read_data(si5351_inst_t inst, void * data) { } #endif +#ifdef DEBUG /*! * @brief Output the value in binary representation and in groups of * bytes @@ -927,4 +931,4 @@ char * si5351_read_register_debug(si5351_inst_t inst, char *buf, size_t bufsize, cx += snprintf(buf + cx, bufsize - (size_t)cx, "]"); return buf; } - +#endif //DEBUG diff --git a/Core/Src/stm32l4xx_hal_msp.c b/Core/Src/stm32l4xx_hal_msp.c index e163b55..f96cf7e 100644 --- a/Core/Src/stm32l4xx_hal_msp.c +++ b/Core/Src/stm32l4xx_hal_msp.c @@ -23,6 +23,7 @@ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ +extern DMA_HandleTypeDef hdma_lpuart_rx; /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ @@ -196,6 +197,24 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitStruct.Alternate = GPIO_AF8_LPUART1; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + /* LPUART1 DMA Init */ + /* LPUART_RX Init */ + hdma_lpuart_rx.Instance = DMA2_Channel7; + hdma_lpuart_rx.Init.Request = DMA_REQUEST_4; + hdma_lpuart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_lpuart_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_lpuart_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_lpuart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_lpuart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_lpuart_rx.Init.Mode = DMA_NORMAL; + hdma_lpuart_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_lpuart_rx) != HAL_OK) + { + Error_Handler(); + } + + __HAL_LINKDMA(huart,hdmarx,hdma_lpuart_rx); + /* LPUART1 interrupt Init */ HAL_NVIC_SetPriority(LPUART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(LPUART1_IRQn); @@ -228,6 +247,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) */ HAL_GPIO_DeInit(GPIOG, STLK_RX_Pin|STLK_TX_Pin); + /* LPUART1 DMA DeInit */ + HAL_DMA_DeInit(huart->hdmarx); + /* LPUART1 interrupt DeInit */ HAL_NVIC_DisableIRQ(LPUART1_IRQn); /* USER CODE BEGIN LPUART1_MspDeInit 1 */ diff --git a/Core/Src/stm32l4xx_hal_timebase_tim.c b/Core/Src/stm32l4xx_hal_timebase_tim.c index c3e7789..385b996 100644 --- a/Core/Src/stm32l4xx_hal_timebase_tim.c +++ b/Core/Src/stm32l4xx_hal_timebase_tim.c @@ -41,14 +41,11 @@ TIM_HandleTypeDef htim6; HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { RCC_ClkInitTypeDef clkconfig; - uint32_t uwTimclock = 0; - uint32_t uwPrescalerValue = 0; - uint32_t pFLatency; - /*Configure the TIM6 IRQ priority */ - HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0); + uint32_t uwTimclock, uwAPB1Prescaler; - /* Enable the TIM6 global Interrupt */ - HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + uint32_t uwPrescalerValue; + uint32_t pFLatency; + HAL_StatusTypeDef status = HAL_OK; /* Enable TIM6 clock */ __HAL_RCC_TIM6_CLK_ENABLE(); @@ -56,8 +53,18 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) /* Get clock configuration */ HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + /* Get APB1 prescaler */ + uwAPB1Prescaler = clkconfig.APB1CLKDivider; /* Compute TIM6 clock */ - uwTimclock = 2*HAL_RCC_GetPCLK1Freq(); + if (uwAPB1Prescaler == RCC_HCLK_DIV1) + { + uwTimclock = HAL_RCC_GetPCLK1Freq(); + } + else + { + uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq(); + } + /* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */ uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U); @@ -74,15 +81,33 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) htim6.Init.Prescaler = uwPrescalerValue; htim6.Init.ClockDivision = 0; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; + htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; - if(HAL_TIM_Base_Init(&htim6) == HAL_OK) + status = HAL_TIM_Base_Init(&htim6); + if (status == HAL_OK) { /* Start the TIM time Base generation in interrupt mode */ - return HAL_TIM_Base_Start_IT(&htim6); + status = HAL_TIM_Base_Start_IT(&htim6); + if (status == HAL_OK) + { + /* Enable the TIM6 global Interrupt */ + HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + /* Configure the SysTick IRQ priority */ + if (TickPriority < (1UL << __NVIC_PRIO_BITS)) + { + /* Configure the TIM IRQ priority */ + HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority, 0U); + uwTickPrio = TickPriority; + } + else + { + status = HAL_ERROR; + } + } } - /* Return function status */ - return HAL_ERROR; + /* Return function status */ + return status; } /** diff --git a/Core/Src/stm32l4xx_it.c b/Core/Src/stm32l4xx_it.c index 62f399d..3d959d5 100644 --- a/Core/Src/stm32l4xx_it.c +++ b/Core/Src/stm32l4xx_it.c @@ -55,6 +55,7 @@ /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ +extern DMA_HandleTypeDef hdma_lpuart_rx; extern UART_HandleTypeDef hlpuart1; extern TIM_HandleTypeDef htim6; @@ -174,6 +175,20 @@ void TIM6_DAC_IRQHandler(void) /* USER CODE END TIM6_DAC_IRQn 1 */ } +/** + * @brief This function handles DMA2 channel7 global interrupt. + */ +void DMA2_Channel7_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel7_IRQn 0 */ + + /* USER CODE END DMA2_Channel7_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_lpuart_rx); + /* USER CODE BEGIN DMA2_Channel7_IRQn 1 */ + + /* USER CODE END DMA2_Channel7_IRQn 1 */ +} + /** * @brief This function handles LPUART1 global interrupt. */ diff --git a/stm32l4a6zg-f0x.at1.ioc b/stm32l4a6zg-f0x.at1.ioc index e42a43f..88820fa 100644 --- a/stm32l4a6zg-f0x.at1.ioc +++ b/stm32l4a6zg-f0x.at1.ioc @@ -1,8 +1,19 @@ #MicroXplorer Configuration settings - do not modify -FREERTOS.BinarySemaphores01=si5351,Dynamic,NULL +Dma.LPUART_RX.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.LPUART_RX.0.Instance=DMA2_Channel7 +Dma.LPUART_RX.0.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.LPUART_RX.0.MemInc=DMA_MINC_ENABLE +Dma.LPUART_RX.0.Mode=DMA_NORMAL +Dma.LPUART_RX.0.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.LPUART_RX.0.PeriphInc=DMA_PINC_DISABLE +Dma.LPUART_RX.0.Priority=DMA_PRIORITY_LOW +Dma.LPUART_RX.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.Request0=LPUART_RX +Dma.RequestsNb=1 +FREERTOS.BinarySemaphores01=si5351,Dynamic,NULL;command,Dynamic,NULL FREERTOS.FootprintOK=true FREERTOS.IPParameters=Tasks01,configUSE_NEWLIB_REENTRANT,FootprintOK,configTOTAL_HEAP_SIZE,BinarySemaphores01 -FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;terminalTask,16,128,start_terminal_task,Default,NULL,Dynamic,NULL,NULL;morseTask,24,128,start_morse_task,Default,si5351_inst,Dynamic,NULL,NULL;clk2Task,40,128,start_clk2_task,Default,si5351_inst,Dynamic,NULL,NULL +FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;terminalTask,24,256,start_terminal_task,Default,NULL,Dynamic,NULL,NULL;morseTask,24,128,start_morse_task,Default,si5351_inst,Dynamic,NULL,NULL;clk2Task,40,128,start_clk2_task,Default,si5351_inst,Dynamic,NULL,NULL FREERTOS.configTOTAL_HEAP_SIZE=30000 FREERTOS.configUSE_NEWLIB_REENTRANT=1 File.Version=6 @@ -15,13 +26,13 @@ I2C1.Timing=0x00000001 KeepUserPlacement=false LPUART1.AutoBaudRateEnableParam=UART_ADVFEATURE_AUTOBAUDRATE_DISABLE LPUART1.BaudRate=115200 -LPUART1.DMADisableonRxErrorParam=UART_ADVFEATURE_DMA_ENABLEONRXERROR +LPUART1.DMADisableonRxErrorParam=UART_ADVFEATURE_DMA_DISABLEONRXERROR LPUART1.DataInvertParam=UART_ADVFEATURE_DATAINV_DISABLE LPUART1.IPParameters=WordLength,Parity,StopBits,Mode,OneBitSampling,AutoBaudRateEnableParam,TxPinLevelInvertParam,RxPinLevelInvertParam,DataInvertParam,SwapParam,OverrunDisableParam,DMADisableonRxErrorParam,MSBFirstParam,BaudRate LPUART1.MSBFirstParam=UART_ADVFEATURE_MSBFIRST_DISABLE LPUART1.Mode=UART_MODE_TX_RX LPUART1.OneBitSampling=UART_ONE_BIT_SAMPLE_DISABLE -LPUART1.OverrunDisableParam=UART_ADVFEATURE_OVERRUN_ENABLE +LPUART1.OverrunDisableParam=UART_ADVFEATURE_OVERRUN_DISABLE LPUART1.Parity=UART_PARITY_NONE LPUART1.RxPinLevelInvertParam=UART_ADVFEATURE_RXINV_DISABLE LPUART1.StopBits=UART_STOPBITS_1 @@ -30,14 +41,15 @@ LPUART1.TxPinLevelInvertParam=UART_ADVFEATURE_TXINV_DISABLE LPUART1.WordLength=UART_WORDLENGTH_8B Mcu.CPN=STM32L4A6ZGT6 Mcu.Family=STM32L4 -Mcu.IP0=FREERTOS -Mcu.IP1=I2C1 -Mcu.IP2=LPUART1 -Mcu.IP3=NVIC -Mcu.IP4=RCC -Mcu.IP5=RTC -Mcu.IP6=SYS -Mcu.IPNb=7 +Mcu.IP0=DMA +Mcu.IP1=FREERTOS +Mcu.IP2=I2C1 +Mcu.IP3=LPUART1 +Mcu.IP4=NVIC +Mcu.IP5=RCC +Mcu.IP6=RTC +Mcu.IP7=SYS +Mcu.IPNb=8 Mcu.Name=STM32L4A6ZGTx Mcu.Package=LQFP144 Mcu.Pin0=PE2 @@ -156,26 +168,27 @@ Mcu.PinsNb=112 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32L4A6ZGTx -MxCube.Version=6.5.0 -MxDb.Version=DB.6.0.50 -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true +MxCube.Version=6.6.1 +MxDb.Version=DB.6.0.60 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false +NVIC.DMA2_Channel7_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false NVIC.ForceEnableDMAVector=true -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false NVIC.LPUART1_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true -NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:true\:false\:true +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false +NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:true\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:true\:false\:true +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:true\:false\:false NVIC.SavedPendsvIrqHandlerGenerated=true NVIC.SavedSvcallIrqHandlerGenerated=true NVIC.SavedSystickIrqHandlerGenerated=true -NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:true\:true\:true +NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:true\:true\:false NVIC.TIM6_DAC_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true NVIC.TimeBase=TIM6_DAC_IRQn NVIC.TimeBaseIP=TIM6 -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false\:false PA0.Signal=GPIO_Analog PA1.Signal=GPIO_Analog PA10.GPIOParameters=GPIO_Label @@ -418,7 +431,7 @@ ProjectManager.StackSize=0x400 ProjectManager.TargetToolchain=STM32CubeIDE ProjectManager.ToolChainLocation= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_LPUART1_UART_Init-LPUART1-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_I2C1_Init-I2C1-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_LPUART1_UART_Init-LPUART1-false-HAL-true,6-MX_RTC_Init-RTC-false-HAL-true RCC.ADCFreq_Value=48000000 RCC.AHBCLKDivider=RCC_SYSCLK_DIV8 RCC.AHBFreq_Value=5916666.666666667 @@ -496,5 +509,4 @@ VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar VP_SYS_VS_tim6.Mode=TIM6 VP_SYS_VS_tim6.Signal=SYS_VS_tim6 board=NUCLEO-L4A6ZG -boardIOC=true isbadioc=false