From 9f41ac96a29f54000750bac53381756eb3721d73 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 15 Aug 2020 23:00:42 +1000 Subject: [PATCH 01/72] Port Pine64 base BSP package --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 50 + .../TS100/Core/BSP/Pine64/FreeRTOSConfig.h | 98 + .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 439 ++++ workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 53 + workspace/TS100/Core/BSP/Pine64/IRQ.h | 25 + workspace/TS100/Core/BSP/Pine64/N200/port.c | 361 +++ .../TS100/Core/BSP/Pine64/N200/portasm.S | 436 ++++ .../TS100/Core/BSP/Pine64/N200/portmacro.h | 142 ++ workspace/TS100/Core/BSP/Pine64/NOTES.md | 38 + workspace/TS100/Core/BSP/Pine64/Pins.h | 38 + workspace/TS100/Core/BSP/Pine64/Power.cpp | 11 + workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp | 33 + workspace/TS100/Core/BSP/Pine64/README.md | 12 + workspace/TS100/Core/BSP/Pine64/Setup.c | 294 +++ workspace/TS100/Core/BSP/Pine64/Setup.h | 22 + .../TS100/Core/BSP/Pine64/UnitSettings.h | 11 + .../BSP/Pine64/Vendor/Lib/GD32VF103xB.lds | 176 ++ .../Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c | 117 + .../Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c | 112 + .../TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h | 65 + .../Core/BSP/Pine64/Vendor/Lib/gd32vf103.h | 246 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_adc.c | 992 +++++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_adc.h | 401 ++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_bkp.c | 292 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_bkp.h | 231 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_crc.c | 127 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_crc.h | 83 + .../BSP/Pine64/Vendor/Lib/gd32vf103_dbg.c | 110 + .../BSP/Pine64/Vendor/Lib/gd32vf103_dbg.h | 113 + .../BSP/Pine64/Vendor/Lib/gd32vf103_dma.c | 732 ++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_dma.h | 287 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_eclic.c | 121 + .../BSP/Pine64/Vendor/Lib/gd32vf103_eclic.h | 71 + .../BSP/Pine64/Vendor/Lib/gd32vf103_exti.c | 254 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_exti.h | 250 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_fmc.c | 651 ++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_fmc.h | 313 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.c | 151 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.h | 109 + .../BSP/Pine64/Vendor/Lib/gd32vf103_gpio.c | 502 +++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_gpio.h | 426 ++++ .../Core/BSP/Pine64/Vendor/Lib/gd32vf103_hw.c | 195 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c | 730 ++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_i2c.h | 347 +++ .../Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.c | 54 + .../Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.h | 51 + .../BSP/Pine64/Vendor/Lib/gd32vf103_libopt.h | 63 + .../BSP/Pine64/Vendor/Lib/gd32vf103_pmu.c | 270 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_pmu.h | 130 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_rcu.c | 1111 ++++++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_rcu.h | 721 ++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_rtc.c | 273 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_rtc.h | 153 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_spi.c | 766 +++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_spi.h | 346 +++ .../BSP/Pine64/Vendor/Lib/gd32vf103_timer.c | 1966 +++++++++++++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_timer.h | 726 ++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_usart.c | 765 +++++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_usart.h | 376 ++++ .../BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.c | 146 ++ .../BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.h | 91 + .../Core/BSP/Pine64/Vendor/Lib/handlers.c | 25 + .../Core/BSP/Pine64/Vendor/Lib/handlers.h | 15 + .../TS100/Core/BSP/Pine64/Vendor/Lib/init.c | 34 + .../Core/BSP/Pine64/Vendor/Lib/integer.h | 50 + .../BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S | 35 + .../TS100/Core/BSP/Pine64/Vendor/Lib/read.c | 13 + .../TS100/Core/BSP/Pine64/Vendor/Lib/rtc.c | 205 ++ .../TS100/Core/BSP/Pine64/Vendor/Lib/rtc.h | 54 + .../TS100/Core/BSP/Pine64/Vendor/Lib/stub.h | 22 + .../BSP/Pine64/Vendor/Lib/system_gd32vf103.c | 999 +++++++++ .../BSP/Pine64/Vendor/Lib/system_gd32vf103.h | 60 + .../Core/BSP/Pine64/Vendor/Lib/systick.c | 57 + .../Core/BSP/Pine64/Vendor/Lib/systick.h | 47 + .../TS100/Core/BSP/Pine64/Vendor/Lib/write.c | 47 + .../Core/BSP/Pine64/Vendor/Lib/write_hex.c | 18 + .../Core/BSP/Pine64/Vendor/Lib/your_printf.c | 4 + .../Core/BSP/Pine64/Vendor/RISCV/entry.S | 291 +++ .../Core/BSP/Pine64/Vendor/RISCV/n200_eclic.h | 48 + .../Core/BSP/Pine64/Vendor/RISCV/n200_func.c | 398 ++++ .../Core/BSP/Pine64/Vendor/RISCV/n200_func.h | 109 + .../Core/BSP/Pine64/Vendor/RISCV/n200_timer.h | 18 + .../Core/BSP/Pine64/Vendor/RISCV/riscv_bits.h | 36 + .../BSP/Pine64/Vendor/RISCV/riscv_const.h | 18 + .../BSP/Pine64/Vendor/RISCV/riscv_encoding.h | 1369 ++++++++++++ .../Core/BSP/Pine64/Vendor/RISCV/start.S | 289 +++ .../TS100/Core/BSP/Pine64/Vendor/heap_4.c | 478 ++++ workspace/TS100/Core/BSP/Pine64/flash.c | 23 + workspace/TS100/Core/BSP/Pine64/logo.cpp | 27 + workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 14 + workspace/TS100/Core/BSP/Pine64/preRTOS.cpp | 21 + 91 files changed, 23099 insertions(+) create mode 100644 workspace/TS100/Core/BSP/Pine64/BSP.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h create mode 100644 workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/IRQ.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/IRQ.h create mode 100644 workspace/TS100/Core/BSP/Pine64/N200/port.c create mode 100644 workspace/TS100/Core/BSP/Pine64/N200/portasm.S create mode 100644 workspace/TS100/Core/BSP/Pine64/N200/portmacro.h create mode 100644 workspace/TS100/Core/BSP/Pine64/NOTES.md create mode 100644 workspace/TS100/Core/BSP/Pine64/Pins.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Power.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/README.md create mode 100644 workspace/TS100/Core/BSP/Pine64/Setup.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Setup.h create mode 100644 workspace/TS100/Core/BSP/Pine64/UnitSettings.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_hw.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_libopt.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/integer.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write_hex.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/your_printf.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_eclic.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_timer.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_bits.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_const.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_encoding.h create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/heap_4.c create mode 100644 workspace/TS100/Core/BSP/Pine64/flash.c create mode 100644 workspace/TS100/Core/BSP/Pine64/logo.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/postRTOS.cpp create mode 100644 workspace/TS100/Core/BSP/Pine64/preRTOS.cpp diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp new file mode 100644 index 00000000..0a31b154 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -0,0 +1,50 @@ +// BSP mapping functions + +#include "BSP.h" +#include "I2C_Wrapper.hpp" +#include "Pins.h" +#include "Setup.h" +#include "gd32vf103_timer.h" +#include "history.hpp" +#include "main.hpp" +#include "systick.h" +#include + +void resetWatchdog() { + //TODO +} + +uint16_t getTipInstantTemperature() { + uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits + + for (int i = 0; i < 4; i++) { + sum += adc_inserted_data_read(ADC0, i); + sum += adc_inserted_data_read(ADC1, i); + } + return sum; // 8x over sample +} + +// Timer callbacks +// TODO +// Handle callback of the PWM modulator to enable / disable the output PWM + +void unstick_I2C() { + // TODO +} + +uint8_t getButtonA() { + // TODO + return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == RESET) ? 1 : 0; +} +uint8_t getButtonB() { + // TODO + return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == RESET) ? 1 : 0; +} + +void reboot() { + // TODO + for (;;) { + } +} + +void delay_ms(uint16_t count) { delay_1ms(count); } diff --git a/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h new file mode 100644 index 00000000..d1e9b3fd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h @@ -0,0 +1,98 @@ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif +//RISC-V configuration + +#define USER_MODE_TASKS 0 + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_TICKLESS_IDLE 0 +#define configCPU_CLOCK_HZ ((uint32_t)SystemCoreClock) +#define configRTC_CLOCK_HZ ((uint32_t)TIMER_FREQ) +#define configTICK_RATE_HZ ((TickType_t)100) +#define configMAX_PRIORITIES (4) //0 - 3 å…±6等级,idle独å� 0,Tmr_svc独å� 3 +#define configMINIMAL_STACK_SIZE ((unsigned short)128) +#define configMAX_TASK_NAME_LEN 24 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 0 +#define configUSE_COUNTING_SEMAPHORES 0 +#define configQUEUE_REGISTRY_SIZE 10 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 1 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 0 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_vTaskDelay 1 +/* Memory allocation related definitions. */ +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configTOTAL_HEAP_SIZE 1024 +#define configAPPLICATION_ALLOCATED_HEAP 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Co-routine related definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 1 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 0 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) //Tmr_svc 独å� æœ€é«˜ä¼˜å…ˆçº§ +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Interrupt nesting behaviour configuration. */ +#define configPRIO_BITS (4UL) +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x1 +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0xe +#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Define to trap errors during development. */ +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_xResumeFromISR 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 1 +#define INCLUDE_xTimerPendFunctionCall 0 +#define INCLUDE_xTaskAbortDelay 0 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif /* FREERTOS_CONFIG_H */ diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp new file mode 100644 index 00000000..e73b9891 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -0,0 +1,439 @@ +/* + * FRToSI2C.cpp + * + * Created on: 14Apr.,2018 + * Author: Ralim + */ +#include "BSP.h" +#include "Setup.h" +#include +#define I2CUSESDMA +SemaphoreHandle_t FRToSI2C::I2CSemaphore; +StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; +#define FLAG_TIMEOUT 1000 + +void FRToSI2C::CpltCallback() { + //TODO +} + +/** Send START command + * + * @param obj The I2C object + */ +int i2c_start() { + int timeout; + + /* clear I2C_FLAG_AERR Flag */ + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + + /* wait until I2C_FLAG_I2CBSY flag is reset */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { + + return (int) -1; + } + } + + /* ensure the i2c has been stopped */ + timeout = FLAG_TIMEOUT + ; + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { + if ((timeout--) == 0) { + return (int) -1; + } + } + + /* generate a START condition */ + i2c_start_on_bus(I2C0); + + /* ensure the i2c has been started successfully */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + return (int) -1; + } + } + + return (int) 0; +} + +/** Send STOP command + * + * @param obj The I2C object + */ +int i2c_stop() { + + /* generate a STOP condition */ + i2c_stop_on_bus(I2C0); + + /* wait for STOP bit reset */ + int timeout = FLAG_TIMEOUT; + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) { + if ((timeout--) == 0) { + return -1; + } + } + + return 0; +} + +/** Read one byte + * + * @param obj The I2C object + * @param last Acknoledge + * @return The read byte + */ +int i2c_byte_read(int last) { + int timeout; + + if (last) { + /* disable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } else { + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + } + + /* wait until the byte is received */ + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) { + if ((timeout--) == 0) { + return -1; + } + } + + return (int) i2c_data_receive(I2C0); +} + +/** Write one byte + * + * @param obj The I2C object + * @param data Byte to be written + * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. + */ +int i2c_byte_write(int data) { + int timeout; + i2c_data_transmit(I2C0, data); + + /* wait until the byte is transmitted */ + timeout = FLAG_TIMEOUT; + while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) + || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { + if ((timeout--) == 0) { + return 2; + } + } + + return 1; +} + +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size) { + if (!lock()) + return false; + + uint32_t count = 0; + int timeout = 0; + + /* wait until I2C_FLAG_I2CBSY flag is reset */ + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return false; + } else { + if (timeout % 5 == 0) { + i2c_stop(); + } + } + } + /* generate a START condition */ + i2c_start_on_bus(I2C0); + + /* ensure the i2c has been started successfully */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return false; + } + } + + /* send slave address */ + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + + timeout = 0; + /* wait until I2C_FLAG_ADDSEND flag is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + timeout++; + if (timeout > 100000) { + i2c_stop(); + unlock(); + return false; + } + } + bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); + no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); + if (no_ack) { + i2c_stop(); + unlock(); + return false; + } + /* clear ADDSEND */ + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + int status = i2c_byte_write(MemAddress); + no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); + no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB); + if (status == 2 || no_ack) { + i2c_stop(); + unlock(); + return false; + } +//////////////////////////// //Restart into read + + /* generate a START condition */ + i2c_start_on_bus(I2C0); + + /* ensure the i2c has been started successfully */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return false; + } + } + + /* send slave address */ + i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); + + timeout = 0; + /* wait until I2C_FLAG_ADDSEND flag is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + timeout++; + if (timeout > 100000) { + i2c_stop(); + unlock(); + return false; + } + } + + /* clear ADDSEND */ + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); + if (no_ack) { + i2c_stop(); + unlock(); + return false; + } + for (count = 0; count < Size; count++) { + pData[count] = i2c_byte_read(count == (Size - 1)); + } + + /* if not sequential write, then send stop */ + + i2c_stop(); + unlock(); + return true; +} +void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { + Mem_Write(address, reg, &data, 1); +} + +uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { + uint8_t temp = 0; + Mem_Read(add, reg, &temp, 1); + return temp; +} +void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size) { + if (!lock()) + return; + + uint32_t count = 0; + int timeout = 0; + + /* wait until I2C_FLAG_I2CBSY flag is reset */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return; + } else { + if (timeout % 5 == 0) { + i2c_stop(); + } + } + } + /* generate a START condition */ + i2c_start_on_bus(I2C0); + + /* ensure the i2c has been started successfully */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return; + } + } + + /* send slave address */ + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + + timeout = 0; + /* wait until I2C_FLAG_ADDSEND flag is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + timeout++; + if (timeout > 100000) { + i2c_stop(); + unlock(); + return; + } + } + + /* clear ADDSEND */ + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + int status = i2c_byte_write(MemAddress); + for (count = 0; count < Size; count++) { + status = i2c_byte_write(pData[count]); + if (status != 1) { + i2c_stop(); + unlock(); + return; + } + } + + /* if not sequential write, then send stop */ + + i2c_stop(); + unlock(); +} + +void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { + if (!lock()) + return; + uint32_t count = 0; + int timeout = 0; + + /* wait until I2C_FLAG_I2CBSY flag is reset */ + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return; + } else { + if (timeout % 5 == 0) { + i2c_stop(); + } + } + } + /* generate a START condition */ + i2c_start_on_bus(I2C0); + + /* ensure the i2c has been started successfully */ + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + i2c_stop(); + unlock(); + return; + } + } + + /* send slave address */ + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + + timeout = 0; + /* wait until I2C_FLAG_ADDSEND flag is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + timeout++; + if (timeout > 100000) { + i2c_stop(); + unlock(); + return; + } + } + + /* clear ADDSEND */ + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + + for (count = 0; count < Size; count++) { + int status = i2c_byte_write(pData[count]); + if (status != 1) { + i2c_stop(); + unlock(); + return; + } + } + + /* if not sequential write, then send stop */ + + i2c_stop(); + unlock(); +} + +bool FRToSI2C::probe(uint16_t DevAddress) { + if (!lock()) + return false; + i2c_start(); + /* send slave address to I2C bus */ + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + /* wait until ADDSEND bit is set */ + int timeout = FLAG_TIMEOUT; + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + if (i2c_flag_get(I2C0, I2C_FLAG_AERR) + || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { + i2c_stop(); + unlock(); + return false; + } + if (timeout-- == 0) { + i2c_stop(); + unlock(); + return false; + } + } + + /* clear ADDSEND bit */ + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + /* wait until the transmit data buffer is empty */ + while (!i2c_flag_get(I2C0, I2C_FLAG_TBE)) + ; + bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* wait until stop condition generate */ + while (I2C_CTL0(I2C0) & 0x0200) + ; + unlock(); + return !no_ack; +} + +void FRToSI2C::I2C_Unstick() { + unstick_I2C(); +} + +bool FRToSI2C::lock() { + if (I2CSemaphore == nullptr) + return true; + return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; +} + +void FRToSI2C::unlock() { + if (I2CSemaphore == nullptr) + return; + xSemaphoreGive(I2CSemaphore); +} diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp new file mode 100644 index 00000000..eb2c8885 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -0,0 +1,53 @@ +/* + * IRQ.c + * + * Created on: 30 May 2020 + * Author: Ralim + */ + +#include "IRQ.h" + +void ADC0_1_IRQHandler(void) { + + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); + //unblock the PID controller thread + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (pidTaskNotification) { + vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +volatile uint16_t PWMSafetyTimer = 0; +volatile uint8_t pendingPWM = 0; +void TIMER1_IRQHandler(void) { + + if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) { + timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP); + //rollover turn on output if required + if (PWMSafetyTimer && pendingPWM) { + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 80); + } + if (PWMSafetyTimer) { + PWMSafetyTimer--; + } + } + if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) { + timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1); + //This is triggered on pwm setpoint trigger; we want to copy the pending PWM value into the output control reg + + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); + if (pendingPWM) { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, + pendingPWM); + } + } +} + +void setTipPWM(uint8_t pulse) { + PWMSafetyTimer = 10; +// This is decremented in the handler for PWM so that the tip pwm is +// disabled if the PID task is not scheduled often enough. + + pendingPWM = pulse; +} diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.h b/workspace/TS100/Core/BSP/Pine64/IRQ.h new file mode 100644 index 00000000..8c6c7325 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.h @@ -0,0 +1,25 @@ +/* + * Irqs.h + * + * Created on: 30 May 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_IRQ_H_ +#define BSP_MINIWARE_IRQ_H_ + +#include "BSP.h" +#include "I2C_Wrapper.hpp" +#include "Setup.h" +#include "gd32vf103.h" +#include "main.hpp" + +#ifdef __cplusplus +extern "C" { +#endif +void ADC0_1_IRQHandler(void); +void TIMER1_IRQHandler(void); +#ifdef __cplusplus +} +#endif +#endif /* BSP_MINIWARE_IRQ_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/N200/port.c b/workspace/TS100/Core/BSP/Pine64/N200/port.c new file mode 100644 index 00000000..ac7c84fd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/N200/port.c @@ -0,0 +1,361 @@ +#include "FreeRTOS.h" +#include "task.h" +#include "portmacro.h" +#include "gd32vf103.h" +#include "n200_func.h" +#include "riscv_encoding.h" +#include "n200_timer.h" +#include "n200_eclic.h" + +/* Standard Includes */ +#include +#include +#include + + +/* Each task maintains its own interrupt status in the critical nesting variable. */ +UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +#if USER_MODE_TASKS +#ifdef __riscv_flen + unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); +#else + unsigned long MSTATUS_INIT = (MSTATUS_MPIE); +#endif +#else +#ifdef __riscv_flen + unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); +#else + unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); +#endif +#endif + + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + + +/** + * @brief System Call Trap + * + * @param mcause csr + * @param sp 触发系统调用时的栈地址 + * @param arg1 ECALL macro stores argument in a2 + * @return unsigned long 传入的sp + */ +unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) +{ + switch(mcause&0X00000fff) + { + //on User and Machine ECALL, handler the request + case 8: + case 11: + { + if(arg1==IRQ_DISABLE) + { + //zero out mstatus.mpie + clear_csr(mstatus,MSTATUS_MPIE); + } + else if(arg1==IRQ_ENABLE) + { + //set mstatus.mpie + set_csr(mstatus,MSTATUS_MPIE); + } + else if(arg1==PORT_YIELD) + { + //always yield from machine mode + //fix up mepc on sync trap + unsigned long epc = read_csr(mepc); + vPortYield_from_ulSynchTrap(sp,epc+4); + } + else if(arg1==PORT_YIELD_TO_RA) + { + vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp)))); + } + break; + } + default: + { + /* 异常处理 */ + extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); + handle_trap(mcause,sp); + } + } + + //fix mepc and return + unsigned long epc = read_csr(mepc); + + write_csr(mepc,epc+4); + return sp; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 设置触发软中断 + * @note 目的是在软中断内进行任务上下文切换 + * + */ +void vPortSetMSIPInt(void) +{ + *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01; + __asm volatile("fence"); + __asm volatile("fence.i"); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 清除软中断 + * + */ +void vPortClearMSIPInt(void) +{ + *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 执行任务上下文切换,在portasm.S中被调用 + * + * @param sp 触发任务切换时的栈地址 + * @param arg1 + * @return unsigned long sp地址 + */ +unsigned long taskswitch( unsigned long sp, unsigned long arg1) +{ + //always yield from machine mode + //fix up mepc on + unsigned long epc = read_csr(mepc); + vPortYield(sp,epc); //never returns + + return sp; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用 + * + */ +void vDoTaskSwitchContext( void ) +{ + portDISABLE_INTERRUPTS(); + vTaskSwitchContext(); + portENABLE_INTERRUPTS(); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 进入临界段 + * + */ +void vPortEnterCritical( void ) +{ + #if USER_MODE_TASKS + ECALL(IRQ_DISABLE); + #else + portDISABLE_INTERRUPTS(); + #endif + + uxCriticalNesting++; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 退出临界段 + * + */ +void vPortExitCritical( void ) +{ + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + #if USER_MODE_TASKS + ECALL(IRQ_ENABLE); + #else + portENABLE_INTERRUPTS(); + #endif + } + return; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief Clear current interrupt mask and set given mask + * + * @param int_mask mth值 + */ +void vPortClearInterruptMask(int int_mask) +{ + eclic_set_mth (int_mask); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief Set interrupt mask and return current interrupt enable register + * + * @return int + */ +int xPortSetInterruptMask(void) +{ + int int_mask=0; + int_mask=eclic_get_mth(); + + portDISABLE_INTERRUPTS(); + return int_mask; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 初始化任务栈帧 + * + * @param pxTopOfStack 栈顶 + * @param pxCode 任务入口 + * @param pvParameters 任务参数 + * @return StackType_t* 完成初始化后的栈顶 + */ +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ +#ifdef __riscv_flen + pxTopOfStack -= 32; /* 浮点寄存器 */ +#endif + + pxTopOfStack--; + *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ + + pxTopOfStack--; + *pxTopOfStack = 0x40; /* CSR_SUBM */ + + pxTopOfStack--; + *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ + + pxTopOfStack--; + *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ + + pxTopOfStack -= 22; + *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ + + pxTopOfStack -=9; + *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */ + pxTopOfStack--; + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 任务退出函数 + * + */ +void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief tick中断 + * @note 由于该中断配置为向量模式,则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler + * + */ +void vPortSysTickHandler(void) +{ + volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); + + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + + #if CONFIG_SYSTEMVIEW_EN + traceISR_ENTER(); + #endif + + uint64_t now = *mtime; + now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); + *mtimecmp = now; + + /* 调用freertos的tick增加接口 */ + if( xTaskIncrementTick() != pdFALSE ) + { + #if CONFIG_SYSTEMVIEW_EN + traceISR_EXIT_TO_SCHEDULER(); + #endif + portYIELD(); + } + #if CONFIG_SYSTEMVIEW_EN + else + { + traceISR_EXIT(); + } + #endif + + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 初始化tick + * + */ +void vPortSetupTimer(void) +{ + /* 内核timer定时器使用64位的计数器来实现 */ + volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); + + portENTER_CRITICAL(); + uint64_t now = *mtime; + now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); + *mtimecmp = now; + portEXIT_CRITICAL(); + + eclic_set_vmode(CLIC_INT_TMR); + eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 初始化软中断 + * + */ +void vPortSetupMSIP(void) +{ + eclic_set_vmode(CLIC_INT_SFT); + eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); +} +/*-----------------------------------------------------------*/ + + +/** + * @brief 调度启动前的初始化准备 + * + */ +void vPortSetup(void) +{ + vPortSetupTimer(); + vPortSetupMSIP(); + uxCriticalNesting = 0; +} +/*-----------------------------------------------------------*/ diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portasm.S b/workspace/TS100/Core/BSP/Pine64/N200/portasm.S new file mode 100644 index 00000000..8e34bedb --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/N200/portasm.S @@ -0,0 +1,436 @@ +#include "riscv_encoding.h" +#include "riscv_bits.h" +#include "n200_timer.h" +#include "n200_eclic.h" +#include "riscv_encoding.h" +#include "riscv_bits.h" +#include "n200_timer.h" +#include "n200_eclic.h" + +#define USE_MSP 1 //启用中断栈 + + + .section .text.entry + .align 4 + + .global vPortYield + .global vPortYield_from_ulSynchTrap + .global xPortStartScheduler + .global vPortEndScheduler + .global vPortAsmAssertSP + +/** + * @brife 压栈通用寄存器 + * @param x 目标sp寄存器 + */ +.macro pushREGFILE x +#ifdef __riscv_flen + addi \x, \x, -REGBYTES * 68 //36+32 +#else + addi \x, \x, -REGBYTES * 36 +#endif + STORE x1, 1 * REGBYTES(\x) + STORE x2, 2 * REGBYTES(\x) + //STORE x3, 3 * REGBYTES(\x) + //STORE x4, 4 * REGBYTES(\x) + STORE x5, 5 * REGBYTES(\x) + STORE x6, 6 * REGBYTES(\x) + STORE x7, 7 * REGBYTES(\x) + STORE x8, 8 * REGBYTES(\x) + STORE x9, 9 * REGBYTES(\x) + STORE x10, 10 * REGBYTES(\x) + STORE x11, 11 * REGBYTES(\x) + STORE x12, 12 * REGBYTES(\x) + STORE x13, 13 * REGBYTES(\x) + STORE x14, 14 * REGBYTES(\x) + STORE x15, 15 * REGBYTES(\x) +#ifndef __riscv_32e + STORE x16, 16 * REGBYTES(\x) + STORE x17, 17 * REGBYTES(\x) + STORE x18, 18 * REGBYTES(\x) + STORE x19, 19 * REGBYTES(\x) + STORE x20, 20 * REGBYTES(\x) + STORE x21, 21 * REGBYTES(\x) + STORE x22, 22 * REGBYTES(\x) + STORE x23, 23 * REGBYTES(\x) + STORE x24, 24 * REGBYTES(\x) + STORE x25, 25 * REGBYTES(\x) + STORE x26, 26 * REGBYTES(\x) + STORE x27, 27 * REGBYTES(\x) + STORE x28, 28 * REGBYTES(\x) + STORE x29, 29 * REGBYTES(\x) + STORE x30, 30 * REGBYTES(\x) + STORE x31, 31 * REGBYTES(\x) +#endif +.endm + + +/** + * @brife 压栈csr寄存器(CSR_MSTATUS CSR_MEPC CSR_MSUBM CSR_MCAUSE) + * @param x 目标sp寄存器 + */ +.macro portSAVE_CONTEXT_EXCP x + csrr t0, CSR_MSTATUS + STORE t0, 32 * REGBYTES(\x) + csrr t0, CSR_MEPC + STORE t0, 33 * REGBYTES(\x) + csrr t0, CSR_MSUBM + STORE t0, 34 * REGBYTES(\x) + csrr t0, CSR_MCAUSE + STORE t0, 35 * REGBYTES(\x) +.endm + + +/** + * @brife 压栈浮点寄存器 + * @param x 目标sp寄存器 + */ +.macro pushVFPREGFILE x + fsw f0, 36 * REGBYTES(\x) + fsw f1, 37 * REGBYTES(\x) + fsw f2, 38 * REGBYTES(\x) + fsw f3, 39 * REGBYTES(\x) + fsw f4, 40 * REGBYTES(\x) + fsw f5, 41 * REGBYTES(\x) + fsw f6, 42 * REGBYTES(\x) + fsw f7, 43 * REGBYTES(\x) + fsw f8, 44 * REGBYTES(\x) + fsw f9, 45 * REGBYTES(\x) + fsw f10, 46 * REGBYTES(\x) + fsw f11, 47 * REGBYTES(\x) + fsw f12, 48 * REGBYTES(\x) + fsw f13, 49 * REGBYTES(\x) + fsw f14, 50 * REGBYTES(\x) + fsw f15, 51 * REGBYTES(\x) + fsw f16, 52 * REGBYTES(\x) + fsw f17, 53 * REGBYTES(\x) + fsw f18, 54 * REGBYTES(\x) + fsw f19, 55 * REGBYTES(\x) + fsw f20, 56 * REGBYTES(\x) + fsw f21, 57 * REGBYTES(\x) + fsw f22, 58 * REGBYTES(\x) + fsw f23, 59 * REGBYTES(\x) + fsw f24, 60 * REGBYTES(\x) + fsw f25, 61 * REGBYTES(\x) + fsw f26, 62 * REGBYTES(\x) + fsw f27, 63 * REGBYTES(\x) + fsw f28, 64 * REGBYTES(\x) + fsw f29, 65 * REGBYTES(\x) + fsw f30, 66 * REGBYTES(\x) + fsw f31, 67 * REGBYTES(\x) +.endm + + +/** + * @brife 出栈通用寄存器 + * @param x 目标sp寄存器 + */ +.macro popREGFILE x + LOAD x1, 1 * REGBYTES(\x) + //LOAD x2, 2 * REGBYTES(\x) + //LOAD x3, 3 * REGBYTES(\x) + //LOAD x4, 4 * REGBYTES(\x) + LOAD x5, 5 * REGBYTES(\x) + LOAD x6, 6 * REGBYTES(\x) + LOAD x7, 7 * REGBYTES(\x) + LOAD x8, 8 * REGBYTES(\x) + LOAD x9, 9 * REGBYTES(\x) + LOAD x10, 10 * REGBYTES(\x) + LOAD x11, 11 * REGBYTES(\x) + LOAD x12, 12 * REGBYTES(\x) + LOAD x13, 13 * REGBYTES(\x) + LOAD x14, 14 * REGBYTES(\x) + LOAD x15, 15 * REGBYTES(\x) +#ifndef __riscv_32e + LOAD x16, 16 * REGBYTES(\x) + LOAD x17, 17 * REGBYTES(\x) + LOAD x18, 18 * REGBYTES(\x) + LOAD x19, 19 * REGBYTES(\x) + LOAD x20, 20 * REGBYTES(\x) + LOAD x21, 21 * REGBYTES(\x) + LOAD x22, 22 * REGBYTES(\x) + LOAD x23, 23 * REGBYTES(\x) + LOAD x24, 24 * REGBYTES(\x) + LOAD x25, 25 * REGBYTES(\x) + LOAD x26, 26 * REGBYTES(\x) + LOAD x27, 27 * REGBYTES(\x) + LOAD x28, 28 * REGBYTES(\x) + LOAD x29, 29 * REGBYTES(\x) + LOAD x30, 30 * REGBYTES(\x) + LOAD x31, 31 * REGBYTES(\x) +#endif +#ifdef __riscv_flen + addi \x, \x, REGBYTES * 68 //36+32 +#else + addi \x, \x, REGBYTES * 36 +#endif +.endm + + +/** + * @brife 出栈csr寄存器(CSR_MSTATUS CSR_MEPC CSR_MSUBM CSR_MCAUSE) + * @param x 目标sp寄存器 + */ +.macro portRESTORE_CONTEXT_EXCP x + LOAD t0, 35 * REGBYTES(\x) + csrw CSR_MCAUSE, t0 + LOAD t0, 34 * REGBYTES(\x) + csrw CSR_MSUBM, t0 + LOAD t0, 33 * REGBYTES(\x) + csrw CSR_MEPC, t0 + LOAD t0, 32 * REGBYTES(\x) + csrw CSR_MSTATUS, t0 +.endm + + +/** + * @brife 出栈浮点寄存器 + * @param x 目标sp寄存器 + */ +.macro popVFPREGFILE x + flw f0, 36 * REGBYTES(\x) + flw f1, 37 * REGBYTES(\x) + flw f2, 38 * REGBYTES(\x) + flw f3, 39 * REGBYTES(\x) + flw f4, 40 * REGBYTES(\x) + flw f5, 41 * REGBYTES(\x) + flw f6, 42 * REGBYTES(\x) + flw f7, 43 * REGBYTES(\x) + flw f8, 44 * REGBYTES(\x) + flw f9, 45 * REGBYTES(\x) + flw f10, 46 * REGBYTES(\x) + flw f11, 47 * REGBYTES(\x) + flw f12, 48 * REGBYTES(\x) + flw f13, 49 * REGBYTES(\x) + flw f14, 50 * REGBYTES(\x) + flw f15, 51 * REGBYTES(\x) + flw f16, 52 * REGBYTES(\x) + flw f17, 53 * REGBYTES(\x) + flw f18, 54 * REGBYTES(\x) + flw f19, 55 * REGBYTES(\x) + flw f20, 56 * REGBYTES(\x) + flw f21, 57 * REGBYTES(\x) + flw f22, 58 * REGBYTES(\x) + flw f23, 59 * REGBYTES(\x) + flw f24, 60 * REGBYTES(\x) + flw f25, 61 * REGBYTES(\x) + flw f26, 62 * REGBYTES(\x) + flw f27, 63 * REGBYTES(\x) + flw f28, 64 * REGBYTES(\x) + flw f29, 65 * REGBYTES(\x) + flw f30, 66 * REGBYTES(\x) + flw f31, 67 * REGBYTES(\x) +.endm + + +/** + * @brife 清理fpu状态寄存器 + */ +.macro CONFIG_FS_CLEAN + li t0, (0x1 << 13) + csrc mstatus,t0 + li t0, (0x1 << 14) + csrs mstatus,t0 +.endm + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife trap入口函数 + */ + .global trap_entry + .align 6 +trap_entry: + pushREGFILE sp + + portSAVE_CONTEXT_EXCP sp + + csrr a0, mcause + mv a1, sp + jal ulSynchTrap + mv sp,a0 + + portRESTORE_CONTEXT_EXCP sp + popREGFILE sp + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife trq入口函数 + */ + .align 2 + .global irq_entry +irq_entry: +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + pushREGFILE sp + portSAVE_CONTEXT_EXCP sp +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1,t2,t0 + bne t1,t0,1f + pushVFPREGFILE sp +1: + CONFIG_FS_CLEAN +#endif + +int_loop: + csrrw ra, CSR_JALMNXTI, ra + csrrsi a0, CSR_MNXTI, MSTATUS_MIE + bnez a0, int_loop + + csrc CSR_MSTATUS, MSTATUS_MIE + +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1,t2, t0 + bne t1,t0, 2f + popVFPREGFILE sp +2: +#endif + portRESTORE_CONTEXT_EXCP sp +#ifdef __riscv_flen + CONFIG_FS_CLEAN +#endif + popREGFILE sp +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife MTIME入口函数 + */ + .align 2 + .globl MTIME_HANDLER +MTIME_HANDLER: +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + pushREGFILE sp + portSAVE_CONTEXT_EXCP sp + + csrs CSR_MSTATUS, MSTATUS_MIE + jal vPortSysTickHandler + csrc CSR_MSTATUS, MSTATUS_MIE + + portRESTORE_CONTEXT_EXCP sp + popREGFILE sp +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife MSIP入口函数 + */ + .align 2 + .globl MSIP_HANDLER + +MSIP_HANDLER: + pushREGFILE sp + portSAVE_CONTEXT_EXCP sp + + mv a0,sp + call vPortClearMSIPInt + jal taskswitch + + portRESTORE_CONTEXT_EXCP sp + popREGFILE sp + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife Trap模式请求切换任务函数 + */ + .align 6 +vPortYield_from_ulSynchTrap: + mv sp, a0 + portSAVE_CONTEXT_EXCP sp + + j _vPortYield + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife MSIP模式请求切换任务函数 + */ + .align 6 +vPortYield: + mv sp, a0 +_vPortYield: + LOAD t0, pxCurrentTCB + STORE sp, 0x0(t0) + +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1,t2,t0 + bne t1,t0,1f + pushVFPREGFILE sp +1: + CONFIG_FS_CLEAN +#endif + STORE a1, 33 * REGBYTES(sp) + +#if USE_MSP + csrr sp, CSR_MSCRATCH +#endif + csrs CSR_MSTATUS, MSTATUS_MIE + jal vDoTaskSwitchContext + csrc CSR_MSTATUS, MSTATUS_MIE + + LOAD sp, pxCurrentTCB + LOAD sp, 0x0(sp) + + portRESTORE_CONTEXT_EXCP sp +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1, t2, t0 + bne t1, t0, 2f + popVFPREGFILE sp +2: + CONFIG_FS_CLEAN +#endif + popREGFILE sp + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife freertos启动调度函数 + */ +xPortStartScheduler: + jal vPortSetup + csrc CSR_MSTATUS, MSTATUS_MIE + +#if USE_MSP + la t0, _sp + csrw CSR_MSCRATCH, t0 +#endif + + LOAD sp, pxCurrentTCB + LOAD sp, 0x0(sp) + + portRESTORE_CONTEXT_EXCP sp + + popREGFILE sp + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brife MSIP模式请求切换任务函数 + */ +vPortEndScheduler: + j vPortEndScheduler diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h new file mode 100644 index 00000000..50383ac5 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h @@ -0,0 +1,142 @@ +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "riscv_encoding.h" + + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +extern void vPortYield(unsigned long,unsigned long); +extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long); +extern int xPortSetInterruptMask(void); +extern void vPortClearInterruptMask( int uxSavedStatusValue ); + + +/*-----------------------------------------------------------*/ +/*System Calls */ +/*-----------------------------------------------------------*/ +//ecall macro used to store argument in a3 +#define ECALL(arg) ({ \ + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \ + asm volatile ("ecall" \ + : "+r" (a2) \ + : \ + : "memory"); \ + a2; \ +}) + + +extern void vPortSetMSIPInt(void); +#define port_MSIPSET_BIT vPortSetMSIPInt() + +#define IRQ_DISABLE 20 +#define IRQ_ENABLE 30 +#define PORT_YIELD 40 +#define PORT_YIELD_TO_RA 50 +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +/* the return after the ECALL is VERY important */ + +//#define portYIELD() ECALL(PORT_YIELD); +#define portYIELD() port_MSIPSET_BIT; + +#if CONFIG_SYSTEMVIEW_EN +#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } } +#else +#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD() +#endif +#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern void eclic_set_mth (uint8_t mth); +#define portDISABLE_INTERRUPTS() \ +{ \ + eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \ + __asm volatile("fence"); \ + __asm volatile("fence.i"); \ +} +#define portENABLE_INTERRUPTS() eclic_set_mth(0) +#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/*-----------------------------------------------------------*/ + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif +/*-----------------------------------------------------------*/ + + +#define portINLINE __inline + +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__(( always_inline)) +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/workspace/TS100/Core/BSP/Pine64/NOTES.md b/workspace/TS100/Core/BSP/Pine64/NOTES.md new file mode 100644 index 00000000..7a697725 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/NOTES.md @@ -0,0 +1,38 @@ +# Notes on RISC-V + +## Pinmap + +| Pin Number | Name | Function | Notes | +| ---------- | ---- | ---------------- | ----------- | +| 17 | PB2 | BOOT2 | Pulldown | +| 32 | | IMU INT 1 | N/A | +| 30 | | IMU INT 2 | N/A | +| 14 | PA7 | Handle Temp | ADC Input 7 | +| 15 | PB0 | Tip Temp | ADC Input 8 | +| 13 | PA6 | B Button | Active Low | +| 21 | PA9 | A Button | Active Low | +| 23 | PA11 | USB D- | - | +| 24 | PA12 | USB D+ | - | +| 31 | PB4 | Tip PWM Out | TIMER2_CH0 | +| 16 | PB1 | Input DC V Sense | ADC Input 9 | +| 20 | PA8 | OLED Reset | | +| 34 | PB7 | SDA | I2C0_SDA | +| 33 | PB6 | SCL | I2C0_SCL | + +## ADC Configuration + +For now running in matching mode for TS100 + +- X channels DMA in background +- Sample tip using "Intereted" channels using TIMER 0,1,3 TRGO or timer0,1,2 channels +- Using just 12 bit mode for now and move to hardware oversampling later +- use DMA for normal samples and 4x16 bit regs for tip temp +- It has dual ADC's so run them in pair mode + +## Timers + +### Timer 2 + +Timer 2 CH0 is tip drive PWM out. +This is fixed at 50% duty cycle and used via the cap to turn on the heater tip. +This should toggle relatively quickly. diff --git a/workspace/TS100/Core/BSP/Pine64/Pins.h b/workspace/TS100/Core/BSP/Pine64/Pins.h new file mode 100644 index 00000000..9ab0ecd2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Pins.h @@ -0,0 +1,38 @@ +/* + * Pins.h + * + * Created on: 29 May 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_PINS_H_ +#define BSP_MINIWARE_PINS_H_ +#include "Vendor/Lib/gd32vf103_gpio.h" +//TODO +#define KEY_B_Pin BIT(6) +#define KEY_B_GPIO_Port GPIOA +#define TMP36_INPUT_Pin BIT(7) +#define TMP36_INPUT_GPIO_Port GPIOA +#define TMP36_ADC1_CHANNEL ADC_CHANNEL_7 +#define TMP36_ADC2_CHANNEL ADC_CHANNEL_7 +#define TIP_TEMP_Pin BIT(0) +#define TIP_TEMP_GPIO_Port GPIOB +#define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_8 +#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_8 + +#define VIN_Pin BIT(1) +#define VIN_GPIO_Port GPIOB +#define VIN_ADC1_CHANNEL ADC_CHANNEL_9 +#define VIN_ADC2_CHANNEL ADC_CHANNEL_9 +#define OLED_RESET_Pin BIT(8) +#define OLED_RESET_GPIO_Port GPIOA +#define KEY_A_Pin BIT(9) +#define KEY_A_GPIO_Port GPIOA +#define PWM_Out_Pin BIT(4) +#define PWM_Out_GPIO_Port GPIOB +#define SCL_Pin BIT(6) +#define SCL_GPIO_Port GPIOB +#define SDA_Pin BIT(7) +#define SDA_GPIO_Port GPIOB + +#endif /* BSP_MINIWARE_PINS_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/Power.cpp b/workspace/TS100/Core/BSP/Pine64/Power.cpp new file mode 100644 index 00000000..522802a3 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Power.cpp @@ -0,0 +1,11 @@ +#include "BSP.h" +#include "BSP_Power.h" +#include "QC3.h" +#include "Settings.h" +void power_probe() { + //TODO -- Check for PD +} + +void power_check() { + //TODO -- Checks for PD? +} \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp new file mode 100644 index 00000000..dfb78715 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp @@ -0,0 +1,33 @@ +/* + * QC.c + * + * Created on: 29 May 2020 + * Author: Ralim + */ +#include "BSP.h" +#include "Pins.h" +#include "QC3.h" +#include "Settings.h" +#include "gd32vf103.h" +void QC_DPlusZero_Six() { +} +void QC_DNegZero_Six() { +} +void QC_DPlusThree_Three() { +} +void QC_DNegThree_Three() { +} +void QC_DM_PullDown() { +} +void QC_DM_No_PullDown() { +} +void QC_Init_GPIO() { +} +void QC_Post_Probe_En() { +} + +uint8_t QC_DM_PulledDown() { return 0; } + +void QC_resync() { + //Any ongoing adjustments +} \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/README.md b/workspace/TS100/Core/BSP/Pine64/README.md new file mode 100644 index 00000000..bb9de245 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/README.md @@ -0,0 +1,12 @@ +# BSP section for STM32F103 based Miniware products + +This folder contains the hardware abstractions required for the TS100, TS80 and probably TS80P soldering irons. + +## Main abstractions + +* Hardware Init +* -> Should contain all bootstrap to bring the hardware up to an operating point +* -> Two functions are required, a pre and post FreeRToS call +* I2C read/write +* Set PWM for the tip +* Links between IRQ's on the system and the calls in the rest of the firmware diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c new file mode 100644 index 00000000..9c9aa327 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -0,0 +1,294 @@ +/* + * Setup.c + * + * Created on: 29Aug.,2017 + * Author: Ben V. Brown + */ +#include "Setup.h" +#include "BSP.h" +#include "Pins.h" +#include "gd32vf103.h" +#include "systick.h" +uint16_t ADCReadings[64]; // room for 32 lots of the pair of readings + +// Functions +void setup_gpio(); +void setup_dma(); +void setup_i2c(); +void setup_adc(); +void setup_timers(); +void setup_iwdg(); + +void hardware_init() { + + //GPIO + setup_gpio(); + //DMA + setup_dma(); + //I2C + setup_i2c(); + //ADC's + setup_adc(); + //Timers + setup_timers(); + //Watchdog + // setup_iwdg(); + + /* enable TIMER1 - PWM control timing*/ + timer_enable(TIMER1); + timer_enable(TIMER2); + eclic_global_interrupt_enable(); +} +// channel 0 -> temperature sensor, 1-> VIN +uint16_t getADC(uint8_t channel) { + uint32_t sum = 0; + for (uint8_t i = 0; i < 32; i++) + sum += ADCReadings[channel + (i * 2)]; + return sum >> 2; +} + +void setup_gpio() { + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOA); + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOB); + //Alternate function clock enable + rcu_periph_clock_enable(RCU_AF); + //Buttons as input + gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, KEY_A_Pin); + gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, KEY_B_Pin); + //OLED reset as output + gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, + OLED_RESET_Pin); + //I2C as AF Open Drain + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ, SDA_Pin); + gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ, SCL_Pin); + //PWM output as AF Push Pull + gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, + PWM_Out_Pin); + //Analog Inputs ... as analog inputs + gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, + TMP36_INPUT_Pin); + gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, + TIP_TEMP_Pin); + gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, VIN_Pin); + //Timer 2 remap to move timer 2 ch0 to pin PB4 + gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE); + //Remap PB4 away from JTAG NJRST + gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); + //TODO - rest of pins as floating +} +void setup_dma() { + //Setup DMA for ADC0 + { + /* enable DMA0 clock */ + rcu_periph_clock_enable(RCU_DMA0); + /* ADC_DMA_channel configuration */ + dma_parameter_struct dma_data_parameter; + + /* ADC DMA_channel configuration */ + dma_deinit(DMA0, DMA_CH0); + + /* initialize DMA data mode */ + dma_data_parameter.periph_addr = (uint32_t) (&ADC_RDATA(ADC0)); + dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_data_parameter.memory_addr = (uint32_t) (&ADCReadings); + dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT; + dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; + dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_data_parameter.number = 64; + dma_data_parameter.priority = DMA_PRIORITY_HIGH; + dma_init(DMA0, DMA_CH0, &dma_data_parameter); + + dma_circulation_enable(DMA0, DMA_CH0); + + /* enable DMA channel */ + dma_channel_enable(DMA0, DMA_CH0); + } +} +void setup_i2c() { + //TODO - DMA + /* enable I2C0 clock */ + rcu_periph_clock_enable(RCU_I2C0); + //Setup I20 at 100kHz with DMA? + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); + i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); + i2c_enable(I2C0); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); +} +void setup_adc() { + + //Setup ADC in normal + injected mode + //Want it to sample handle temp and input voltage normally via dma + //Then injected trigger to sample tip temp + + /* enable ADC0 clock */ + rcu_periph_clock_enable(RCU_ADC0); + /* enable ADC1 clock */ + rcu_periph_clock_enable(RCU_ADC1); + /* config ADC clock */ + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8); + /* reset ADC */ + adc_deinit(ADC0); + adc_deinit(ADC1); + //Run in normal parallel + inserted parallel + adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); + adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE | ADC_SCAN_MODE, + ENABLE); + adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE | ADC_SCAN_MODE, + ENABLE); + //Align right + adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); + adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); + //Setup reading 2 channels on regular mode (Handle Temp + ) + adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2); + adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 2); + //Setup the two channels + adc_regular_channel_config(ADC0, 0, TMP36_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); //temp sensor + adc_regular_channel_config(ADC1, 0, TMP36_ADC2_CHANNEL, + ADC_SAMPLETIME_71POINT5); //temp sensor + adc_regular_channel_config(ADC0, 1, VIN_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); //DC Input voltage + adc_regular_channel_config(ADC1, 1, VIN_ADC2_CHANNEL, + ADC_SAMPLETIME_71POINT5); //DC Input voltage + //Setup that we want all 4 inserted readings to be the tip temp + adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); + adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); + for (int rank = 0; rank < 4; rank++) { + adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC1_CHANNEL, + ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC2_CHANNEL, + ADC_SAMPLETIME_1POINT5); + } + // Enable triggers for the ADC + adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); + adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); + //Setup timer 1 channel 0 to trigger injected measurements + adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); + adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); + + adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + + adc_tempsensor_vrefint_disable(); + adc_watchdog_disable(ADC0); + adc_watchdog_disable(ADC1); + adc_resolution_config(ADC0, ADC_RESOLUTION_12B); + adc_resolution_config(ADC1, ADC_RESOLUTION_12B); + /* clear the ADC flag */ + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); + adc_oversample_mode_disable(ADC0); + adc_oversample_mode_disable(ADC1); + adc_enable(ADC0); + adc_enable(ADC1); + delay_1ms(1); + adc_calibration_enable(ADC0); + delay_1ms(1); + adc_calibration_enable(ADC1); + delay_1ms(1); + //Enable DMA mode + adc_dma_mode_enable(ADC0); + //Enable interrupt on end of injected readings + adc_interrupt_enable(ADC0, ADC_INT_EOIC); + eclic_irq_enable(ADC0_1_IRQn, 2, 0); + adc_dma_mode_enable(ADC0); + adc_dma_mode_enable(ADC1); + adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); +} +void setup_timers() { + //Setup timer 1 to run the actual PWM level + /* enable timer1 clock */ + rcu_periph_clock_enable(RCU_TIMER1); + rcu_periph_clock_enable(RCU_TIMER2); + timer_oc_parameter_struct timer_ocintpara; + timer_parameter_struct timer_initpara; + { + //deinit to reset the timer + timer_deinit(TIMER1); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 24000; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 255 + 17; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER1, &timer_initpara); + + /* CH0 configured to implement the PWM irq's for the output control*/ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); + + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, 255 + 13); + timer_channel_output_mode_config(TIMER1, TIMER_CH_0, + TIMER_OC_MODE_PWM1); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + /* CH1 used for irq */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara); + + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0); + timer_channel_output_mode_config(TIMER1, TIMER_CH_1, + TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, + TIMER_OC_SHADOW_DISABLE); + //IRQ + timer_interrupt_enable(TIMER1, TIMER_INT_UP); + timer_interrupt_enable(TIMER1, TIMER_INT_CH1); + + } + + eclic_irq_enable(TIMER1_IRQn, 2, 5); + //Setup timer 2 to control the output signal + { + timer_deinit(TIMER2); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 200; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 100; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER2, &timer_initpara); + + /* CH0 configuration in PWM mode0 */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); +//todo + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); + timer_channel_output_mode_config(TIMER2, TIMER_CH_0, + TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + timer_auto_reload_shadow_enable(TIMER2); + timer_enable(TIMER2); + } +} +void setup_iwdg() { + //TODO +} diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.h b/workspace/TS100/Core/BSP/Pine64/Setup.h new file mode 100644 index 00000000..805a78de --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Setup.h @@ -0,0 +1,22 @@ +/* + * Setup.h + * + * Created on: 29Aug.,2017 + * Author: Ben V. Brown + */ + +#ifndef SETUP_H_ +#define SETUP_H_ +#include "Vendor/Lib/gd32vf103_libopt.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif +uint16_t getADC(uint8_t channel); +void hardware_init(); +#ifdef __cplusplus +} +#endif + +#endif /* SETUP_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/UnitSettings.h b/workspace/TS100/Core/BSP/Pine64/UnitSettings.h new file mode 100644 index 00000000..46f76091 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/UnitSettings.h @@ -0,0 +1,11 @@ +/* + * UnitSettings.h + * + * Created on: 29 May 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_UNITSETTINGS_H_ +#define BSP_MINIWARE_UNITSETTINGS_H_ + +#endif /* BSP_MINIWARE_UNITSETTINGS_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds new file mode 100644 index 00000000..83ce13a0 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds @@ -0,0 +1,176 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + /* Run in FLASH */ + flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k + ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K + + /* Run in RAM */ +/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k + ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K +*/ +} + + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash + + .ilalign : + { + . = ALIGN(4); + PROVIDE( _ilm_lma = . ); + } >flash AT>flash + + .ialign : + { + PROVIDE( _ilm = . ); + } >flash AT>flash + + .text : + { + *(.rodata .rodata.*) + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash + + . = ALIGN(4); + + PROVIDE (__etext = .); + PROVIDE (_etext = .);/*0x80022c8*/ + PROVIDE (etext = .);/*0x80022c8*/ + PROVIDE( _eilm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash + + . = ALIGN(4); + PROVIDE( _eilm = . ); + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash + + + .data : + { + *(.rdata) + + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); /*0X200052A0 0X200002A0*/ + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram + + . = ALIGN(8); + PROVIDE( _end = . ); /*0X2000,0340*/ + PROVIDE( end = . ); + PROVIDE( heap_start = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c new file mode 100644 index 00000000..f48da3d2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c @@ -0,0 +1,117 @@ +/*! + \file I2C0_IE.c + \brief I2C0 master transmitter interrupt program + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_i2c.h" + +#include "I2C_IE.h" + +uint32_t event1; + +/*! + \brief handle I2C0 event interrupt request + \param[in] none + \param[out] none + \retval none +*/ +void I2C0_EventIRQ_Handler(void) { + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + /* send slave address */ + i2c_master_addressing(I2C0, I2C1_SLAVE_ADDRESS7, I2C_TRANSMITTER); + } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + if (I2C_nBytes > 0) { + /* the master sends a data byte */ + i2c_data_transmit(I2C0, *i2c_txbuffer++); + I2C_nBytes--; + } else { + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + } + } +} + +/*! + \brief handle I2C0 error interrupt request + \param[in] none + \param[out] none + \retval none +*/ +void I2C0_ErrorIRQ_Handler(void) { + /* no acknowledge received */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + } + + /* SMBus alert */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + } + + /* bus timeout in SMBus mode */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + } + + /* over-run or under-run when SCL stretch is disabled */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + } + + /* arbitration lost */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + } + + /* bus error */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + } + + /* CRC value doesn't match */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + } + + /* disable the error interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c new file mode 100644 index 00000000..096d771b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c @@ -0,0 +1,112 @@ +/*! + \file I2C1_IE.c + \brief I2C1 slave receiver interrupt program + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_i2c.h" + +#include "I2C_IE.h" + +uint32_t event2; + +/*! + \brief handle I2C1 event interrupt request + \param[in] none + \param[out] none + \retval none +*/ +void I2C1_EventIRQ_Handler(void) { + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) { + /* clear the ADDSEND bit */ + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND); + } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) { + /* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */ + *i2c_rxbuffer++ = i2c_data_receive(I2C1); + } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) { + status = SUCCESS; + /* clear the STPDET bit */ + i2c_enable(I2C1); + /* disable I2C1 interrupt */ + i2c_interrupt_disable(I2C1, I2C_INT_ERR); + i2c_interrupt_disable(I2C1, I2C_INT_BUF); + i2c_interrupt_disable(I2C1, I2C_INT_EV); + } +} + +/*! + \brief handle I2C1 error interrupt request + \param[in] none + \param[out] none + \retval none +*/ +void I2C1_ErrorIRQ_Handler(void) { + /* no acknowledge received */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_AERR); + } + + /* SMBus alert */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT); + } + + /* bus timeout in SMBus mode */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBTO)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBTO); + } + + /* over-run or under-run when SCL stretch is disabled */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR); + } + + /* arbitration lost */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB); + } + + /* bus error */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR); + } + + /* CRC value doesn't match */ + if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) { + i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR); + } + + /* disable the error interrupt */ + i2c_interrupt_disable(I2C1, I2C_INT_ERR); + i2c_interrupt_disable(I2C1, I2C_INT_BUF); + i2c_interrupt_disable(I2C1, I2C_INT_EV); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h new file mode 100644 index 00000000..09eb5ea9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h @@ -0,0 +1,65 @@ +/*! + \file I2C1_IE.c + \brief The header file of I2C0 and I2C1 interrupt + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef I2C_IE_H +#define I2C_IE_H + +#include "gd32vf103.h" + +#define I2C0_SLAVE_ADDRESS7 0x82 +#define I2C1_SLAVE_ADDRESS7 0x72 + +extern volatile ErrStatus status; +extern volatile uint8_t *i2c_txbuffer; +extern volatile uint8_t *i2c_rxbuffer; +extern volatile uint16_t I2C_nBytes; + +/* function declarations */ +/* handle I2C0 event interrupt request */ +void I2C0_EventIRQ_Handler(void); +/* handle I2C0 error interrupt request */ +void I2C0_ErrorIRQ_Handler(void); +/* handle I2C1 event interrupt request */ +void I2C1_EventIRQ_Handler(void); +/* handle I2C1 error interrupt request */ +void I2C1_ErrorIRQ_Handler(void); + +#endif /* I2C_IE_H */ + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103.h new file mode 100644 index 00000000..7366fea7 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103.h @@ -0,0 +1,246 @@ +/*! + \file gd32vf103.h + \brief general definitions for GD32VF103 + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32VF103_H +#define GD32VF103_H + +#ifdef cplusplus +extern "C" { +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. + */ +#ifdef __cplusplus +#define __I volatile /*!< Defines 'read only' permissions */ +#else +#define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ +#define GD32VF103V_EVAL +/* define value of high speed crystal oscillator (HXTAL) in Hz */ +#if !defined HXTAL_VALUE +#ifdef GD32VF103R_START +#define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#define HXTAL_VALUE_8M HXTAL_VALUE +#elif defined(GD32VF103V_EVAL) || defined(GD32VF103C_START) || defined(GD32VF103T_START) +#define HXTAL_VALUE ((uint32_t)8000000) /*!< value of the external oscillator in Hz */ +#define HXTAL_VALUE_25M HXTAL_VALUE +#else +#error "Please select the target board type used in your application (in gd32vf103.h file)" +#endif +#endif /* high speed crystal oscillator value */ + +/* define startup timeout value of high speed crystal oscillator (HXTAL) */ +#if !defined(HXTAL_STARTUP_TIMEOUT) +#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) +#endif /* high speed crystal oscillator startup timeout */ + +/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ +#if !defined(IRC8M_VALUE) +#define IRC8M_VALUE ((uint32_t)8000000) +#endif /* internal 8MHz RC oscillator value */ + +/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ +#if !defined(IRC8M_STARTUP_TIMEOUT) +#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) +#endif /* internal 8MHz RC oscillator startup timeout */ + +/* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ +#if !defined(IRC40K_VALUE) +#define IRC40K_VALUE ((uint32_t)40000) +#endif /* internal 40KHz RC oscillator value */ + +/* define value of low speed crystal oscillator (LXTAL)in Hz */ +#if !defined(LXTAL_VALUE) +#define LXTAL_VALUE ((uint32_t)32768) +#endif /* low speed crystal oscillator value */ + +/* define interrupt number */ +typedef enum IRQn { + + CLIC_INT_RESERVED = 0, /*!< RISC-V reserved */ + CLIC_INT_SFT = 3, /*!< Software interrupt */ + CLIC_INT_TMR = 7, /*!< CPU Timer interrupt */ + CLIC_INT_BWEI = 17, /*!< Bus Error interrupt */ + CLIC_INT_PMOVI = 18, /*!< Performance Monitor */ + + /* interrupt numbers */ + WWDGT_IRQn = 19, /*!< window watchDog timer interrupt */ + LVD_IRQn = 20, /*!< LVD through EXTI line detect interrupt */ + TAMPER_IRQn = 21, /*!< tamper through EXTI line detect */ + RTC_IRQn = 22, /*!< RTC alarm interrupt */ + FMC_IRQn = 23, /*!< FMC interrupt */ + RCU_CTC_IRQn = 24, /*!< RCU and CTC interrupt */ + EXTI0_IRQn = 25, /*!< EXTI line 0 interrupts */ + EXTI1_IRQn = 26, /*!< EXTI line 1 interrupts */ + EXTI2_IRQn = 27, /*!< EXTI line 2 interrupts */ + EXTI3_IRQn = 28, /*!< EXTI line 3 interrupts */ + EXTI4_IRQn = 29, /*!< EXTI line 4 interrupts */ + DMA0_Channel0_IRQn = 30, /*!< DMA0 channel0 interrupt */ + DMA0_Channel1_IRQn = 31, /*!< DMA0 channel1 interrupt */ + DMA0_Channel2_IRQn = 32, /*!< DMA0 channel2 interrupt */ + DMA0_Channel3_IRQn = 33, /*!< DMA0 channel3 interrupt */ + DMA0_Channel4_IRQn = 34, /*!< DMA0 channel4 interrupt */ + DMA0_Channel5_IRQn = 35, /*!< DMA0 channel5 interrupt */ + DMA0_Channel6_IRQn = 36, /*!< DMA0 channel6 interrupt */ + ADC0_1_IRQn = 37, /*!< ADC0 and ADC1 interrupt */ + CAN0_TX_IRQn = 38, /*!< CAN0 TX interrupts */ + CAN0_RX0_IRQn = 39, /*!< CAN0 RX0 interrupts */ + CAN0_RX1_IRQn = 40, /*!< CAN0 RX1 interrupts */ + CAN0_EWMC_IRQn = 41, /*!< CAN0 EWMC interrupts */ + EXTI5_9_IRQn = 42, /*!< EXTI[9:5] interrupts */ + TIMER0_BRK_IRQn = 43, /*!< TIMER0 break interrupts */ + TIMER0_UP_IRQn = 44, /*!< TIMER0 update interrupts */ + TIMER0_TRG_CMT_IRQn = 45, /*!< TIMER0 trigger and commutation interrupts */ + TIMER0_Channel_IRQn = 46, /*!< TIMER0 channel capture compare interrupts */ + TIMER1_IRQn = 47, /*!< TIMER1 interrupt */ + TIMER2_IRQn = 48, /*!< TIMER2 interrupt */ + TIMER3_IRQn = 49, /*!< TIMER3 interrupts */ + I2C0_EV_IRQn = 50, /*!< I2C0 event interrupt */ + I2C0_ER_IRQn = 51, /*!< I2C0 error interrupt */ + I2C1_EV_IRQn = 52, /*!< I2C1 event interrupt */ + I2C1_ER_IRQn = 53, /*!< I2C1 error interrupt */ + SPI0_IRQn = 54, /*!< SPI0 interrupt */ + SPI1_IRQn = 55, /*!< SPI1 interrupt */ + USART0_IRQn = 56, /*!< USART0 interrupt */ + USART1_IRQn = 57, /*!< USART1 interrupt */ + USART2_IRQn = 58, /*!< USART2 interrupt */ + EXTI10_15_IRQn = 59, /*!< EXTI[15:10] interrupts */ + RTC_ALARM_IRQn = 60, /*!< RTC alarm interrupt EXTI */ + USBFS_WKUP_IRQn = 61, /*!< USBFS wakeup interrupt */ + + EXMC_IRQn = 67, /*!< EXMC global interrupt */ + + TIMER4_IRQn = 69, /*!< TIMER4 global interrupt */ + SPI2_IRQn = 70, /*!< SPI2 global interrupt */ + UART3_IRQn = 71, /*!< UART3 global interrupt */ + UART4_IRQn = 72, /*!< UART4 global interrupt */ + TIMER5_IRQn = 73, /*!< TIMER5 global interrupt */ + TIMER6_IRQn = 74, /*!< TIMER6 global interrupt */ + DMA1_Channel0_IRQn = 75, /*!< DMA1 channel0 global interrupt */ + DMA1_Channel1_IRQn = 76, /*!< DMA1 channel1 global interrupt */ + DMA1_Channel2_IRQn = 77, /*!< DMA1 channel2 global interrupt */ + DMA1_Channel3_IRQn = 78, /*!< DMA1 channel3 global interrupt */ + DMA1_Channel4_IRQn = 79, /*!< DMA1 channel3 global interrupt */ + + CAN1_TX_IRQn = 82, /*!< CAN1 TX interrupt */ + CAN1_RX0_IRQn = 83, /*!< CAN1 RX0 interrupt */ + CAN1_RX1_IRQn = 84, /*!< CAN1 RX1 interrupt */ + CAN1_EWMC_IRQn = 85, /*!< CAN1 EWMC interrupt */ + USBFS_IRQn = 86, /*!< USBFS global interrupt */ + + ECLIC_NUM_INTERRUPTS +} IRQn_Type; + +/* includes */ +#include "system_gd32vf103.h" +#include + +/* enum definitions */ +typedef enum { DISABLE = 0, + ENABLE = !DISABLE } EventStatus, + ControlStatus; +// typedef enum { FALSE = 0, +// TRUE = !FALSE } bool; +typedef enum { RESET = 0, + SET = 1, + MAX = 0X7FFFFFFF } FlagStatus; +typedef enum { ERROR = 0, + SUCCESS = !ERROR } ErrStatus; + +/* bit operations */ +#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) +#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) +#define BIT(x) ((uint32_t)((uint32_t)0x01U << (x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define GET_BITS(regval, start, end) (((regval)&BITS((start), (end))) >> (start)) + +/* main flash and SRAM memory map */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< main FLASH base address */ +#define SRAM_BASE ((uint32_t)0x20000000U) /*!< SRAM0 base address */ +#define OB_BASE ((uint32_t)0x1FFFF800U) /*!< OB base address */ +#define DBG_BASE ((uint32_t)0xE0042000U) /*!< DBG base address */ +#define EXMC_BASE ((uint32_t)0xA0000000U) /*!< EXMC register base address */ + +/* peripheral memory map */ +#define APB1_BUS_BASE ((uint32_t)0x40000000U) /*!< apb1 base address */ +#define APB2_BUS_BASE ((uint32_t)0x40010000U) /*!< apb2 base address */ +#define AHB1_BUS_BASE ((uint32_t)0x40018000U) /*!< ahb1 base address */ +#define AHB3_BUS_BASE ((uint32_t)0x60000000U) /*!< ahb3 base address */ + +/* advanced peripheral bus 1 memory map */ +#define TIMER_BASE (APB1_BUS_BASE + 0x00000000U) /*!< TIMER base address */ +#define RTC_BASE (APB1_BUS_BASE + 0x00002800U) /*!< RTC base address */ +#define WWDGT_BASE (APB1_BUS_BASE + 0x00002C00U) /*!< WWDGT base address */ +#define FWDGT_BASE (APB1_BUS_BASE + 0x00003000U) /*!< FWDGT base address */ +#define SPI_BASE (APB1_BUS_BASE + 0x00003800U) /*!< SPI base address */ +#define USART_BASE (APB1_BUS_BASE + 0x00004400U) /*!< USART base address */ +#define I2C_BASE (APB1_BUS_BASE + 0x00005400U) /*!< I2C base address */ +#define CAN_BASE (APB1_BUS_BASE + 0x00006400U) /*!< CAN base address */ +#define BKP_BASE (APB1_BUS_BASE + 0x00006C00U) /*!< BKP base address */ +#define PMU_BASE (APB1_BUS_BASE + 0x00007000U) /*!< PMU base address */ +#define DAC_BASE (APB1_BUS_BASE + 0x00007400U) /*!< DAC base address */ + +/* advanced peripheral bus 2 memory map */ +#define AFIO_BASE (APB2_BUS_BASE + 0x00000000U) /*!< AFIO base address */ +#define EXTI_BASE (APB2_BUS_BASE + 0x00000400U) /*!< EXTI base address */ +#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */ +#define ADC_BASE (APB2_BUS_BASE + 0x00002400U) /*!< ADC base address */ + +/* advanced high performance bus 1 memory map */ +#define DMA_BASE (AHB1_BUS_BASE + 0x00008000U) /*!< DMA base address */ +#define RCU_BASE (AHB1_BUS_BASE + 0x00009000U) /*!< RCU base address */ +#define FMC_BASE (AHB1_BUS_BASE + 0x0000A000U) /*!< FMC base address */ +#define CRC_BASE (AHB1_BUS_BASE + 0x0000B000U) /*!< CRC base address */ +#define USBFS_BASE (AHB1_BUS_BASE + 0x0FFE8000U) /*!< USBFS base address */ + +/* define marco USE_STDPERIPH_DRIVER */ +#if !defined USE_STDPERIPH_DRIVER +#define USE_STDPERIPH_DRIVER +#endif +#ifdef USE_STDPERIPH_DRIVER +#include "gd32vf103_libopt.h" +#endif /* USE_STDPERIPH_DRIVER */ + +#ifdef cplusplus +} +#endif +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c new file mode 100644 index 00000000..7b0e743f --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c @@ -0,0 +1,992 @@ +/*! + \file gd32vf103_adc.c + \brief ADC driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_adc.h" + +/* discontinuous mode macro*/ +#define ADC_CHANNEL_LENGTH_SUBTRACT_ONE ((uint8_t)1U) + +/* ADC regular channel macro */ +#define ADC_REGULAR_CHANNEL_RANK_SIX ((uint8_t)6U) +#define ADC_REGULAR_CHANNEL_RANK_TWELVE ((uint8_t)12U) +#define ADC_REGULAR_CHANNEL_RANK_SIXTEEN ((uint8_t)16U) +#define ADC_REGULAR_CHANNEL_RANK_LENGTH ((uint8_t)5U) + +/* ADC sampling time macro */ +#define ADC_CHANNEL_SAMPLE_TEN ((uint8_t)10U) +#define ADC_CHANNEL_SAMPLE_EIGHTEEN ((uint8_t)18U) +#define ADC_CHANNEL_SAMPLE_LENGTH ((uint8_t)3U) + +/* ADC inserted channel macro */ +#define ADC_INSERTED_CHANNEL_RANK_LENGTH ((uint8_t)5U) +#define ADC_INSERTED_CHANNEL_SHIFT_LENGTH ((uint8_t)15U) + +/* ADC inserted channel offset macro */ +#define ADC_OFFSET_LENGTH ((uint8_t)3U) +#define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) + +/*! + \brief reset ADC + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_deinit(uint32_t adc_periph) +{ + switch(adc_periph){ + case ADC0: + /* reset ADC0 */ + rcu_periph_reset_enable(RCU_ADC0RST); + rcu_periph_reset_disable(RCU_ADC0RST); + break; + case ADC1: + /* reset ADC1 */ + rcu_periph_reset_enable(RCU_ADC1RST); + rcu_periph_reset_disable(RCU_ADC1RST); + break; + default: + break; + } +} + +/*! + \brief configure the ADC sync mode + \param[in] mode: ADC mode + only one parameter can be selected which is shown as below: + \arg ADC_MODE_FREE: all the ADCs work independently + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL: ADC0 and ADC1 work in combined regular parallel + inserted parallel mode + \arg ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION: ADC0 and ADC1 work in combined regular parallel + trigger rotation mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode + \arg ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode + \arg ADC_DAUL_INSERTED_PARALLEL: ADC0 and ADC1 work in inserted parallel mode only + \arg ADC_DAUL_REGULAL_PARALLEL: ADC0 and ADC1 work in regular parallel mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_FAST: ADC0 and ADC1 work in follow-up fast mode only + \arg ADC_DAUL_REGULAL_FOLLOWUP_SLOW: ADC0 and ADC1 work in follow-up slow mode only + \arg ADC_DAUL_INSERTED_TRIGGER_ROTATION: ADC0 and ADC1 work in trigger rotation mode only + \param[out] none + \retval none +*/ +void adc_mode_config(uint32_t mode) +{ + ADC_CTL0(ADC0) &= ~(ADC_CTL0_SYNCM); + ADC_CTL0(ADC0) |= mode; +} + +/*! + \brief enable or disable ADC special function + \param[in] adc_periph: ADCx, x=0,1 + \param[in] function: the function to config + only one parameter can be selected which is shown as below: + \arg ADC_SCAN_MODE: scan mode select + \arg ADC_INSERTED_CHANNEL_AUTO: inserted channel group convert automatically + \arg ADC_CONTINUOUS_MODE: continuous mode select + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (function & ADC_SCAN_MODE)){ + /* enable scan mode */ + ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* enable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* enable continuous mode */ + ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; + } + }else{ + if(0U != (function & ADC_SCAN_MODE)){ + /* disable scan mode */ + ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; + } + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + /* disable inserted channel group convert automatically */ + ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; + } + if(0U != (function & ADC_CONTINUOUS_MODE)){ + /* disable continuous mode */ + ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; + } + } +} + +/*! + \brief configure ADC data alignment + \param[in] adc_periph: ADCx, x=0,1 + \param[in] data_alignment: data alignment select + only one parameter can be selected which is shown as below: + \arg ADC_DATAALIGN_RIGHT: LSB alignment + \arg ADC_DATAALIGN_LEFT: MSB alignment + \param[out] none + \retval none +*/ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) +{ + if(ADC_DATAALIGN_RIGHT != data_alignment){ + /* MSB alignment */ + ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; + }else{ + /* LSB alignment */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); + } +} + +/*! + \brief enable ADC interface + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_enable(uint32_t adc_periph) +{ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + /* enable ADC */ + ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; + } +} + +/*! + \brief disable ADC interface + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_disable(uint32_t adc_periph) +{ + /* disable ADC */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ADCON); +} + +/*! + \brief ADC calibration and reset calibration + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_calibration_enable(uint32_t adc_periph) +{ + /* reset the selected ADC1 calibration registers */ + ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; + /* check the RSTCLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + } + /* enable ADC calibration process */ + ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; + /* check the CLB bit state */ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + } +} + +/*! + \brief enable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_enable(void) +{ + /* enable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) |= ADC_CTL1_TSVREN; +} + +/*! + \brief disable the temperature sensor and Vrefint channel + \param[in] none + \param[out] none + \retval none +*/ +void adc_tempsensor_vrefint_disable(void) +{ + /* disable the temperature sensor and Vrefint channel */ + ADC_CTL1(ADC0) &= ~ADC_CTL1_TSVREN; +} + +/*! + \brief enable DMA request + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_dma_mode_enable(uint32_t adc_periph) +{ + /* enable DMA request */ + ADC_CTL1(adc_periph) |= (uint32_t)(ADC_CTL1_DMA); +} + +/*! + \brief disable DMA request + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_dma_mode_disable(uint32_t adc_periph) +{ + /* disable DMA request */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DMA); +} + +/*! + \brief configure ADC discontinuous mode + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_CHANNEL_DISCON_DISABLE: disable discontinuous mode of regular & inserted channel + \param[in] length: number of conversions in discontinuous mode,the number can be 1..8 + for regular channel, the number has no effect for inserted channel + \param[out] none + \retval none +*/ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length) +{ + /* disable discontinuous mode of regular & inserted channel */ + ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* config the number of conversions in discontinuous mode */ + ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); + ADC_CTL0(adc_periph) |= CTL0_DISNUM(((uint32_t)length - ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + /* enable regular channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISRC; + break; + case ADC_INSERTED_CHANNEL: + /* enable inserted channel group discontinuous mode */ + ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; + break; + case ADC_CHANNEL_DISCON_DISABLE: + /* disable discontinuous mode of regular & inserted channel */ + default: + break; + } +} + +/*! + \brief configure the length of regular channel group or inserted channel group + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] length: the length of the channel + regular channel 1-16 + inserted channel 1-4 + \param[out] none + \retval none +*/ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure the length of regular channel group */ + ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); + ADC_RSQ0(adc_periph) |= RSQ0_RL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + case ADC_INSERTED_CHANNEL: + /* configure the length of inserted channel group */ + ADC_ISQ(adc_periph) &= ~((uint32_t)ADC_ISQ_IL); + ADC_ISQ(adc_periph) |= ISQ_IL((uint32_t)(length-ADC_CHANNEL_LENGTH_SUBTRACT_ONE)); + break; + default: + break; + } +} + +/*! + \brief configure ADC regular channel + \param[in] adc_periph: ADCx, x=0,1 + \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: the sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint32_t rsq,sampt; + + /* ADC regular sequence config */ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + /* the regular group sequence rank is smaller than six */ + rsq = ADC_RSQ2(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*rank)); + ADC_RSQ2(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + /* the regular group sequence rank is smaller than twelve */ + rsq = ADC_RSQ1(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_SIX))); + ADC_RSQ1(adc_periph) = rsq; + }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + /* the regular group sequence rank is smaller than sixteen */ + rsq = ADC_RSQ0(adc_periph); + rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE)))); + /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ + rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH*(rank-ADC_REGULAR_CHANNEL_RANK_TWELVE))); + ADC_RSQ0(adc_periph) = rsq; + }else{ + } + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the regular group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel)); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the regular group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel + \param[in] adc_periph: ADCx, x=0,1 + \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \param[in] sample_time: The sample time value + only one parameter can be selected which is shown as below: + \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles + \arg ADC_SAMPLETIME_7POINT5: 7.5 cycles + \arg ADC_SAMPLETIME_13POINT5: 13.5 cycles + \arg ADC_SAMPLETIME_28POINT5: 28.5 cycles + \arg ADC_SAMPLETIME_41POINT5: 41.5 cycles + \arg ADC_SAMPLETIME_55POINT5: 55.5 cycles + \arg ADC_SAMPLETIME_71POINT5: 71.5 cycles + \arg ADC_SAMPLETIME_239POINT5: 239.5 cycles + \param[out] none + \retval none +*/ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) +{ + uint8_t inserted_length; + uint32_t isq,sampt; + /* get inserted channel group length */ + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ + isq = ADC_ISQ(adc_periph); + isq &= ~((uint32_t)(ADC_ISQ_ISQN << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH))); + isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH-(inserted_length-rank)*ADC_INSERTED_CHANNEL_RANK_LENGTH)); + ADC_ISQ(adc_periph) = isq; + + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* the inserted group sequence rank is smaller than ten */ + sampt = ADC_SAMPT1(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel))); + /* channel sample time set*/ + sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*adc_channel); + ADC_SAMPT1(adc_periph) = sampt; + }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + /* the inserted group sequence rank is smaller than eighteen */ + sampt = ADC_SAMPT0(adc_periph); + sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN)))); + /* channel sample time set*/ + sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH*(adc_channel-ADC_CHANNEL_SAMPLE_TEN))); + ADC_SAMPT0(adc_periph) = sampt; + }else{ + } +} + +/*! + \brief configure ADC inserted channel offset + \param[in] adc_periph: ADCx, x=0,1 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted channel3 + \param[in] offset: the offset data + \param[out] none + \retval none +*/ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset) +{ + uint8_t inserted_length; + uint32_t num = 0U; + + inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph) , 20U , 21U); + num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); + + if(num <= ADC_OFFSET_LENGTH){ + /* calculate the offset of the register */ + num = num * ADC_OFFSET_SHIFT_LENGTH; + /* config the offset of the selected channels */ + REG32((adc_periph) + 0x14U + num) = IOFFX_IOFF((uint32_t)offset); + } +} + +/*! + \brief configure ADC external trigger source + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: select the channel group + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] external_trigger_source: regular or inserted group trigger source + only one parameter can be selected + for regular channel: + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH0: TIMER0 CH0 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH1: TIMER0 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select + \arg ADC0_1_EXTTRIG_REGULAR_T1_CH1: TIMER1 CH1 event select + \arg ADC0_1_EXTTRIG_REGULAR_T2_TRGO: TIMER2 TRGO event select + \arg ADC0_1_EXTTRIG_REGULAR_T3_CH3: TIMER3 CH3 event select + \arg ADC0_1_EXTTRIG_REGULAR_EXTI_11: external interrupt line 11 + \arg ADC0_1_EXTTRIG_REGULAR_NONE: software trigger + for inserted channel: + \arg ADC0_1_EXTTRIG_INSERTED_T0_TRGO: TIMER0 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T0_CH3: TIMER0 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_TRGO: TIMER1 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_T1_CH0: TIMER1 CH0 event select + \arg ADC0_1_EXTTRIG_INSERTED_T2_CH3: TIMER2 CH3 event select + \arg ADC0_1_EXTTRIG_INSERTED_T3_TRGO: TIMER3 TRGO event select + \arg ADC0_1_EXTTRIG_INSERTED_EXTI_15: external interrupt line 15 + \arg ADC0_1_EXTTRIG_INSERTED_NONE: software trigger + \param[out] none + \retval none +*/ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) +{ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* configure ADC regular group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + case ADC_INSERTED_CHANNEL: + /* configure ADC inserted group external trigger source */ + ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSIC); + ADC_CTL1(adc_periph) |= (uint32_t)external_trigger_source; + break; + default: + break; + } +} + +/*! + \brief configure ADC external trigger + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) +{ + if(newvalue){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group external trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; + } + }else{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* disable ADC regular channel group external trigger */ + ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; + } + } +} + +/*! + \brief enable ADC software trigger + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: select the channel group + one or more parameters can be selected which are shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \param[out] none + \retval none +*/ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + /* enable ADC regular channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; + } + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + /* enable ADC inserted channel group software trigger */ + ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; + } +} + +/*! + \brief read ADC regular group data register + \param[in] adc_periph: ADCx, x=0,1 + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint16_t adc_regular_data_read(uint32_t adc_periph) +{ + return (uint16_t)(ADC_RDATA(adc_periph)); +} + +/*! + \brief read ADC inserted group data register + \param[in] adc_periph: ADCx, x=0,1 + \param[in] inserted_channel: insert channel select + only one parameter can be selected + \arg ADC_INSERTED_CHANNEL_0: inserted Channel0 + \arg ADC_INSERTED_CHANNEL_1: inserted channel1 + \arg ADC_INSERTED_CHANNEL_2: inserted Channel2 + \arg ADC_INSERTED_CHANNEL_3: inserted Channel3 + \param[out] none + \retval the conversion value +*/ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) +{ + uint32_t idata; + /* read the data of the selected channel */ + switch(inserted_channel){ + case ADC_INSERTED_CHANNEL_0: + /* read the data of channel 0 */ + idata = ADC_IDATA0(adc_periph); + break; + case ADC_INSERTED_CHANNEL_1: + /* read the data of channel 1 */ + idata = ADC_IDATA1(adc_periph); + break; + case ADC_INSERTED_CHANNEL_2: + /* read the data of channel 2 */ + idata = ADC_IDATA2(adc_periph); + break; + case ADC_INSERTED_CHANNEL_3: + /* read the data of channel 3 */ + idata = ADC_IDATA3(adc_periph); + break; + default: + idata = 0U; + break; + } + return (uint16_t)idata; +} + +/*! + \brief read the last ADC0 and ADC1 conversion result data in sync mode + \param[in] none + \param[out] none + \retval the conversion value +*/ +uint32_t adc_sync_mode_convert_value_read(void) +{ + /* return conversion value */ + return ADC_RDATA(ADC0); +} + + +/*! + \brief configure ADC analog watchdog single channel + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel: the selected ADC channel + only one parameter can be selected which is shown as below: + \arg ADC_CHANNEL_x: ADC Channelx(x=0..17)(x=16 and x=17 are only for ADC0) + \param[out] none + \retval none +*/ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); + /* analog watchdog channel select */ + ADC_CTL0(adc_periph) |= (uint32_t)adc_channel; + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); +} + +/*! + \brief configure ADC analog watchdog group channel + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_channel_group: the channel group use analog watchdog + only one parameter can be selected which is shown as below: + \arg ADC_REGULAR_CHANNEL: regular channel group + \arg ADC_INSERTED_CHANNEL: inserted channel group + \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group + \param[out] none + \retval none +*/ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); + /* select the group */ + switch(adc_channel_group){ + case ADC_REGULAR_CHANNEL: + /* regular channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; + break; + case ADC_INSERTED_CHANNEL: + /* inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_IWDEN; + break; + case ADC_REGULAR_INSERTED_CHANNEL: + /* regular and inserted channel analog watchdog enable */ + ADC_CTL0(adc_periph) |= (uint32_t)(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN); + break; + default: + break; + } +} + +/*! + \brief disable ADC analog watchdog + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_watchdog_disable(uint32_t adc_periph) +{ + ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC | ADC_CTL0_WDCHSEL); +} + +/*! + \brief configure ADC analog watchdog threshold + \param[in] adc_periph: ADCx, x=0,1 + \param[in] low_threshold: analog watchdog low threshold, 0..4095 + \param[in] high_threshold: analog watchdog high threshold, 0..4095 + \param[out] none + \retval none +*/ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold) +{ + ADC_WDLT(adc_periph) = (uint32_t)WDLT_WDLT(low_threshold); + ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); +} + +/*! + \brief get the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_flag: the adc flag bits + only one parameter can be selected which is shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) +{ + FlagStatus reval = RESET; + if(ADC_STAT(adc_periph) & adc_flag){ + reval = SET; + } + return reval; +} + +/*! + \brief clear the ADC flag bits + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_flag: the adc flag bits + one or more parameters can be selected which are shown as below: + \arg ADC_FLAG_WDE: analog watchdog event flag + \arg ADC_FLAG_EOC: end of group conversion flag + \arg ADC_FLAG_EOIC: end of inserted group conversion flag + \arg ADC_FLAG_STIC: start flag of inserted channel group + \arg ADC_FLAG_STRC: start flag of regular channel group + \param[out] none + \retval none +*/ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_flag); +} + +/*! + \brief get the bit state of ADCx software start conversion + \param[in] adc_periph: ADCx, x=0,1 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWRCST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the bit state of ADCx software inserted channel start conversion + \param[in] adc_periph: ADCx, x=0,1 + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph) +{ + FlagStatus reval = RESET; + if((uint32_t)RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_SWICST)){ + reval = SET; + } + return reval; +} + +/*! + \brief get the ADC interrupt bits + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) +{ + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt){ + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ + interrupt_flag = SET; + } + break; + default: + break; + } + return interrupt_flag; +} + +/*! + \brief clear the ADC flag + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt + \param[out] none + \retval none +*/ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) +{ + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); +} + +/*! + \brief enable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_interrupt: the adc interrupt + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* enable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; + } + /* enable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; + } + /* enable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief disable ADC interrupt + \param[in] adc_periph: ADCx, x=0,1 + \param[in] adc_interrupt: the adc interrupt flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_WDE: analog watchdog interrupt flag + \arg ADC_INT_EOC: end of group conversion interrupt flag + \arg ADC_INT_EOIC: end of inserted group conversion interrupt flag + \param[out] none + \retval none +*/ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) +{ + /* disable ADC analog watchdog interrupt */ + if(0U != (adc_interrupt & ADC_INT_WDE)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; + } + /* disable ADC end of group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; + } + /* disable ADC end of inserted group conversion interrupt */ + if(0U != (adc_interrupt & ADC_INT_EOIC)){ + ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; + } +} + +/*! + \brief adc resolution config + \param[in] adc_periph: ADCx, x=0,1 + \param[in] resolution: ADC resolution + only one parameter can be selected which is shown as below: + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) +{ + ADC_OVSCR(adc_periph) &= ~((uint32_t)ADC_OVSCR_DRES); + ADC_OVSCR(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief adc oversample mode config + \param[in] adc_periph: ADCx, x=0,1 + \param[in] mode: ADC oversampling mode + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel + are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel + needs a trigger + \param[in] shift: ADC oversampling shift + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only one parameter can be selected which is shown as below: + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio X2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio X4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio X8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio X16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio X32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio X64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio X128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio X256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift,uint8_t ratio) +{ + if(mode){ + ADC_OVSCR(adc_periph) |= (uint32_t)ADC_OVSCR_TOVS; + }else{ + ADC_OVSCR(adc_periph) &= ~((uint32_t)ADC_OVSCR_TOVS); + } + /* config the shift and ratio */ + ADC_OVSCR(adc_periph) &= ~((uint32_t)(ADC_OVSCR_OVSR | ADC_OVSCR_OVSS)); + ADC_OVSCR(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSCR(adc_periph) |= ADC_OVSCR_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx, x=0,1 + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSCR(adc_periph) &= ~((uint32_t)ADC_OVSCR_OVSEN); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.h new file mode 100644 index 00000000..c47699c9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.h @@ -0,0 +1,401 @@ +/*! + \file gd32vf103_adc.h + \brief definitions for the ADC + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_ADC_H +#define GD32VF103_ADC_H + +#include "gd32vf103.h" + +/* ADC definitions */ +#define ADC0 ADC_BASE +#define ADC1 (ADC_BASE + 0x400U) + +/* registers definitions */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ +#define ADC_OVSCR(adcx) REG32((adcx) + 0x80U) /*!< ADC oversample control register */ + +/* bits definitions */ +/* ADC_STAT */ +#define ADC_STAT_WDE BIT(0) /*!< analog watchdog event flag */ +#define ADC_STAT_EOC BIT(1) /*!< end of conversion */ +#define ADC_STAT_EOIC BIT(2) /*!< inserted channel end of conversion */ +#define ADC_STAT_STIC BIT(3) /*!< inserted channel start flag */ +#define ADC_STAT_STRC BIT(4) /*!< regular channel start flag */ + +/* ADC_CTL0 */ +#define ADC_CTL0_WDCHSEL BITS(0, 4) /*!< analog watchdog channel select bits */ +#define ADC_CTL0_EOCIE BIT(5) /*!< interrupt enable for EOC */ +#define ADC_CTL0_WDEIE BIT(6) /*!< analog watchdog interrupt enable */ +#define ADC_CTL0_EOICIE BIT(7) /*!< interrupt enable for inserted channels */ +#define ADC_CTL0_SM BIT(8) /*!< scan mode */ +#define ADC_CTL0_WDSC BIT(9) /*!< when in scan mode, analog watchdog is effective on a single channel */ +#define ADC_CTL0_ICA BIT(10) /*!< automatic inserted group conversion */ +#define ADC_CTL0_DISRC BIT(11) /*!< discontinuous mode on regular channels */ +#define ADC_CTL0_DISIC BIT(12) /*!< discontinuous mode on inserted channels */ +#define ADC_CTL0_DISNUM BITS(13, 15) /*!< discontinuous mode channel count */ +#define ADC_CTL0_SYNCM BITS(16, 19) /*!< sync mode selection */ +#define ADC_CTL0_IWDEN BIT(22) /*!< analog watchdog enable on inserted channels */ +#define ADC_CTL0_RWDEN BIT(23) /*!< analog watchdog enable on regular channels */ + +/* ADC_CTL1 */ +#define ADC_CTL1_ADCON BIT(0) /*!< ADC converter on */ +#define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ +#define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ +#define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ +#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DAL BIT(11) /*!< data alignment */ +#define ADC_CTL1_ETSIC BITS(12, 14) /*!< external trigger select for inserted channel */ +#define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ +#define ADC_CTL1_ETSRC BITS(17, 19) /*!< external trigger select for regular channel */ +#define ADC_CTL1_ETERC BIT(20) /*!< external trigger conversion mode for inserted channels */ +#define ADC_CTL1_SWICST BIT(21) /*!< start on inserted channel */ +#define ADC_CTL1_SWRCST BIT(22) /*!< start on regular channel */ +#define ADC_CTL1_TSVREN BIT(23) /*!< channel 16 and 17 enable of ADC0 */ + +/* ADC_SAMPTx x=0..1 */ +#define ADC_SAMPTX_SPTN BITS(0, 2) /*!< channel n sample time selection */ + +/* ADC_IOFFx x=0..3 */ +#define ADC_IOFFX_IOFF BITS(0, 11) /*!< data offset for inserted channel x */ + +/* ADC_WDHT */ +#define ADC_WDHT_WDHT BITS(0, 11) /*!< analog watchdog high threshold */ + +/* ADC_WDLT */ +#define ADC_WDLT_WDLT BITS(0, 11) /*!< analog watchdog low threshold */ + +/* ADC_RSQx x=0..2 */ +#define ADC_RSQX_RSQN BITS(0, 4) /*!< nth conversion in regular sequence */ +#define ADC_RSQ0_RL BITS(20, 23) /*!< regular channel sequence length */ + +/* ADC_ISQ */ +#define ADC_ISQ_ISQN BITS(0, 4) /*!< nth conversion in inserted sequence */ +#define ADC_ISQ_IL BITS(20, 21) /*!< inserted sequence length */ + +/* ADC_IDATAx x=0..3*/ +#define ADC_IDATAX_IDATAN BITS(0, 15) /*!< inserted data n */ + +/* ADC_RDATA */ +#define ADC_RDATA_RDATA BITS(0, 15) /*!< regular data */ +#define ADC_RDATA_ADC1RDTR BITS(16, 31) /*!< ADC1 regular channel data */ + +/* ADC_OVSCR */ +#define ADC_OVSCR_OVSEN BIT(0) /*!< oversampling enable */ +#define ADC_OVSCR_OVSR BITS(2, 4) /*!< oversampling ratio */ +#define ADC_OVSCR_OVSS BITS(5, 8) /*!< oversampling shift */ +#define ADC_OVSCR_TOVS BIT(9) /*!< triggered oversampling */ +#define ADC_OVSCR_DRES BITS(12, 13) /*!< ADC data resolution */ + +/* constants definitions */ +/* adc_stat register value */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< inserted channel end of conversion */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ + +/* adc_ctl0 register value */ +#define CTL0_DISNUM(regval) (BITS(13, 15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ + +/* scan mode */ +#define ADC_SCAN_MODE ADC_CTL0_SM /*!< scan mode */ + +/* inserted channel group convert automatically */ +#define ADC_INSERTED_CHANNEL_AUTO ADC_CTL0_ICA /*!< inserted channel group convert automatically */ + +/* ADC sync mode */ +#define CTL0_SYNCM(regval) (BITS(16, 19) & ((uint32_t)(regval) << 16)) /*!< write value to ADC_CTL0_SYNCM bit field */ +#define ADC_MODE_FREE CTL0_SYNCM(0) /*!< all the ADCs work independently */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL CTL0_SYNCM(1) /*!< ADC0 and ADC1 work in combined regular parallel + inserted parallel mode */ +#define ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION CTL0_SYNCM(2) /*!< ADC0 and ADC1 work in combined regular parallel + trigger rotation mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(3) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up fast mode */ +#define ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(4) /*!< ADC0 and ADC1 work in combined inserted parallel + follow-up slow mode */ +#define ADC_DAUL_INSERTED_PARALLEL CTL0_SYNCM(5) /*!< ADC0 and ADC1 work in inserted parallel mode only */ +#define ADC_DAUL_REGULAL_PARALLEL CTL0_SYNCM(6) /*!< ADC0 and ADC1 work in regular parallel mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_FAST CTL0_SYNCM(7) /*!< ADC0 and ADC1 work in follow-up fast mode only */ +#define ADC_DAUL_REGULAL_FOLLOWUP_SLOW CTL0_SYNCM(8) /*!< ADC0 and ADC1 work in follow-up slow mode only */ +#define ADC_DAUL_INSERTED_TRIGGER_ROTATION CTL0_SYNCM(9) /*!< ADC0 and ADC1 work in trigger rotation mode only */ + +/* adc_ctl1 register value */ +#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000U) /*!< LSB alignment */ +#define ADC_DATAALIGN_LEFT ADC_CTL1_DAL /*!< MSB alignment */ + +/* continuous mode */ +#define ADC_CONTINUOUS_MODE ADC_CTL1_CTN /*!< continuous mode */ + +/* external trigger select for regular channel */ +#define CTL1_ETSRC(regval) (BITS(17, 19) & ((uint32_t)(regval) << 17)) /*!< write value to ADC_CTL1_ETSRC bit field */ +/* for ADC0 and ADC1 regular channel */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH0 CTL1_ETSRC(0) /*!< TIMER0 CH0 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH1 CTL1_ETSRC(1) /*!< TIMER0 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T0_CH2 CTL1_ETSRC(2) /*!< TIMER0 CH2 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T1_CH1 CTL1_ETSRC(3) /*!< TIMER1 CH1 event select */ +#define ADC0_1_EXTTRIG_REGULAR_T2_TRGO CTL1_ETSRC(4) /*!< TIMER2 TRGO event select */ +#define ADC0_1_EXTTRIG_REGULAR_T3_CH3 CTL1_ETSRC(5) /*!< TIMER3 CH3 event select */ +#define ADC0_1_EXTTRIG_REGULAR_EXTI_11 CTL1_ETSRC(6) /*!< external interrupt line 11 */ +#define ADC0_1_EXTTRIG_REGULAR_NONE CTL1_ETSRC(7) /*!< software trigger */ + +/* external trigger mode for inserted channel */ +#define CTL1_ETSIC(regval) (BITS(12, 14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ +/* for ADC0 and ADC1 inserted channel */ +#define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T0_CH3 CTL1_ETSIC(1) /*!< TIMER0 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_TRGO CTL1_ETSIC(2) /*!< TIMER1 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_T1_CH0 CTL1_ETSIC(3) /*!< TIMER1 CH0 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T2_CH3 CTL1_ETSIC(4) /*!< TIMER2 CH3 event select */ +#define ADC0_1_EXTTRIG_INSERTED_T3_TRGO CTL1_ETSIC(5) /*!< TIMER3 TRGO event select */ +#define ADC0_1_EXTTRIG_INSERTED_EXTI_15 CTL1_ETSIC(6) /*!< external interrupt line 15 */ +#define ADC0_1_EXTTRIG_INSERTED_NONE CTL1_ETSIC(7) /*!< software trigger */ + +/* adc_samptx register value */ +#define SAMPTX_SPT(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_SAMPTX_SPT bit field */ +#define ADC_SAMPLETIME_1POINT5 SAMPTX_SPT(0) /*!< 1.5 sampling cycles */ +#define ADC_SAMPLETIME_7POINT5 SAMPTX_SPT(1) /*!< 7.5 sampling cycles */ +#define ADC_SAMPLETIME_13POINT5 SAMPTX_SPT(2) /*!< 13.5 sampling cycles */ +#define ADC_SAMPLETIME_28POINT5 SAMPTX_SPT(3) /*!< 28.5 sampling cycles */ +#define ADC_SAMPLETIME_41POINT5 SAMPTX_SPT(4) /*!< 41.5 sampling cycles */ +#define ADC_SAMPLETIME_55POINT5 SAMPTX_SPT(5) /*!< 55.5 sampling cycles */ +#define ADC_SAMPLETIME_71POINT5 SAMPTX_SPT(6) /*!< 71.5 sampling cycles */ +#define ADC_SAMPLETIME_239POINT5 SAMPTX_SPT(7) /*!< 239.5 sampling cycles */ + +/* adc_ioffx register value */ +#define IOFFX_IOFF(regval) (BITS(0, 11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_IOFFX_IOFF bit field */ + +/* adc_wdht register value */ +#define WDHT_WDHT(regval) (BITS(0, 11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDHT_WDHT bit field */ + +/* adc_wdlt register value */ +#define WDLT_WDLT(regval) (BITS(0, 11) & ((uint32_t)(regval) << 0)) /*!< write value to ADC_WDLT_WDLT bit field */ + +/* adc_rsqx register value */ +#define RSQ0_RL(regval) (BITS(20, 23) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_RSQ0_RL bit field */ + +/* adc_isq register value */ +#define ISQ_IL(regval) (BITS(20, 21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ + +/* ADC channel group definitions */ +#define ADC_REGULAR_CHANNEL ((uint8_t)0x01U) /*!< adc regular channel group */ +#define ADC_INSERTED_CHANNEL ((uint8_t)0x02U) /*!< adc inserted channel group */ +#define ADC_REGULAR_INSERTED_CHANNEL ((uint8_t)0x03U) /*!< both regular and inserted channel group */ + +#define ADC_CHANNEL_DISCON_DISABLE ((uint8_t)0x04U) /*!< disable discontinuous mode of regular & inserted channel */ + +/* ADC inserted channel definitions */ +#define ADC_INSERTED_CHANNEL_0 ((uint8_t)0x00U) /*!< adc inserted channel 0 */ +#define ADC_INSERTED_CHANNEL_1 ((uint8_t)0x01U) /*!< adc inserted channel 1 */ +#define ADC_INSERTED_CHANNEL_2 ((uint8_t)0x02U) /*!< adc inserted channel 2 */ +#define ADC_INSERTED_CHANNEL_3 ((uint8_t)0x03U) /*!< adc inserted channel 3 */ + +/* ADC channel definitions */ +#define ADC_CHANNEL_0 ((uint8_t)0x00U) /*!< ADC channel 0 */ +#define ADC_CHANNEL_1 ((uint8_t)0x01U) /*!< ADC channel 1 */ +#define ADC_CHANNEL_2 ((uint8_t)0x02U) /*!< ADC channel 2 */ +#define ADC_CHANNEL_3 ((uint8_t)0x03U) /*!< ADC channel 3 */ +#define ADC_CHANNEL_4 ((uint8_t)0x04U) /*!< ADC channel 4 */ +#define ADC_CHANNEL_5 ((uint8_t)0x05U) /*!< ADC channel 5 */ +#define ADC_CHANNEL_6 ((uint8_t)0x06U) /*!< ADC channel 6 */ +#define ADC_CHANNEL_7 ((uint8_t)0x07U) /*!< ADC channel 7 */ +#define ADC_CHANNEL_8 ((uint8_t)0x08U) /*!< ADC channel 8 */ +#define ADC_CHANNEL_9 ((uint8_t)0x09U) /*!< ADC channel 9 */ +#define ADC_CHANNEL_10 ((uint8_t)0x0AU) /*!< ADC channel 10 */ +#define ADC_CHANNEL_11 ((uint8_t)0x0BU) /*!< ADC channel 11 */ +#define ADC_CHANNEL_12 ((uint8_t)0x0CU) /*!< ADC channel 12 */ +#define ADC_CHANNEL_13 ((uint8_t)0x0DU) /*!< ADC channel 13 */ +#define ADC_CHANNEL_14 ((uint8_t)0x0EU) /*!< ADC channel 14 */ +#define ADC_CHANNEL_15 ((uint8_t)0x0FU) /*!< ADC channel 15 */ +#define ADC_CHANNEL_16 ((uint8_t)0x10U) /*!< ADC channel 16 */ +#define ADC_CHANNEL_17 ((uint8_t)0x11U) /*!< ADC channel 17 */ + +/* ADC interrupt */ +#define ADC_INT_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt */ +#define ADC_INT_EOC ADC_STAT_EOC /*!< end of group conversion interrupt */ +#define ADC_INT_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt */ + +/* ADC interrupt flag */ +#define ADC_INT_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event interrupt flag */ +#define ADC_INT_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion interrupt flag */ +#define ADC_INT_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted group conversion interrupt flag */ + +/* ADC resolution definitions */ +#define OVSCR_DRES(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12)) +#define ADC_RESOLUTION_12B OVSCR_DRES(0) /*!< 12-bit ADC resolution */ +#define ADC_RESOLUTION_10B OVSCR_DRES(1) /*!< 10-bit ADC resolution */ +#define ADC_RESOLUTION_8B OVSCR_DRES(2) /*!< 8-bit ADC resolution */ +#define ADC_RESOLUTION_6B OVSCR_DRES(3) /*!< 6-bit ADC resolution */ + +/* ADC oversampling mode */ +#define ADC_OVERSAMPLING_ALL_CONVERT 0 /*!< all oversampled conversions for a channel are done consecutively after a trigger */ +#define ADC_OVERSAMPLING_ONE_CONVERT 1 /*!< each oversampled conversion for a channel needs a trigger */ + +/* ADC oversampling shift */ +#define OVSCR_OVSS(regval) (BITS(5, 8) & ((uint32_t)(regval) << 5)) +#define ADC_OVERSAMPLING_SHIFT_NONE OVSCR_OVSS(0) /*!< no oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_1B OVSCR_OVSS(1) /*!< 1-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_2B OVSCR_OVSS(2) /*!< 2-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_3B OVSCR_OVSS(3) /*!< 3-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_4B OVSCR_OVSS(4) /*!< 4-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_5B OVSCR_OVSS(5) /*!< 5-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_6B OVSCR_OVSS(6) /*!< 6-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_7B OVSCR_OVSS(7) /*!< 7-bit oversampling shift */ +#define ADC_OVERSAMPLING_SHIFT_8B OVSCR_OVSS(8) /*!< 8-bit oversampling shift */ + +/* ADC oversampling ratio */ +#define OVSCR_OVSR(regval) (BITS(2, 4) & ((uint32_t)(regval) << 2)) +#define ADC_OVERSAMPLING_RATIO_MUL2 OVSCR_OVSR(0) /*!< oversampling ratio X2 */ +#define ADC_OVERSAMPLING_RATIO_MUL4 OVSCR_OVSR(1) /*!< oversampling ratio X4 */ +#define ADC_OVERSAMPLING_RATIO_MUL8 OVSCR_OVSR(2) /*!< oversampling ratio X8 */ +#define ADC_OVERSAMPLING_RATIO_MUL16 OVSCR_OVSR(3) /*!< oversampling ratio X16 */ +#define ADC_OVERSAMPLING_RATIO_MUL32 OVSCR_OVSR(4) /*!< oversampling ratio X32 */ +#define ADC_OVERSAMPLING_RATIO_MUL64 OVSCR_OVSR(5) /*!< oversampling ratio X64 */ +#define ADC_OVERSAMPLING_RATIO_MUL128 OVSCR_OVSR(6) /*!< oversampling ratio X128 */ +#define ADC_OVERSAMPLING_RATIO_MUL256 OVSCR_OVSR(7) /*!< oversampling ratio X256 */ + +/* function declarations */ +/* initialization config */ +/* reset ADC */ +void adc_deinit(uint32_t adc_periph); +/* configure the ADC sync mode */ +void adc_mode_config(uint32_t mode); +/* enable or disable ADC special function */ +void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue); +/* configure ADC data alignment */ +void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment); +/* enable ADC interface */ +void adc_enable(uint32_t adc_periph); +/* disable ADC interface */ +void adc_disable(uint32_t adc_periph); +/* ADC calibration and reset calibration */ +void adc_calibration_enable(uint32_t adc_periph); +/* enable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_enable(void); +/* disable the temperature sensor and Vrefint channel */ +void adc_tempsensor_vrefint_disable(void); + +/* DMA config */ +/* enable DMA request */ +void adc_dma_mode_enable(uint32_t adc_periph); +/* disable DMA request */ +void adc_dma_mode_disable(uint32_t adc_periph); + +/* regular group and inserted group config */ +/* configure ADC discontinuous mode */ +void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_group, uint8_t length); + +/* configure the length of regular channel group or inserted channel group */ +void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length); +/* configure ADC regular channel */ +void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel */ +void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time); +/* configure ADC inserted channel offset */ +void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_channel, uint16_t offset); + +/* configure ADC external trigger source */ +void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source); +/* configure ADC external trigger */ +void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue); +/* enable ADC software trigger */ +void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); + +/* get channel data */ +/* read ADC regular group data register */ +uint16_t adc_regular_data_read(uint32_t adc_periph); +/* read ADC inserted group data register */ +uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); +/* read the last ADC0 and ADC1 conversion result data in sync mode */ +uint32_t adc_sync_mode_convert_value_read(void); + +/* watchdog config */ +/* configure ADC analog watchdog single channel */ +void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); +/* configure ADC analog watchdog group channel */ +void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_group); +/* disable ADC analog watchdog */ +void adc_watchdog_disable(uint32_t adc_periph); +/* configure ADC analog watchdog threshold */ +void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); + +/* interrupt & flag functions */ +/* get the ADC flag bits */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag bits */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* get the bit state of ADCx software start conversion */ +FlagStatus adc_regular_software_startconv_flag_get(uint32_t adc_periph); +/* get the bit state of ADCx software inserted channel start conversion */ +FlagStatus adc_inserted_software_startconv_flag_get(uint32_t adc_periph); +/* get the ADC interrupt bits */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); + +/* ADC resolution & oversample */ +/* ADC resolution config */ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution); +/* ADC oversample mode config */ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio); +/* enable ADC oversample mode */ +void adc_oversample_mode_enable(uint32_t adc_periph); +/* disable ADC oversample mode */ +void adc_oversample_mode_disable(uint32_t adc_periph); + +#endif /* GD32VF103_ADC_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.c new file mode 100644 index 00000000..f2de1677 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.c @@ -0,0 +1,292 @@ +/*! + \file gd32vf103_bkp.c + \brief BKP driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_bkp.h" + +/* BKP register bits offset */ +#define BKP_TAMPER_BITS_OFFSET ((uint32_t)8U) + +/*! + \brief reset BKP registers + \param[in] none + \param[out] none + \retval none +*/ +void bkp_deinit(void) +{ + /* reset BKP domain register*/ + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); +} + +/*! + \brief write BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[in] data: the data to be write in BKP data register + \param[out] none + \retval none +*/ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) +{ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + BKP_DATA10_41(register_number - 1U) = data; + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + BKP_DATA0_9(register_number - 1U) = data; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief read BKP data register + \param[in] register_number: refer to bkp_data_register_enum + only one parameter can be selected which is shown as below: + \arg BKP_DATA_x(x = 0..41): bkp data register number x + \param[out] none + \retval data of BKP data register +*/ +uint16_t bkp_data_read(bkp_data_register_enum register_number) +{ + uint16_t data = 0U; + + /* get the data from the BKP data register */ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + data = BKP_DATA10_41(register_number - 1U); + }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + data = BKP_DATA0_9(register_number - 1U); + }else{ + /* illegal parameters */ + } + return data; +} + +/*! + \brief enable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_COEN; +} + +/*! + \brief disable RTC clock calibration output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_COEN; +} + +/*! + \brief enable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_enable(void) +{ + BKP_OCTL |= (uint16_t)BKP_OCTL_ASOEN; +} + +/*! + \brief disable RTC alarm or second signal output + \param[in] none + \param[out] none + \retval none +*/ +void bkp_rtc_signal_output_disable(void) +{ + BKP_OCTL &= (uint16_t)~BKP_OCTL_ASOEN; +} + +/*! + \brief select RTC output + \param[in] outputsel: RTC output selection + only one parameter can be selected which is shown as below: + \arg RTC_OUTPUT_ALARM_PULSE: RTC alarm pulse is selected as the RTC output + \arg RTC_OUTPUT_SECOND_PULSE: RTC second pulse is selected as the RTC output + \param[out] none + \retval none +*/ +void bkp_rtc_output_select(uint16_t outputsel) +{ + uint16_t ctl = 0U; + + /* configure BKP_OCTL_ROSEL with outputsel */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_ROSEL; + ctl |= outputsel; + BKP_OCTL = ctl; +} + +/*! + \brief set RTC clock calibration value + \param[in] value: RTC clock calibration value + \arg 0x00 - 0x7F + \param[out] none + \retval none +*/ +void bkp_rtc_calibration_value_set(uint8_t value) +{ + uint16_t ctl; + + /* configure BKP_OCTL_RCCV with value */ + ctl = BKP_OCTL; + ctl &= (uint16_t)~BKP_OCTL_RCCV; + ctl |= (uint16_t)OCTL_RCCV(value); + BKP_OCTL = ctl; +} + +/*! + \brief enable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_enable(void) +{ + BKP_TPCTL |= (uint16_t)BKP_TPCTL_TPEN; +} + +/*! + \brief disable tamper detection + \param[in] none + \param[out] none + \retval none +*/ +void bkp_tamper_detection_disable(void) +{ + BKP_TPCTL &= (uint16_t)~BKP_TPCTL_TPEN; +} + +/*! + \brief set tamper pin active level + \param[in] level: tamper active level + only one parameter can be selected which is shown as below: + \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high + \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low + \param[out] none + \retval none +*/ +void bkp_tamper_active_level_set(uint16_t level) +{ + uint16_t ctl = 0U; + + /* configure BKP_TPCTL_TPAL with level */ + ctl = BKP_TPCTL; + ctl &= (uint16_t)~BKP_TPCTL_TPAL; + ctl |= level; + BKP_TPCTL = ctl; +} + +/*! + \brief enable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_enable(void) +{ + BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE; +} + +/*! + \brief disable tamper interrupt + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_disable(void) +{ + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE; +} + +/*! + \brief get tamper flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} + +/*! + \brief get tamper interrupt flag state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus bkp_interrupt_flag_get(void) +{ + if(RESET != (BKP_TPCS & BKP_INT_FLAG_TAMPER)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear tamper interrupt flag state + \param[in] none + \param[out] none + \retval none +*/ +void bkp_interrupt_flag_clear(void) +{ + BKP_TPCS |= (uint16_t)(BKP_INT_FLAG_TAMPER >> BKP_TAMPER_BITS_OFFSET); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.h new file mode 100644 index 00000000..7d2e0683 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_bkp.h @@ -0,0 +1,231 @@ +/*! + \file gd32vf103_bkp.h + \brief definitions for the BKP + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_BKP_H +#define GD32VF103_BKP_H + +#include "gd32vf103.h" + +/* BKP definitions */ +#define BKP BKP_BASE /*!< BKP base address */ + +/* registers definitions */ +#define BKP_DATA0 REG16((BKP) + 0x04U) /*!< BKP data register 0 */ +#define BKP_DATA1 REG16((BKP) + 0x08U) /*!< BKP data register 1 */ +#define BKP_DATA2 REG16((BKP) + 0x0CU) /*!< BKP data register 2 */ +#define BKP_DATA3 REG16((BKP) + 0x10U) /*!< BKP data register 3 */ +#define BKP_DATA4 REG16((BKP) + 0x14U) /*!< BKP data register 4 */ +#define BKP_DATA5 REG16((BKP) + 0x18U) /*!< BKP data register 5 */ +#define BKP_DATA6 REG16((BKP) + 0x1CU) /*!< BKP data register 6 */ +#define BKP_DATA7 REG16((BKP) + 0x20U) /*!< BKP data register 7 */ +#define BKP_DATA8 REG16((BKP) + 0x24U) /*!< BKP data register 8 */ +#define BKP_DATA9 REG16((BKP) + 0x28U) /*!< BKP data register 9 */ +#define BKP_DATA10 REG16((BKP) + 0x40U) /*!< BKP data register 10 */ +#define BKP_DATA11 REG16((BKP) + 0x44U) /*!< BKP data register 11 */ +#define BKP_DATA12 REG16((BKP) + 0x48U) /*!< BKP data register 12 */ +#define BKP_DATA13 REG16((BKP) + 0x4CU) /*!< BKP data register 13 */ +#define BKP_DATA14 REG16((BKP) + 0x50U) /*!< BKP data register 14 */ +#define BKP_DATA15 REG16((BKP) + 0x54U) /*!< BKP data register 15 */ +#define BKP_DATA16 REG16((BKP) + 0x58U) /*!< BKP data register 16 */ +#define BKP_DATA17 REG16((BKP) + 0x5CU) /*!< BKP data register 17 */ +#define BKP_DATA18 REG16((BKP) + 0x60U) /*!< BKP data register 18 */ +#define BKP_DATA19 REG16((BKP) + 0x64U) /*!< BKP data register 19 */ +#define BKP_DATA20 REG16((BKP) + 0x68U) /*!< BKP data register 20 */ +#define BKP_DATA21 REG16((BKP) + 0x6CU) /*!< BKP data register 21 */ +#define BKP_DATA22 REG16((BKP) + 0x70U) /*!< BKP data register 22 */ +#define BKP_DATA23 REG16((BKP) + 0x74U) /*!< BKP data register 23 */ +#define BKP_DATA24 REG16((BKP) + 0x78U) /*!< BKP data register 24 */ +#define BKP_DATA25 REG16((BKP) + 0x7CU) /*!< BKP data register 25 */ +#define BKP_DATA26 REG16((BKP) + 0x80U) /*!< BKP data register 26 */ +#define BKP_DATA27 REG16((BKP) + 0x84U) /*!< BKP data register 27 */ +#define BKP_DATA28 REG16((BKP) + 0x88U) /*!< BKP data register 28 */ +#define BKP_DATA29 REG16((BKP) + 0x8CU) /*!< BKP data register 29 */ +#define BKP_DATA30 REG16((BKP) + 0x90U) /*!< BKP data register 30 */ +#define BKP_DATA31 REG16((BKP) + 0x94U) /*!< BKP data register 31 */ +#define BKP_DATA32 REG16((BKP) + 0x98U) /*!< BKP data register 32 */ +#define BKP_DATA33 REG16((BKP) + 0x9CU) /*!< BKP data register 33 */ +#define BKP_DATA34 REG16((BKP) + 0xA0U) /*!< BKP data register 34 */ +#define BKP_DATA35 REG16((BKP) + 0xA4U) /*!< BKP data register 35 */ +#define BKP_DATA36 REG16((BKP) + 0xA8U) /*!< BKP data register 36 */ +#define BKP_DATA37 REG16((BKP) + 0xACU) /*!< BKP data register 37 */ +#define BKP_DATA38 REG16((BKP) + 0xB0U) /*!< BKP data register 38 */ +#define BKP_DATA39 REG16((BKP) + 0xB4U) /*!< BKP data register 39 */ +#define BKP_DATA40 REG16((BKP) + 0xB8U) /*!< BKP data register 40 */ +#define BKP_DATA41 REG16((BKP) + 0xBCU) /*!< BKP data register 41 */ +#define BKP_OCTL REG16((BKP) + 0x2CU) /*!< RTC signal output control register */ +#define BKP_TPCTL REG16((BKP) + 0x30U) /*!< tamper pin control register */ +#define BKP_TPCS REG16((BKP) + 0x34U) /*!< tamper control and status register */ + +/* bits definitions */ +/* BKP_DATA */ +#define BKP_DATA BITS(0, 15) /*!< backup data */ + +/* BKP_OCTL */ +#define BKP_OCTL_RCCV BITS(0, 6) /*!< RTC clock calibration value */ +#define BKP_OCTL_COEN BIT(7) /*!< RTC clock calibration output enable */ +#define BKP_OCTL_ASOEN BIT(8) /*!< RTC alarm or second signal output enable */ +#define BKP_OCTL_ROSEL BIT(9) /*!< RTC output selection */ + +/* BKP_TPCTL */ +#define BKP_TPCTL_TPEN BIT(0) /*!< tamper detection enable */ +#define BKP_TPCTL_TPAL BIT(1) /*!< tamper pin active level */ + +/* BKP_TPCS */ +#define BKP_TPCS_TER BIT(0) /*!< tamper event reset */ +#define BKP_TPCS_TIR BIT(1) /*!< tamper interrupt reset */ +#define BKP_TPCS_TPIE BIT(2) /*!< tamper interrupt enable */ +#define BKP_TPCS_TEF BIT(8) /*!< tamper event flag */ +#define BKP_TPCS_TIF BIT(9) /*!< tamper interrupt flag */ + +/* constants definitions */ +/* BKP data register number */ +typedef enum { + BKP_DATA_0 = 1, /*!< BKP data register 0 */ + BKP_DATA_1, /*!< BKP data register 1 */ + BKP_DATA_2, /*!< BKP data register 2 */ + BKP_DATA_3, /*!< BKP data register 3 */ + BKP_DATA_4, /*!< BKP data register 4 */ + BKP_DATA_5, /*!< BKP data register 5 */ + BKP_DATA_6, /*!< BKP data register 6 */ + BKP_DATA_7, /*!< BKP data register 7 */ + BKP_DATA_8, /*!< BKP data register 8 */ + BKP_DATA_9, /*!< BKP data register 9 */ + BKP_DATA_10, /*!< BKP data register 10 */ + BKP_DATA_11, /*!< BKP data register 11 */ + BKP_DATA_12, /*!< BKP data register 12 */ + BKP_DATA_13, /*!< BKP data register 13 */ + BKP_DATA_14, /*!< BKP data register 14 */ + BKP_DATA_15, /*!< BKP data register 15 */ + BKP_DATA_16, /*!< BKP data register 16 */ + BKP_DATA_17, /*!< BKP data register 17 */ + BKP_DATA_18, /*!< BKP data register 18 */ + BKP_DATA_19, /*!< BKP data register 19 */ + BKP_DATA_20, /*!< BKP data register 20 */ + BKP_DATA_21, /*!< BKP data register 21 */ + BKP_DATA_22, /*!< BKP data register 22 */ + BKP_DATA_23, /*!< BKP data register 23 */ + BKP_DATA_24, /*!< BKP data register 24 */ + BKP_DATA_25, /*!< BKP data register 25 */ + BKP_DATA_26, /*!< BKP data register 26 */ + BKP_DATA_27, /*!< BKP data register 27 */ + BKP_DATA_28, /*!< BKP data register 28 */ + BKP_DATA_29, /*!< BKP data register 29 */ + BKP_DATA_30, /*!< BKP data register 30 */ + BKP_DATA_31, /*!< BKP data register 31 */ + BKP_DATA_32, /*!< BKP data register 32 */ + BKP_DATA_33, /*!< BKP data register 33 */ + BKP_DATA_34, /*!< BKP data register 34 */ + BKP_DATA_35, /*!< BKP data register 35 */ + BKP_DATA_36, /*!< BKP data register 36 */ + BKP_DATA_37, /*!< BKP data register 37 */ + BKP_DATA_38, /*!< BKP data register 38 */ + BKP_DATA_39, /*!< BKP data register 39 */ + BKP_DATA_40, /*!< BKP data register 40 */ + BKP_DATA_41, /*!< BKP data register 41 */ +} bkp_data_register_enum; + +/* BKP register */ +#define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number)*0x04U) +#define BKP_DATA10_41(number) REG16((BKP) + 0x40U + ((number)-10U) * 0x04U) + +/* get data of BKP data register */ +#define BKP_DATA_GET(regval) GET_BITS((uint32_t)(regval), 0, 15) + +/* RTC clock calibration value */ +#define OCTL_RCCV(regval) (BITS(0, 6) & ((uint32_t)(regval) << 0)) + +/* RTC output selection */ +#define RTC_OUTPUT_ALARM_PULSE ((uint16_t)0x0000U) /*!< RTC alarm pulse is selected as the RTC output */ +#define RTC_OUTPUT_SECOND_PULSE ((uint16_t)0x0200U) /*!< RTC second pulse is selected as the RTC output */ + +/* tamper pin active level */ +#define TAMPER_PIN_ACTIVE_HIGH ((uint16_t)0x0000U) /*!< the tamper pin is active high */ +#define TAMPER_PIN_ACTIVE_LOW ((uint16_t)0x0002U) /*!< the tamper pin is active low */ + +/* tamper flag */ +#define BKP_FLAG_TAMPER BKP_TPCS_TEF /*!< tamper event flag */ + +/* tamper interrupt flag */ +#define BKP_INT_FLAG_TAMPER BKP_TPCS_TIF /*!< tamper interrupt flag */ + +/* function declarations */ +/* reset BKP registers */ +void bkp_deinit(void); +/* write BKP data register */ +void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); +/* read BKP data register */ +uint16_t bkp_data_read(bkp_data_register_enum register_number); + +/* RTC related functions */ +/* enable RTC clock calibration output */ +void bkp_rtc_calibration_output_enable(void); +/* disable RTC clock calibration output */ +void bkp_rtc_calibration_output_disable(void); +/* enable RTC alarm or second signal output */ +void bkp_rtc_signal_output_enable(void); +/* disable RTC alarm or second signal output */ +void bkp_rtc_signal_output_disable(void); +/* select RTC output */ +void bkp_rtc_output_select(uint16_t outputsel); +/* set RTC clock calibration value */ +void bkp_rtc_calibration_value_set(uint8_t value); + +/* tamper pin related functions */ +/* enable tamper pin detection */ +void bkp_tamper_detection_enable(void); +/* disable tamper pin detection */ +void bkp_tamper_detection_disable(void); +/* set tamper pin active level */ +void bkp_tamper_active_level_set(uint16_t level); + +/* interrupt & flag functions */ +/* enable tamper interrupt */ +void bkp_interrupt_enable(void); +/* disable tamper interrupt */ +void bkp_interrupt_disable(void); +/* get tamper flag state */ +FlagStatus bkp_flag_get(void); +/* clear tamper flag state */ +void bkp_flag_clear(void); +/* get tamper interrupt flag state */ +FlagStatus bkp_interrupt_flag_get(void); +/* clear tamper interrupt flag state */ +void bkp_interrupt_flag_clear(void); + +#endif /* GD32VF103_BKP_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.c new file mode 100644 index 00000000..cd5354c3 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.c @@ -0,0 +1,127 @@ +/*! + \file gd32vf103_crc.c + \brief CRC driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_crc.h" + +#define CRC_DATA_RESET_VALUE ((uint32_t)0xFFFFFFFFU) +#define CRC_FDATA_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinit CRC calculation unit + \param[in] none + \param[out] none + \retval none +*/ +void crc_deinit(void) +{ + CRC_DATA = CRC_DATA_RESET_VALUE; + CRC_FDATA = CRC_FDATA_RESET_VALUE; + CRC_CTL = (uint32_t)CRC_CTL_RST; +} + +/*! + \brief reset data register(CRC_DATA) to the value of 0xFFFFFFFF + \param[in] none + \param[out] none + \retval none +*/ +void crc_data_register_reset(void) +{ + CRC_CTL |= (uint32_t)CRC_CTL_RST; +} + +/*! + \brief read the value of the data register + \param[in] none + \param[out] none + \retval 32-bit value of the data register +*/ +uint32_t crc_data_register_read(void) +{ + uint32_t data; + data = CRC_DATA; + return (data); +} + +/*! + \brief read the value of the free data register + \param[in] none + \param[out] none + \retval 8-bit value of the free data register +*/ +uint8_t crc_free_data_register_read(void) +{ + uint8_t fdata; + fdata = (uint8_t)CRC_FDATA; + return (fdata); +} + +/*! + \brief write data to the free data register + \param[in] free_data: specified 8-bit data + \param[out] none + \retval none +*/ +void crc_free_data_register_write(uint8_t free_data) +{ + CRC_FDATA = (uint32_t)free_data; +} + +/*! + \brief calculate the CRC value of a 32-bit data + \param[in] sdata: specified 32-bit data + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_single_data_calculate(uint32_t sdata) +{ + CRC_DATA = sdata; + return (CRC_DATA); +} + +/*! + \brief calculate the CRC value of an array of 32-bit values + \param[in] array: pointer to an array of 32-bit values + \param[in] size: size of the array + \param[out] none + \retval 32-bit value calculated by CRC +*/ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) +{ + uint32_t index; + for(index = 0U; index < size; index++){ + CRC_DATA = array[index]; + } + return (CRC_DATA); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.h new file mode 100644 index 00000000..4a8a9f94 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_crc.h @@ -0,0 +1,83 @@ +/*! + \file gd32vf103_crc.h + \brief definitions for the CRC + + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_CRC_H +#define GD32VF103_CRC_H + +#include "gd32vf103.h" + +/* CRC definitions */ +#define CRC CRC_BASE + +/* registers definitions */ +#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ + +/* bits definitions */ +/* CRC_DATA */ +#define CRC_DATA_DATA BITS(0, 31) /*!< CRC calculation result bits */ + +/* CRC_FDATA */ +#define CRC_FDATA_FDATA BITS(0, 7) /*!< CRC free data bits */ + +/* CRC_CTL */ +#define CRC_CTL_RST BIT(0) /*!< CRC reset CRC_DATA register bit */ + +/* function declarations */ +/* deinit CRC calculation unit */ +void crc_deinit(void); + +/* reset data register(CRC_DATA) to the value of 0xFFFFFFFF */ +void crc_data_register_reset(void); +/* read the value of the data register */ +uint32_t crc_data_register_read(void); + +/* read the value of the free data register */ +uint8_t crc_free_data_register_read(void); +/* write data to the free data register */ +void crc_free_data_register_write(uint8_t free_data); + +/* calculate the CRC value of a 32-bit data */ +uint32_t crc_single_data_calculate(uint32_t sdata); +/* calculate the CRC value of an array of 32-bit values */ +uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size); + +#endif /* GD32VF103_CRC_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.c new file mode 100644 index 00000000..924b12de --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.c @@ -0,0 +1,110 @@ +/*! + \file gd32vf103_dbg.c + \brief DBG driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_dbg.h" + +/*! + \brief read DBG_ID code register + \param[in] none + \param[out] none + \retval DBG_ID code +*/ +uint32_t dbg_id_get(void) +{ + return DBG_ID; +} + +/*! + \brief enable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_enable(uint32_t dbg_low_power) +{ + DBG_CTL |= dbg_low_power; +} + +/*! + \brief disable low power behavior when the mcu is in debug mode + \param[in] dbg_low_power: + one or more parameters can be selected which are shown as below: + \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \param[out] none + \retval none +*/ +void dbg_low_power_disable(uint32_t dbg_low_power) +{ + DBG_CTL &= ~dbg_low_power; +} + +/*! + \brief enable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_enable(dbg_periph_enum dbg_periph) +{ + DBG_CTL |= (uint32_t)dbg_periph; +} + +/*! + \brief disable peripheral behavior when the mcu is in debug mode + \param[in] dbg_periph: refer to dbg_periph_enum + one or more parameters can be selected which are shown as below: + \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD (x=0,1): hold CAN0 counter when core is halted + \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6): hold TIMERx counter when core is halted + \param[out] none + \retval none +*/ +void dbg_periph_disable(dbg_periph_enum dbg_periph) +{ + DBG_CTL &= ~(uint32_t)dbg_periph; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.h new file mode 100644 index 00000000..9ea6f7e1 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dbg.h @@ -0,0 +1,113 @@ +/*! + \file gd32vf103_dbg.h + \brief definitions for the DBG + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_DBG_H +#define GD32VF103_DBG_H + +#include "gd32vf103.h" + +/* DBG definitions */ +#define DBG DBG_BASE + +/* registers definitions */ +#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ + +/* bits definitions */ +/* DBG_ID */ +#define DBG_ID_ID_CODE BITS(0, 31) /*!< DBG ID code values */ + +/* DBG_CTL */ +#define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ +#define DBG_CTL_DSLP_HOLD BIT(1) /*!< keep debugger connection during deepsleep mode */ +#define DBG_CTL_STB_HOLD BIT(2) /*!< keep debugger connection during standby mode */ +#define DBG_CTL_FWDGT_HOLD BIT(8) /*!< debug FWDGT kept when core is halted */ +#define DBG_CTL_WWDGT_HOLD BIT(9) /*!< debug WWDGT kept when core is halted */ +#define DBG_CTL_TIMER0_HOLD BIT(10) /*!< hold TIMER0 counter when core is halted */ +#define DBG_CTL_TIMER1_HOLD BIT(11) /*!< hold TIMER1 counter when core is halted */ +#define DBG_CTL_TIMER2_HOLD BIT(12) /*!< hold TIMER2 counter when core is halted */ +#define DBG_CTL_TIMER3_HOLD BIT(13) /*!< hold TIMER3 counter when core is halted */ +#define DBG_CTL_CAN0_HOLD BIT(14) /*!< debug CAN0 kept when core is halted */ +#define DBG_CTL_I2C0_HOLD BIT(15) /*!< hold I2C0 smbus when core is halted */ +#define DBG_CTL_I2C1_HOLD BIT(16) /*!< hold I2C1 smbus when core is halted */ +#define DBG_CTL_TIMER4_HOLD BIT(18) /*!< hold TIMER4 counter when core is halted */ +#define DBG_CTL_TIMER5_HOLD BIT(19) /*!< hold TIMER5 counter when core is halted */ +#define DBG_CTL_TIMER6_HOLD BIT(20) /*!< hold TIMER6 counter when core is halted */ +#define DBG_CTL_CAN1_HOLD BIT(21) /*!< debug CAN1 kept when core is halted */ + +/* constants definitions */ +/* debug hold when core is halted */ +typedef enum { + DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER4_HOLD = BIT(17), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = BIT(18), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = BIT(19), /*!< hold TIMER6 counter when core is halted */ + DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ +} dbg_periph_enum; + +/* DBG low power mode configurations */ +#define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ +#define DBG_LOW_POWER_DEEPSLEEP DBG_CTL_DSLP_HOLD /*!< keep debugger connection during deepsleep mode */ +#define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ + +/* function declarations */ +/* read DBG_ID code register */ +uint32_t dbg_id_get(void); + +/* low power behavior configuration */ +/* enable low power behavior when the MCU is in debug mode */ +void dbg_low_power_enable(uint32_t dbg_low_power); +/* disable low power behavior when the MCU is in debug mode */ +void dbg_low_power_disable(uint32_t dbg_low_power); + +/* peripheral behavior configuration */ +/* enable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_enable(dbg_periph_enum dbg_periph); +/* disable peripheral behavior when the MCU is in debug mode */ +void dbg_periph_disable(dbg_periph_enum dbg_periph); + +#endif /* GD32VF103_DBG_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.c new file mode 100644 index 00000000..b06432f6 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.c @@ -0,0 +1,732 @@ +/*! + \file gd32vf103_dma.c + \brief DMA driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-10-30, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_dma.h" + +#define DMA_WRONG_HANDLE while(1){} + +/* check whether peripheral matches channels or not */ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx); + +/*! + \brief deinitialize DMA a channel registers + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is deinitialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* disable DMA a channel */ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; + /* reset DMA channel registers */ + DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE; + DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE; + DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; + DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); +} + +/*! + \brief initialize the parameters of DMA struct with the default values + \param[in] init_struct: the initialization data needed to initialize DMA channel + \param[out] none + \retval none +*/ +void dma_struct_para_init(dma_parameter_struct* init_struct) +{ + /* set the DMA struct with the default values */ + init_struct->periph_addr = 0U; + init_struct->periph_width = 0U; + init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; + init_struct->memory_addr = 0U; + init_struct->memory_width = 0U; + init_struct->memory_inc = DMA_MEMORY_INCREASE_DISABLE; + init_struct->number = 0U; + init_struct->direction = DMA_PERIPHERAL_TO_MEMORY; + init_struct->priority = DMA_PRIORITY_LOW; +} + +/*! + \brief initialize DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel is initialized + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] init_struct: the data needed to initialize DMA channel + periph_addr: peripheral base address + periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + memory_addr: memory base address + memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT + memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE + direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL + number: the number of remaining data to be transferred by the DMA + priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH + \param[out] none + \retval none +*/ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct* init_struct) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* configure peripheral base address */ + DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; + + /* configure memory base address */ + DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; + + /* configure the number of remaining data to be transferred */ + DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); + + /* configure peripheral transfer width,memory transfer width and priority */ + ctl = DMA_CHCTL(dma_periph, channelx); + ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); + ctl |= (init_struct->periph_width | init_struct->memory_width | init_struct->priority); + DMA_CHCTL(dma_periph, channelx) = ctl; + + /* configure peripheral increasing mode */ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; + } + + /* configure memory increasing mode */ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; + }else{ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; + } + + /* configure the direction of data transfer */ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + }else{ + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief enable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CMEN; +} + +/*! + \brief disable DMA circulation mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CMEN; +} + +/*! + \brief enable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_M2M; +} + +/*! + \brief disable memory to memory mode + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_M2M; +} + +/*! + \brief enable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_CHEN; +} + +/*! + \brief disable DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_CHEN; +} + +/*! + \brief set DMA peripheral base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set peripheral base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: peripheral base address + \param[out] none + \retval none +*/ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHPADDR(dma_periph, channelx) = address; +} + +/*! + \brief set DMA memory base address + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set memory base address + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] address: memory base address + \param[out] none + \retval none +*/ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHMADDR(dma_periph, channelx) = address; +} + +/*! + \brief set the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] number: the number of remaining data to be transferred by the DMA + \param[out] none + \retval none +*/ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCNT(dma_periph, channelx) = (number & DMA_CHANNEL_CNT_MASK); +} + +/*! + \brief get the number of remaining data to be transferred by the DMA + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to set number + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval uint32_t: the number of remaining data to be transferred by the DMA +*/ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + return (uint32_t)DMA_CHCNT(dma_periph, channelx); +} + +/*! + \brief configure priority level of DMA channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] priority: priority Level of this channel + only one parameter can be selected which is shown as below: + \arg DMA_PRIORITY_LOW: low priority + \arg DMA_PRIORITY_MEDIUM: medium priority + \arg DMA_PRIORITY_HIGH: high priority + \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority + \param[out] none + \retval none +*/ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PRIO; + ctl |= priority; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] mwidth: transfer data width of memory + only one parameter can be selected which is shown as below: + \arg DMA_MEMORY_WIDTH_8BIT: transfer data width of memory is 8-bit + \arg DMA_MEMORY_WIDTH_16BIT: transfer data width of memory is 16-bit + \arg DMA_MEMORY_WIDTH_32BIT: transfer data width of memory is 32-bit + \param[out] none + \retval none +*/ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_MWIDTH; + ctl |= mwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief configure transfer data size of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] pwidth: transfer data width of peripheral + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_WIDTH_8BIT: transfer data width of peripheral is 8-bit + \arg DMA_PERIPHERAL_WIDTH_16BIT: transfer data width of peripheral is 16-bit + \arg DMA_PERIPHERAL_WIDTH_32BIT: transfer data width of peripheral is 32-bit + \param[out] none + \retval none +*/ +void dma_periph_width_config (uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth) +{ + uint32_t ctl; + + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + /* acquire DMA_CHxCTL register */ + ctl = DMA_CHCTL(dma_periph, channelx); + /* assign regiser */ + ctl &= ~DMA_CHXCTL_PWIDTH; + ctl |= pwidth; + DMA_CHCTL(dma_periph, channelx) = ctl; +} + +/*! + \brief enable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; +} + +/*! + \brief disable next address increasement algorithm of memory + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; +} + +/*! + \brief enable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; +} + +/*! + \brief disable next address increasement algorithm of peripheral + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[out] none + \retval none +*/ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; +} + +/*! + \brief configure the direction of data transfer on the channel + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] direction: specify the direction of data transfer + only one parameter can be selected which is shown as below: + \arg DMA_PERIPHERAL_TO_MEMORY: read from peripheral and write to memory + \arg DMA_MEMORY_TO_PERIPHERAL: read from memory and write to peripheral + \param[out] none + \retval none +*/ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + if(DMA_PERIPHERAL_TO_MEMORY == direction){ + DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; + } else { + DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; + } +} + +/*! + \brief check DMA flag is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + FlagStatus reval; + + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + reval = SET; + }else{ + reval = RESET; + } + + return reval; +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_FLAG_G: global interrupt flag of channel + \arg DMA_FLAG_FTF: full transfer finish flag of channel + \arg DMA_FLAG_HTF: half transfer finish flag of channel + \arg DMA_FLAG_ERR: error flag of channel + \param[out] none + \retval none +*/ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + switch(flag){ + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel + \param[out] none + \retval none +*/ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) +{ + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); +} + +/*! + \brief enable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to enbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) |= source; +} + +/*! + \brief disable DMA interrupt + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..4) + \param[in] source: specify which interrupt to disbale + one or more parameters can be selected which are shown as below + \arg DMA_INT_FTF: channel full transfer finish interrupt + \arg DMA_INT_HTF: channel half transfer finish interrupt + \arg DMA_INT_ERR: channel error interrupt + \param[out] none + \retval none +*/ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source) +{ + if(ERROR == dma_periph_and_channel_check(dma_periph, channelx)){ + DMA_WRONG_HANDLE + } + + DMA_CHCTL(dma_periph, channelx) &= ~source; +} + +/*! + \brief check whether peripheral and channels match + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel + only one parameter can be selected which is shown as below: + \arg DMA_CHx(x=0..6) + \param[out] none + \retval none +*/ +static ErrStatus dma_periph_and_channel_check(uint32_t dma_periph, dma_channel_enum channelx) +{ + ErrStatus val = SUCCESS; + + if(DMA1 == dma_periph){ + /* for DMA1, the channel is from DMA_CH0 to DMA_CH4 */ + if(channelx > DMA_CH4){ + val = ERROR; + } + } + + return val; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.h new file mode 100644 index 00000000..005b6e32 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_dma.h @@ -0,0 +1,287 @@ +/*! + \file gd32vf103_dma.h + \brief definitions for the DMA + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-10-30, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_DMA_H +#define GD32VF103_DMA_H + +#include "gd32vf103.h" + +/* DMA definitions */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ + +/* registers definitions */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ + +/* bits definitions */ +/* DMA_INTF */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ + +/* DMA_INTC */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ + +/* DMA_CHxCTL, x=0..6 */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8, 9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10, 11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12, 13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ + +/* DMA_CHxCNT, x=0..6 */ +#define DMA_CHXCNT_CNT BITS(0, 15) /*!< transfer counter */ + +/* DMA_CHxPADDR, x=0..6 */ +#define DMA_CHXPADDR_PADDR BITS(0, 31) /*!< peripheral base address */ + +/* DMA_CHxMADDR, x=0..6 */ +#define DMA_CHXMADDR_MADDR BITS(0, 31) /*!< memory base address */ + +/* constants definitions */ +/* DMA channel select */ +typedef enum { + DMA_CH0 = 0, /*!< DMA Channel0 */ + DMA_CH1, /*!< DMA Channel1 */ + DMA_CH2, /*!< DMA Channel2 */ + DMA_CH3, /*!< DMA Channel3 */ + DMA_CH4, /*!< DMA Channel4 */ + DMA_CH5, /*!< DMA Channel5 */ + DMA_CH6 /*!< DMA Channel6 */ +} dma_channel_enum; + +/* DMA initialize struct */ +typedef struct +{ + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ + +} dma_parameter_struct; + +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift)*4U)) /*!< DMA channel flag shift */ + +/* DMA_register address */ +#define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ +#define DMA_CHCNT(dma, channel) REG32(((dma) + 0x0CU) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCNT register */ +#define DMA_CHPADDR(dma, channel) REG32(((dma) + 0x10U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXPADDR register */ +#define DMA_CHMADDR(dma, channel) REG32(((dma) + 0x14U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXMADDR register */ + +/* DMA reset value */ +#define DMA_CHCTL_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCTL register */ +#define DMA_CHCNT_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXCNT register */ +#define DMA_CHPADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXPADDR register */ +#define DMA_CHMADDR_RESET_VALUE ((uint32_t)0x00000000U) /*!< the reset value of DMA channel CHXMADDR register */ +#define DMA_CHINTF_RESET_VALUE (DMA_INTF_GIF | DMA_INTF_FTFIF | \ + DMA_INTF_HTFIF | DMA_INTF_ERRIF) /*!< clear DMA channel DMA_INTF register */ + +/* DMA_INTF register */ +/* interrupt flag bits */ +#define DMA_INT_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_INT_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish interrupt flag of channel */ +#define DMA_INT_FLAG_ERR DMA_INTF_ERRIF /*!< error interrupt flag of channel */ + +/* flag bits */ +#define DMA_FLAG_G DMA_INTF_GIF /*!< global interrupt flag of channel */ +#define DMA_FLAG_FTF DMA_INTF_FTFIF /*!< full transfer finish flag of channel */ +#define DMA_FLAG_HTF DMA_INTF_HTFIF /*!< half transfer finish flag of channel */ +#define DMA_FLAG_ERR DMA_INTF_ERRIF /*!< error flag of channel */ + +/* DMA_CHxCTL register */ +/* interrupt enable bits */ +#define DMA_INT_FTF DMA_CHXCTL_FTFIE /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_INT_HTF DMA_CHXCTL_HTFIE /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_INT_ERR DMA_CHXCTL_ERRIE /*!< enable bit for channel error interrupt */ + +/* transfer direction */ +#define DMA_PERIPHERAL_TO_MEMORY ((uint8_t)0x00U) /*!< read from peripheral and write to memory */ +#define DMA_MEMORY_TO_PERIPHERAL ((uint8_t)0x01U) /*!< read from memory and write to peripheral */ + +/* peripheral increasing mode */ +#define DMA_PERIPH_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of peripheral is fixed address mode */ +#define DMA_PERIPH_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of peripheral is increasing address mode */ + +/* memory increasing mode */ +#define DMA_MEMORY_INCREASE_DISABLE ((uint8_t)0x00U) /*!< next address of memory is fixed address mode */ +#define DMA_MEMORY_INCREASE_ENABLE ((uint8_t)0x01U) /*!< next address of memory is increasing address mode */ + +/* transfer data size of peripheral */ +#define CHCTL_PWIDTH(regval) (BITS(8, 9) & ((uint32_t)(regval) << 8)) /*!< transfer data size of peripheral */ +#define DMA_PERIPHERAL_WIDTH_8BIT CHCTL_PWIDTH(0U) /*!< transfer data size of peripheral is 8-bit */ +#define DMA_PERIPHERAL_WIDTH_16BIT CHCTL_PWIDTH(1U) /*!< transfer data size of peripheral is 16-bit */ +#define DMA_PERIPHERAL_WIDTH_32BIT CHCTL_PWIDTH(2U) /*!< transfer data size of peripheral is 32-bit */ + +/* transfer data size of memory */ +#define CHCTL_MWIDTH(regval) (BITS(10, 11) & ((uint32_t)(regval) << 10)) /*!< transfer data size of memory */ +#define DMA_MEMORY_WIDTH_8BIT CHCTL_MWIDTH(0U) /*!< transfer data size of memory is 8-bit */ +#define DMA_MEMORY_WIDTH_16BIT CHCTL_MWIDTH(1U) /*!< transfer data size of memory is 16-bit */ +#define DMA_MEMORY_WIDTH_32BIT CHCTL_MWIDTH(2U) /*!< transfer data size of memory is 32-bit */ + +/* channel priority level */ +#define CHCTL_PRIO(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12)) /*!< DMA channel priority level */ +#define DMA_PRIORITY_LOW CHCTL_PRIO(0U) /*!< low priority */ +#define DMA_PRIORITY_MEDIUM CHCTL_PRIO(1U) /*!< medium priority */ +#define DMA_PRIORITY_HIGH CHCTL_PRIO(2U) /*!< high priority */ +#define DMA_PRIORITY_ULTRA_HIGH CHCTL_PRIO(3U) /*!< ultra high priority */ + +/* memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_DISABLE ((uint32_t)0x00000000U) /*!< disable memory to memory mode */ +#define DMA_MEMORY_TO_MEMORY_ENABLE ((uint32_t)0x00000001U) /*!< enable memory to memory mode */ + +/* DMA_CHxCNT register */ +/* transfer counter */ +#define DMA_CHANNEL_CNT_MASK DMA_CHXCNT_CNT /*!< transfer counter mask */ + +/* function declarations */ +/* DMA deinitialization and initialization functions */ +/* deinitialize DMA a channel registers */ +void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); +/* initialize the parameters of DMA struct with the default values */ +void dma_struct_para_init(dma_parameter_struct *init_struct); +/* initialize DMA channel */ +void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); +/* enable DMA circulation mode */ +void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA circulation mode */ +void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable memory to memory mode */ +void dma_memory_to_memory_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable memory to memory mode */ +void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable DMA channel */ +void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable DMA channel */ +void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx); + +/* DMA configuration functions */ +/* set DMA peripheral base address */ +void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set DMA memory base address */ +void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address); +/* set the number of remaining data to be transferred by the DMA */ +void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number); +/* get the number of remaining data to be transferred by the DMA */ +uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx); +/* configure priority level of DMA channel */ +void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority); +/* configure transfer data size of memory */ +void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t mwidth); +/* configure transfer data size of peripheral */ +void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t pwidth); +/* enable next address increasement algorithm of memory */ +void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of memory */ +void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* enable next address increasement algorithm of peripheral */ +void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx); +/* disable next address increasement algorithm of peripheral */ +void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx); +/* configure the direction of data transfer on the channel */ +void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); + +/* flag and interrupt functions */ +/* check DMA flag is set or not */ +FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the flag of a DMA channel */ +void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* enable DMA interrupt */ +void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); +/* disable DMA interrupt */ +void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); + +#endif /* GD32VF103_DMA_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.c new file mode 100644 index 00000000..39ed4a31 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.c @@ -0,0 +1,121 @@ +/*! + \file gd32vf103_eclic.c + \brief ECLIC(Enhancement Core-Local Interrupt Controller) driver + + \version 2019-06-05, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_eclic.h" +#include "riscv_encoding.h" +extern uint32_t mstatus; +#define REG_DBGMCU2 ((uint32_t)0xE0042008) +#define REG_DBGMCU2EN ((uint32_t)0xE004200C) + +/*! + \brief enable the global interrupt + \param[in] none + \param[out] none + \retval none +*/ +void eclic_global_interrupt_enable(void) { + /* set machine interrupt enable bit */ + set_csr(mstatus, MSTATUS_MIE); +} + +/*! + \brief disable the global interrupt + \param[in] none + \param[out] none + \retval none +*/ +void eclic_global_interrupt_disable(void) { + /* clear machine interrupt enable bit */ + clear_csr(mstatus, MSTATUS_MIE); +} + +/*! + \brief set the priority group + \param[in] prigroup: specify the priority group + \arg ECLIC_PRIGROUP_LEVEL0_PRIO4 + \arg ECLIC_PRIGROUP_LEVEL1_PRIO3 + \arg ECLIC_PRIGROUP_LEVEL2_PRIO2 + \arg ECLIC_PRIGROUP_LEVEL3_PRIO1 + \arg ECLIC_PRIGROUP_LEVEL4_PRIO0 + \param[out] none + \retval none +*/ +void eclic_priority_group_set(uint32_t prigroup) { + eclic_set_nlbits(prigroup); +} + +/*! + \brief enable the interrupt request + \param[in] source: interrupt request, detailed in IRQn_Type + \param[in] level: the level needed to set (maximum is 15, refer to the priority group) + \param[in] priority: the priority needed to set (maximum is 15, refer to the priority group) + \param[out] none + \retval none +*/ +void eclic_irq_enable(uint32_t source, uint8_t level, uint8_t priority) { + eclic_enable_interrupt(source); + eclic_set_irq_lvl_abs(source, level); + eclic_set_irq_priority(source, priority); +} + +/*! + \brief disable the interrupt request + \param[in] source: interrupt request, detailed in IRQn_Type + \param[out] none + \retval none +*/ +void eclic_irq_disable(uint32_t source) { + eclic_disable_interrupt(source); +} + +/*! + \brief reset system + \param[in] none + \param[out] none + \retval none +*/ +void eclic_system_reset(void) { + REG32(REG_DBGMCU2EN) = 0x4b5a6978; + REG32(REG_DBGMCU2) = 0x1; +} + +/*! + \brief send event(SEV) + \param[in] none + \param[out] none + \retval none +*/ +void eclic_send_event(void) { + set_csr(0x812, 0x1); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.h new file mode 100644 index 00000000..9799e5f9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_eclic.h @@ -0,0 +1,71 @@ +/*! + \file gd32vf103_eclic.h + \brief definitions for the ECLIC(Enhancement Core-Local Interrupt Controller) + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_ECLIC_H +#define GD32VF103_ECLIC_H + +#include "gd32vf103.h" + +/* constants definitions */ +#define ECLIC_PRIGROUP_LEVEL0_PRIO4 0 /*!< 0 bits for level 4 bits for priority */ +#define ECLIC_PRIGROUP_LEVEL1_PRIO3 1 /*!< 1 bits for level 3 bits for priority */ +#define ECLIC_PRIGROUP_LEVEL2_PRIO2 2 /*!< 2 bits for level 2 bits for priority */ +#define ECLIC_PRIGROUP_LEVEL3_PRIO1 3 /*!< 3 bits for level 1 bits for priority */ +#define ECLIC_PRIGROUP_LEVEL4_PRIO0 4 /*!< 4 bits for level 0 bits for priority */ + +#define __SEV eclic_send_event + +/* function declarations */ +/* enable the global interrupt */ +void eclic_global_interrupt_enable(void); +/* disable the global interrupt */ +void eclic_global_interrupt_disable(void); +/* set the priority group */ +void eclic_priority_group_set(uint32_t prigroup); +/* enable the interrupt request */ +void eclic_irq_enable(uint32_t source, uint8_t level, uint8_t priority); +/* disable the interrupt request */ +void eclic_irq_disable(uint32_t source); + +/* reset system */ +void eclic_system_reset(void); +/* send event(SEV) */ +void eclic_send_event(void); + +#endif /* GD32VF103_ECLIC_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.c new file mode 100644 index 00000000..ebc5cdfd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.c @@ -0,0 +1,254 @@ +/*! + \file gd32vf103_exti.c + \brief EXTI driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_exti.h" + +#define EXTI_REG_RESET_VALUE ((uint32_t)0x00000000U) + +/*! + \brief deinitialize the EXTI + \param[in] none + \param[out] none + \retval none + */ +void exti_deinit(void) +{ + /* reset the value of all the EXTI registers */ + EXTI_INTEN = EXTI_REG_RESET_VALUE; + EXTI_EVEN = EXTI_REG_RESET_VALUE; + EXTI_RTEN = EXTI_REG_RESET_VALUE; + EXTI_FTEN = EXTI_REG_RESET_VALUE; + EXTI_SWIEV = EXTI_REG_RESET_VALUE; +} + +/*! + \brief initialize the EXTI + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[in] mode: interrupt or event mode, refer to exti_mode_enum + only one parameter can be selected which is shown as below: + \arg EXTI_INTERRUPT: interrupt mode + \arg EXTI_EVENT: event mode + \param[in] trig_type: trigger type, refer to exti_trig_type_enum + only one parameter can be selected which is shown as below: + \arg EXTI_TRIG_RISING: rising edge trigger + \arg EXTI_TRIG_FALLING: falling edge trigger + \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \arg EXTI_TRIG_NONE: without rising edge or falling edge trigger + \param[out] none + \retval none + */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type) +{ + /* reset the EXTI line x */ + EXTI_INTEN &= ~(uint32_t) linex; + EXTI_EVEN &= ~(uint32_t) linex; + EXTI_RTEN &= ~(uint32_t) linex; + EXTI_FTEN &= ~(uint32_t) linex; + + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ + switch (mode) { + case EXTI_INTERRUPT: + EXTI_INTEN |= (uint32_t) linex; + break; + case EXTI_EVENT: + EXTI_EVEN |= (uint32_t) linex; + break; + default: + break; + } + + /* set the EXTI trigger type */ + switch (trig_type) { + case EXTI_TRIG_RISING: + EXTI_RTEN |= (uint32_t) linex; + EXTI_FTEN &= ~(uint32_t) linex; + break; + case EXTI_TRIG_FALLING: + EXTI_RTEN &= ~(uint32_t) linex; + EXTI_FTEN |= (uint32_t) linex; + break; + case EXTI_TRIG_BOTH: + EXTI_RTEN |= (uint32_t) linex; + EXTI_FTEN |= (uint32_t) linex; + break; + case EXTI_TRIG_NONE: + default: + break; + } +} + +/*! + \brief enable the interrupts from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_enable(exti_line_enum linex) +{ + EXTI_INTEN |= (uint32_t) linex; +} + +/*! + \brief enable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_enable(exti_line_enum linex) +{ + EXTI_EVEN |= (uint32_t) linex; +} + +/*! + \brief disable the interrupt from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_disable(exti_line_enum linex) +{ + EXTI_INTEN &= ~(uint32_t) linex; +} + +/*! + \brief disable the events from EXTI line x + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_event_disable(exti_line_enum linex) +{ + EXTI_EVEN &= ~(uint32_t) linex; +} + +/*! + \brief get EXTI lines flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_flag_get(exti_line_enum linex) +{ + if (RESET != (EXTI_PD & (uint32_t) linex)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t) linex; +} + +/*! + \brief get EXTI lines flag when the interrupt flag is set + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval FlagStatus: status of flag (RESET or SET) +*/ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +{ + uint32_t flag_left, flag_right; + + flag_left = EXTI_PD & (uint32_t) linex; + flag_right = EXTI_INTEN & (uint32_t) linex; + + if ((RESET != flag_left) && (RESET != flag_right)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear EXTI lines pending flag + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_interrupt_flag_clear(exti_line_enum linex) +{ + EXTI_PD = (uint32_t) linex; +} + +/*! + \brief enable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_enable(exti_line_enum linex) +{ + EXTI_SWIEV |= (uint32_t) linex; +} + +/*! + \brief disable EXTI software interrupt event + \param[in] linex: EXTI line number, refer to exti_line_enum + only one parameter can be selected which is shown as below: + \arg EXTI_x (x=0..18): EXTI line x + \param[out] none + \retval none +*/ +void exti_software_interrupt_disable(exti_line_enum linex) +{ + EXTI_SWIEV &= ~(uint32_t) linex; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.h new file mode 100644 index 00000000..6e910f8f --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_exti.h @@ -0,0 +1,250 @@ +/*! + \file gd32vf103_exti.h + \brief definitions for the EXTI + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_EXTI_H +#define GD32VF103_EXTI_H + +#include "gd32vf103.h" + +/* EXTI definitions */ +#define EXTI EXTI_BASE + +/* registers definitions */ +#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ + +/* bits definitions */ +/* EXTI_INTEN */ +#define EXTI_INTEN_INTEN0 BIT(0) /*!< interrupt from line 0 */ +#define EXTI_INTEN_INTEN1 BIT(1) /*!< interrupt from line 1 */ +#define EXTI_INTEN_INTEN2 BIT(2) /*!< interrupt from line 2 */ +#define EXTI_INTEN_INTEN3 BIT(3) /*!< interrupt from line 3 */ +#define EXTI_INTEN_INTEN4 BIT(4) /*!< interrupt from line 4 */ +#define EXTI_INTEN_INTEN5 BIT(5) /*!< interrupt from line 5 */ +#define EXTI_INTEN_INTEN6 BIT(6) /*!< interrupt from line 6 */ +#define EXTI_INTEN_INTEN7 BIT(7) /*!< interrupt from line 7 */ +#define EXTI_INTEN_INTEN8 BIT(8) /*!< interrupt from line 8 */ +#define EXTI_INTEN_INTEN9 BIT(9) /*!< interrupt from line 9 */ +#define EXTI_INTEN_INTEN10 BIT(10) /*!< interrupt from line 10 */ +#define EXTI_INTEN_INTEN11 BIT(11) /*!< interrupt from line 11 */ +#define EXTI_INTEN_INTEN12 BIT(12) /*!< interrupt from line 12 */ +#define EXTI_INTEN_INTEN13 BIT(13) /*!< interrupt from line 13 */ +#define EXTI_INTEN_INTEN14 BIT(14) /*!< interrupt from line 14 */ +#define EXTI_INTEN_INTEN15 BIT(15) /*!< interrupt from line 15 */ +#define EXTI_INTEN_INTEN16 BIT(16) /*!< interrupt from line 16 */ +#define EXTI_INTEN_INTEN17 BIT(17) /*!< interrupt from line 17 */ +#define EXTI_INTEN_INTEN18 BIT(18) /*!< interrupt from line 18 */ + +/* EXTI_EVEN */ +#define EXTI_EVEN_EVEN0 BIT(0) /*!< event from line 0 */ +#define EXTI_EVEN_EVEN1 BIT(1) /*!< event from line 1 */ +#define EXTI_EVEN_EVEN2 BIT(2) /*!< event from line 2 */ +#define EXTI_EVEN_EVEN3 BIT(3) /*!< event from line 3 */ +#define EXTI_EVEN_EVEN4 BIT(4) /*!< event from line 4 */ +#define EXTI_EVEN_EVEN5 BIT(5) /*!< event from line 5 */ +#define EXTI_EVEN_EVEN6 BIT(6) /*!< event from line 6 */ +#define EXTI_EVEN_EVEN7 BIT(7) /*!< event from line 7 */ +#define EXTI_EVEN_EVEN8 BIT(8) /*!< event from line 8 */ +#define EXTI_EVEN_EVEN9 BIT(9) /*!< event from line 9 */ +#define EXTI_EVEN_EVEN10 BIT(10) /*!< event from line 10 */ +#define EXTI_EVEN_EVEN11 BIT(11) /*!< event from line 11 */ +#define EXTI_EVEN_EVEN12 BIT(12) /*!< event from line 12 */ +#define EXTI_EVEN_EVEN13 BIT(13) /*!< event from line 13 */ +#define EXTI_EVEN_EVEN14 BIT(14) /*!< event from line 14 */ +#define EXTI_EVEN_EVEN15 BIT(15) /*!< event from line 15 */ +#define EXTI_EVEN_EVEN16 BIT(16) /*!< event from line 16 */ +#define EXTI_EVEN_EVEN17 BIT(17) /*!< event from line 17 */ +#define EXTI_EVEN_EVEN18 BIT(18) /*!< event from line 18 */ + +/* EXTI_RTEN */ +#define EXTI_RTEN_RTEN0 BIT(0) /*!< rising edge from line 0 */ +#define EXTI_RTEN_RTEN1 BIT(1) /*!< rising edge from line 1 */ +#define EXTI_RTEN_RTEN2 BIT(2) /*!< rising edge from line 2 */ +#define EXTI_RTEN_RTEN3 BIT(3) /*!< rising edge from line 3 */ +#define EXTI_RTEN_RTEN4 BIT(4) /*!< rising edge from line 4 */ +#define EXTI_RTEN_RTEN5 BIT(5) /*!< rising edge from line 5 */ +#define EXTI_RTEN_RTEN6 BIT(6) /*!< rising edge from line 6 */ +#define EXTI_RTEN_RTEN7 BIT(7) /*!< rising edge from line 7 */ +#define EXTI_RTEN_RTEN8 BIT(8) /*!< rising edge from line 8 */ +#define EXTI_RTEN_RTEN9 BIT(9) /*!< rising edge from line 9 */ +#define EXTI_RTEN_RTEN10 BIT(10) /*!< rising edge from line 10 */ +#define EXTI_RTEN_RTEN11 BIT(11) /*!< rising edge from line 11 */ +#define EXTI_RTEN_RTEN12 BIT(12) /*!< rising edge from line 12 */ +#define EXTI_RTEN_RTEN13 BIT(13) /*!< rising edge from line 13 */ +#define EXTI_RTEN_RTEN14 BIT(14) /*!< rising edge from line 14 */ +#define EXTI_RTEN_RTEN15 BIT(15) /*!< rising edge from line 15 */ +#define EXTI_RTEN_RTEN16 BIT(16) /*!< rising edge from line 16 */ +#define EXTI_RTEN_RTEN17 BIT(17) /*!< rising edge from line 17 */ +#define EXTI_RTEN_RTEN18 BIT(18) /*!< rising edge from line 18 */ + +/* EXTI_FTEN */ +#define EXTI_FTEN_FTEN0 BIT(0) /*!< falling edge from line 0 */ +#define EXTI_FTEN_FTEN1 BIT(1) /*!< falling edge from line 1 */ +#define EXTI_FTEN_FTEN2 BIT(2) /*!< falling edge from line 2 */ +#define EXTI_FTEN_FTEN3 BIT(3) /*!< falling edge from line 3 */ +#define EXTI_FTEN_FTEN4 BIT(4) /*!< falling edge from line 4 */ +#define EXTI_FTEN_FTEN5 BIT(5) /*!< falling edge from line 5 */ +#define EXTI_FTEN_FTEN6 BIT(6) /*!< falling edge from line 6 */ +#define EXTI_FTEN_FTEN7 BIT(7) /*!< falling edge from line 7 */ +#define EXTI_FTEN_FTEN8 BIT(8) /*!< falling edge from line 8 */ +#define EXTI_FTEN_FTEN9 BIT(9) /*!< falling edge from line 9 */ +#define EXTI_FTEN_FTEN10 BIT(10) /*!< falling edge from line 10 */ +#define EXTI_FTEN_FTEN11 BIT(11) /*!< falling edge from line 11 */ +#define EXTI_FTEN_FTEN12 BIT(12) /*!< falling edge from line 12 */ +#define EXTI_FTEN_FTEN13 BIT(13) /*!< falling edge from line 13 */ +#define EXTI_FTEN_FTEN14 BIT(14) /*!< falling edge from line 14 */ +#define EXTI_FTEN_FTEN15 BIT(15) /*!< falling edge from line 15 */ +#define EXTI_FTEN_FTEN16 BIT(16) /*!< falling edge from line 16 */ +#define EXTI_FTEN_FTEN17 BIT(17) /*!< falling edge from line 17 */ +#define EXTI_FTEN_FTEN18 BIT(18) /*!< falling edge from line 18 */ + +/* EXTI_SWIEV */ +#define EXTI_SWIEV_SWIEV0 BIT(0) /*!< software interrupt/event request from line 0 */ +#define EXTI_SWIEV_SWIEV1 BIT(1) /*!< software interrupt/event request from line 1 */ +#define EXTI_SWIEV_SWIEV2 BIT(2) /*!< software interrupt/event request from line 2 */ +#define EXTI_SWIEV_SWIEV3 BIT(3) /*!< software interrupt/event request from line 3 */ +#define EXTI_SWIEV_SWIEV4 BIT(4) /*!< software interrupt/event request from line 4 */ +#define EXTI_SWIEV_SWIEV5 BIT(5) /*!< software interrupt/event request from line 5 */ +#define EXTI_SWIEV_SWIEV6 BIT(6) /*!< software interrupt/event request from line 6 */ +#define EXTI_SWIEV_SWIEV7 BIT(7) /*!< software interrupt/event request from line 7 */ +#define EXTI_SWIEV_SWIEV8 BIT(8) /*!< software interrupt/event request from line 8 */ +#define EXTI_SWIEV_SWIEV9 BIT(9) /*!< software interrupt/event request from line 9 */ +#define EXTI_SWIEV_SWIEV10 BIT(10) /*!< software interrupt/event request from line 10 */ +#define EXTI_SWIEV_SWIEV11 BIT(11) /*!< software interrupt/event request from line 11 */ +#define EXTI_SWIEV_SWIEV12 BIT(12) /*!< software interrupt/event request from line 12 */ +#define EXTI_SWIEV_SWIEV13 BIT(13) /*!< software interrupt/event request from line 13 */ +#define EXTI_SWIEV_SWIEV14 BIT(14) /*!< software interrupt/event request from line 14 */ +#define EXTI_SWIEV_SWIEV15 BIT(15) /*!< software interrupt/event request from line 15 */ +#define EXTI_SWIEV_SWIEV16 BIT(16) /*!< software interrupt/event request from line 16 */ +#define EXTI_SWIEV_SWIEV17 BIT(17) /*!< software interrupt/event request from line 17 */ +#define EXTI_SWIEV_SWIEV18 BIT(18) /*!< software interrupt/event request from line 18 */ + +/* EXTI_PD */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ + +/* constants definitions */ +/* EXTI line number */ +typedef enum { + EXTI_0 = BIT(0), /*!< EXTI line 0 */ + EXTI_1 = BIT(1), /*!< EXTI line 1 */ + EXTI_2 = BIT(2), /*!< EXTI line 2 */ + EXTI_3 = BIT(3), /*!< EXTI line 3 */ + EXTI_4 = BIT(4), /*!< EXTI line 4 */ + EXTI_5 = BIT(5), /*!< EXTI line 5 */ + EXTI_6 = BIT(6), /*!< EXTI line 6 */ + EXTI_7 = BIT(7), /*!< EXTI line 7 */ + EXTI_8 = BIT(8), /*!< EXTI line 8 */ + EXTI_9 = BIT(9), /*!< EXTI line 9 */ + EXTI_10 = BIT(10), /*!< EXTI line 10 */ + EXTI_11 = BIT(11), /*!< EXTI line 11 */ + EXTI_12 = BIT(12), /*!< EXTI line 12 */ + EXTI_13 = BIT(13), /*!< EXTI line 13 */ + EXTI_14 = BIT(14), /*!< EXTI line 14 */ + EXTI_15 = BIT(15), /*!< EXTI line 15 */ + EXTI_16 = BIT(16), /*!< EXTI line 16 */ + EXTI_17 = BIT(17), /*!< EXTI line 17 */ + EXTI_18 = BIT(18), /*!< EXTI line 18 */ +} exti_line_enum; + +/* external interrupt and event */ +typedef enum { + EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ + EXTI_EVENT /*!< EXTI event mode */ +} exti_mode_enum; + +/* interrupt trigger mode */ +typedef enum { + EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ + EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ + EXTI_TRIG_BOTH, /*!< EXTI rising edge and falling edge trigger */ + EXTI_TRIG_NONE /*!< without rising edge or falling edge trigger */ +} exti_trig_type_enum; + +/* function declarations */ +/* initialization, EXTI lines configuration functions */ +/* deinitialize the EXTI */ +void exti_deinit(void); +/* enable the configuration of EXTI initialize */ +void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); +/* enable the interrupts from EXTI line x */ +void exti_interrupt_enable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); +/* disable the interrupts from EXTI line x */ +void exti_interrupt_disable(exti_line_enum linex); +/* disable the events from EXTI line x */ +void exti_event_disable(exti_line_enum linex); + +/* interrupt & flag functions */ +/* get EXTI lines pending flag */ +FlagStatus exti_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_flag_clear(exti_line_enum linex); +/* get EXTI lines flag when the interrupt flag is set */ +FlagStatus exti_interrupt_flag_get(exti_line_enum linex); +/* clear EXTI lines pending flag */ +void exti_interrupt_flag_clear(exti_line_enum linex); +/* enable the EXTI software interrupt event */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the EXTI software interrupt event */ +void exti_software_interrupt_disable(exti_line_enum linex); + +#endif /* GD32VF103_EXTI_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.c new file mode 100644 index 00000000..fc337e28 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.c @@ -0,0 +1,651 @@ +/*! + \file gd32vf103_fmc.c + \brief FMC driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_fmc.h" + +/*! + \brief set the FMC wait state counter + \param[in] wscntwait state counter value + \arg WS_WSCNT_0: FMC 0 wait state + \arg WS_WSCNT_1: FMC 1 wait state + \arg WS_WSCNT_2: FMC 2 wait state + \param[out] none + \retval none + */ +void fmc_wscnt_set(uint32_t wscnt) +{ + uint32_t reg; + + reg = FMC_WS; + /* set the wait state counter value */ + reg &= ~FMC_WS_WSCNT; + FMC_WS = (reg | wscnt); +} + +/*! + \brief unlock the main FMC operation + \param[in] none + \param[out] none + \retval none + */ +void fmc_unlock(void) +{ + if((RESET != (FMC_CTL & FMC_CTL_LK))){ + /* write the FMC unlock key */ + FMC_KEY = UNLOCK_KEY0; + FMC_KEY = UNLOCK_KEY1; + } +} + +/*! + \brief lock the main FMC operation + \param[in] none + \param[out] none + \retval none + */ +void fmc_lock(void) +{ + /* set the LK bit */ + FMC_CTL |= FMC_CTL_LK; +} + + +/*! + \brief FMC erase page + \param[in] page_address: the page address to be erased. + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum fmc_page_erase(uint32_t page_address) +{ + fmc_state_enum fmc_state; + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* if the last operation is completed, start page erase */ + if (FMC_READY == fmc_state) { + FMC_CTL |= FMC_CTL_PER; + FMC_ADDR = page_address; + FMC_CTL |= FMC_CTL_START; + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PER bit */ + FMC_CTL &= ~FMC_CTL_PER; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief FMC erase whole chip + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum fmc_mass_erase(void) +{ + fmc_state_enum fmc_state; + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* start whole chip erase */ + FMC_CTL |= FMC_CTL_MER; + FMC_CTL |= FMC_CTL_START; + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the MER bit */ + FMC_CTL &= ~FMC_CTL_MER; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief FMC program a word at the corresponding address + \param[in] address: address to program + \param[in] data: word to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL |= FMC_CTL_PG; + REG32(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL &= ~FMC_CTL_PG; + } + /* return the FMC state */ + return fmc_state; +} +/* + \brief FMC program a half word at the corresponding address + \param[in] address: address to program + \param[in] data: halfword to program + \param[out] none + \retval state of FMC, refer to fmc_state_enum +*/ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) +{ + fmc_state_enum fmc_state = FMC_READY; + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the PG bit to start program */ + FMC_CTL |= FMC_CTL_PG; + REG16(address) = data; + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + /* reset the PG bit */ + FMC_CTL &= ~FMC_CTL_PG; + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief unlock the option byte operation + \param[in] none + \param[out] none + \retval none + */ +void ob_unlock(void) +{ + if(RESET == (FMC_CTL & FMC_CTL_OBWEN)){ + /* write the FMC key */ + FMC_OBKEY = UNLOCK_KEY0; + FMC_OBKEY = UNLOCK_KEY1; + } + + /* wait until OBWEN bit is set by hardware */ + while (RESET == (FMC_CTL & FMC_CTL_OBWEN)){ + } +} + +/*! + \brief lock the option byte operation + \param[in] none + \param[out] none + \retval none + */ +void ob_lock(void) +{ + /* reset the OBWEN bit */ + FMC_CTL &= ~FMC_CTL_OBWEN; +} + +/*! + \brief erase the FMC option byte + unlock the FMC_CTL and option byte before calling this function + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum ob_erase(void) +{ + uint16_t temp_spc = FMC_NSPC; + + fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + /* check the option byte security protection value */ + if(RESET != ob_spc_get()){ + temp_spc = FMC_USPC; + } + + if(FMC_READY == fmc_state){ + + /* start erase the option byte */ + FMC_CTL |= FMC_CTL_OBER; + FMC_CTL |= FMC_CTL_START; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL &= ~FMC_CTL_OBER; + /* set the OBPG bit */ + FMC_CTL |= FMC_CTL_OBPG; + /* no security protection */ + OB_SPC = (uint16_t) temp_spc; + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + if (FMC_TOERR != fmc_state) { + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + }else{ + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief enable write protection + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. + one or more parameters can be selected which are shown as below: + \arg OB_WP_x(x = 0..31): write protect specify sector + \arg OB_WP_ALL: write protect all sector + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) +{ + uint16_t temp_wp0, temp_wp1, temp_wp2, temp_wp3; + + fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + ob_wp = (uint32_t) (~ob_wp); + temp_wp0 = (uint16_t) (ob_wp & OB_WP0_WP0); + temp_wp1 = (uint16_t) ((ob_wp & OB_WP1_WP1) >> 8U); + temp_wp2 = (uint16_t) ((ob_wp & OB_WP2_WP2) >> 16U); + temp_wp3 = (uint16_t) ((ob_wp & OB_WP3_WP3) >> 24U); + + if(FMC_READY == fmc_state){ + + /* set the OBPG bit*/ + FMC_CTL |= FMC_CTL_OBPG; + + if(0xFFU != temp_wp0){ + OB_WP0 = temp_wp0; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + OB_WP1 = temp_wp1; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + OB_WP2 = temp_wp2; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + } + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + OB_WP3 = temp_wp3; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + } + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief configure security protection + \param[in] ob_spc: specify security protection + only one parameter can be selected which is shown as below: + \arg FMC_NSPC: no security protection + \arg FMC_USPC: under security protection + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc) +{ + fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + FMC_CTL |= FMC_CTL_OBER; + FMC_CTL |= FMC_CTL_START; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* reset the OBER bit */ + FMC_CTL &= ~FMC_CTL_OBER; + + /* start the option byte program */ + FMC_CTL |= FMC_CTL_OBPG; + + OB_SPC = (uint16_t) ob_spc; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if (FMC_TOERR != fmc_state) { + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + }else{ + if (FMC_TOERR != fmc_state) { + /* reset the OBER bit */ + FMC_CTL &= ~FMC_CTL_OBER; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC user option byte + \param[in] ob_fwdgt: option byte watchdog value + \arg OB_FWDGT_SW: software free watchdog + \arg OB_FWDGT_HW: hardware free watchdog + \param[in] ob_deepsleep: option byte deepsleep reset value + \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \param[in] ob_stdby:option byte standby reset value + \arg OB_STDBY_NRST: no reset when entering standby mode + \arg OB_STDBY_RST: generate a reset instead of entering standby mode + \param[in] ob_boot: specifies the option byte boot bank value + \arg OB_BOOT_B0: boot from bank0 + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot) +{ + fmc_state_enum fmc_state = FMC_READY; + uint8_t temp; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit*/ + FMC_CTL |= FMC_CTL_OBPG; + + temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); + OB_USER = (uint16_t) temp; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief program the FMC data option byte + \param[in] address: the option bytes address to be programmed + \param[in] data: the byte to be programmed + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data) +{ + fmc_state_enum fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state){ + /* set the OBPG bit */ + FMC_CTL |= FMC_CTL_OBPG; + REG16(address) = data; + + /* wait for the FMC ready */ + fmc_state = fmc_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state){ + /* reset the OBPG bit */ + FMC_CTL &= ~FMC_CTL_OBPG; + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief get OB_USER in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval the FMC user option byte values + */ +uint8_t ob_user_get(void) +{ + /* return the FMC user option byte value */ + return (uint8_t) (FMC_OBSTAT >> 2U); +} + +/*! + \brief get OB_DATA in register FMC_OBSTAT + \param[in] none + \param[out] none + \retval ob_data + */ +uint16_t ob_data_get(void) +{ + return (uint16_t) (FMC_OBSTAT >> 10U); +} + +/*! + \brief get the FMC option byte write protection + \param[in] none + \param[out] none + \retval the FMC write protection option byte value + */ +uint32_t ob_write_protection_get(void) +{ + /* return the FMC write protection option byte value */ + return FMC_WP; +} + +/*! + \brief get FMC option byte security protection state + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus ob_spc_get(void) +{ + FlagStatus spc_state = RESET; + + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + spc_state = SET; + }else{ + spc_state = RESET; + } + return spc_state; +} + +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_END: enable FMC end of program interrupt + \arg FMC_INT_ERR: enable FMC error interrupt + \param[out] none + \retval none + */ +void fmc_interrupt_enable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_END: enable FMC end of program interrupt + \arg FMC_INT_ERR: enable FMC error interrupt + \param[out] none + \retval none + */ +void fmc_interrupt_disable(uint32_t interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief check flag is set or not + \param[in] flag: check FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_BUSY: FMC busy flag bit + \arg FMC_FLAG_PGERR: FMC operation error flag bit + \arg FMC_FLAG_WPERR: FMC erase/program protection error flag bit + \arg FMC_FLAG_END: FMC end of operation flag bit + \arg FMC_FLAG_OBERR: FMC option byte read error flag bit + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus fmc_flag_get(uint32_t flag) +{ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear the FMC flag + \param[in] flag: clear FMC flag + only one parameter can be selected which is shown as below: + \arg FMC_FLAG_PGERR: FMC operation error flag bit + \arg FMC_FLAG_WPERR: FMC erase/program protection error flag bit + \arg FMC_FLAG_END: FMC end of operation flag bit + \param[out] none + \retval none + */ +void fmc_flag_clear(uint32_t flag) +{ + FMC_REG_VAL(flag) = (!FMC_REG_VAL(flag)) | BIT(FMC_BIT_POS(flag)); +} + +/*! + \brief get FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag bit + \arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_END: FMC end of operation interrupt flag bit + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) +{ + FlagStatus ret1 = RESET; + FlagStatus ret2 = RESET; + + if(FMC_STAT_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ + /* get the staus of interrupt flag */ + ret1 = (FlagStatus) (FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); + /* get the staus of interrupt enale bit */ + ret2 = (FlagStatus) (FMC_CTL & BIT(FMC_BIT_POS1(flag))); + } + + if(ret1 && ret2){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear FMC interrupt flag state + \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg FMC_INT_FLAG_PGERR: FMC operation error interrupt flag bit + \arg FMC_INT_FLAG_WPERR: FMC erase/program protection error interrupt flag bit + \arg FMC_INT_FLAG_END: FMC end of operation interrupt flag bit + \param[out] none + \retval none + */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +{ + FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); +} + +/*! + \brief get the FMC state + \param[in] none + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum fmc_state_get(void) +{ + fmc_state_enum fmc_state = FMC_READY; + + if((uint32_t) 0x00U != (FMC_STAT & FMC_STAT_BUSY)){ + fmc_state = FMC_BUSY; + }else{ + if((uint32_t) 0x00U != (FMC_STAT & FMC_STAT_WPERR)){ + fmc_state = FMC_WPERR; + }else{ + if((uint32_t) 0x00U != (FMC_STAT & (FMC_STAT_PGERR))){ + fmc_state = FMC_PGERR; + } + } + } + /* return the FMC state */ + return fmc_state; +} + +/*! + \brief check whether FMC is ready or not + \param[in] timeout: count of loop + \param[out] none + \retval state of FMC, refer to fmc_state_enum + */ +fmc_state_enum fmc_ready_wait(uint32_t timeout) +{ + fmc_state_enum fmc_state = FMC_BUSY; + + /* wait for FMC ready */ + do{ + /* get FMC state */ + fmc_state = fmc_state_get(); + timeout--; + }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state){ + fmc_state = FMC_TOERR; + } + /* return the FMC state */ + return fmc_state; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.h new file mode 100644 index 00000000..48e74d1a --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fmc.h @@ -0,0 +1,313 @@ +/*! + \file gd32vf103_fmc.h + \brief definitions for the FMC + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_FMC_H +#define GD32VF103_FMC_H + +#include "gd32vf103.h" + +/* FMC and option byte definition */ +#define FMC FMC_BASE /*!< FMC register base address */ +#define OB OB_BASE /*!< option bytes base address */ + +/* registers definitions */ +#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ +#define FMC_KEY REG32((FMC) + 0x04U) /*!< FMC unlock key register */ +#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT REG32((FMC) + 0x0CU) /*!< FMC status register */ +#define FMC_CTL REG32((FMC) + 0x10U) /*!< FMC control register */ +#define FMC_ADDR REG32((FMC) + 0x14U) /*!< FMC address register */ +#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ +#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ + +/* bits definitions */ +/* FMC_WS */ +#define FMC_WS_WSCNT BITS(0, 2) /*!< wait state counter */ + +/* FMC_KEY */ +#define FMC_KEY_KEY BITS(0, 31) /*!< FMC_CTL unlock key bits */ + +/* FMC_OBKEY */ +#define FMC_OBKEY_OBKEY BITS(0, 31) /*!< option bytes unlock key bits */ + +/* FMC_STAT */ +#define FMC_STAT_BUSY BIT(0) /*!< flash busy flag bit */ +#define FMC_STAT_PGERR BIT(2) /*!< flash program error flag bit */ +#define FMC_STAT_WPERR BIT(4) /*!< erase/program protection error flag bit */ +#define FMC_STAT_ENDF BIT(5) /*!< end of operation flag bit */ + +/* FMC_CTL */ +#define FMC_CTL_PG BIT(0) /*!< main flash program command bit */ +#define FMC_CTL_PER BIT(1) /*!< main flash page erase command bit */ +#define FMC_CTL_MER BIT(2) /*!< main flash mass erase command bit */ +#define FMC_CTL_OBPG BIT(4) /*!< option bytes program command bit */ +#define FMC_CTL_OBER BIT(5) /*!< option bytes erase command bit */ +#define FMC_CTL_START BIT(6) /*!< send erase command to FMC bit */ +#define FMC_CTL_LK BIT(7) /*!< FMC_CTL lock bit */ +#define FMC_CTL_OBWEN BIT(9) /*!< option bytes erase/program enable bit */ +#define FMC_CTL_ERRIE BIT(10) /*!< error interrupt enable bit */ +#define FMC_CTL_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ + +/* FMC_ADDR */ +#define FMC_ADDR0_ADDR BITS(0, 31) /*!< Flash erase/program command address bits */ + +/* FMC_OBSTAT */ +#define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ +#define FMC_OBSTAT_SPC BIT(1) /*!< option bytes security protection code */ +#define FMC_OBSTAT_USER BITS(2, 9) /*!< store USER of option bytes block after system reset */ +#define FMC_OBSTAT_DATA BITS(10, 25) /*!< store DATA of option bytes block after system reset. */ + +/* FMC_WP */ +#define FMC_WP_WP BITS(0, 31) /*!< store WP of option bytes block after system reset */ + +/* FMC_WSEN */ +#define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ + +/* FMC_PID */ +#define FMC_PID_PID BITS(0, 31) /*!< product ID bits */ + +/* constants definitions */ +/* define the FMC bit position and its register index offset */ +#define FMC_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define FMC_REG_VAL(offset) (REG32(FMC + ((uint32_t)(offset) >> 6))) +#define FMC_BIT_POS(val) ((uint32_t)(val)&0x1FU) +#define FMC_REGIDX_BITS(regidx, bitpos0, bitpos1) (((uint32_t)(regidx) << 12) | ((uint32_t)(bitpos0) << 6) | (uint32_t)(bitpos1)) +#define FMC_REG_VALS(offset) (REG32(FMC + ((uint32_t)(offset) >> 12))) +#define FMC_BIT_POS0(val) (((uint32_t)(val) >> 6) & 0x1FU) +#define FMC_BIT_POS1(val) ((uint32_t)(val)&0x1FU) +#define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) + +/* configuration register */ +#define FMC_STAT_REG_OFFSET 0x0CU /*!< status register offset */ +#define FMC_CTL_REG_OFFSET 0x10U /*!< control register offset */ +#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ + +/* fmc state */ +typedef enum { + FMC_READY, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR, /*!< timeout error */ +} fmc_state_enum; + +/* FMC interrupt enable */ +typedef enum { + FMC_INT_END = FMC_REGIDX_BIT(FMC_CTL_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ + FMC_INT_ERR = FMC_REGIDX_BIT(FMC_CTL_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ +} fmc_int_enum; + +/* FMC flags */ +typedef enum { + FMC_FLAG_BUSY = FMC_REGIDX_BIT(FMC_STAT_REG_OFFSET, 0U), /*!< FMC busy flag */ + FMC_FLAG_PGERR = FMC_REGIDX_BIT(FMC_STAT_REG_OFFSET, 2U), /*!< FMC operation error flag bit */ + FMC_FLAG_WPERR = FMC_REGIDX_BIT(FMC_STAT_REG_OFFSET, 4U), /*!< FMC erase/program protection error flag bit */ + FMC_FLAG_END = FMC_REGIDX_BIT(FMC_STAT_REG_OFFSET, 5U), /*!< FMC end of operation flag bit */ + FMC_FLAG_OBERR = FMC_REGIDX_BIT(FMC_OBSTAT_REG_OFFSET, 0U), /*!< FMC option bytes read error flag */ +} fmc_flag_enum; + +/* FMC interrupt flags */ +typedef enum { + FMC_INT_FLAG_PGERR = FMC_REGIDX_BITS(FMC_STAT_REG_OFFSET, 2U, 10U), /*!< FMC operation error interrupt flag bit */ + FMC_INT_FLAG_WPERR = FMC_REGIDX_BITS(FMC_STAT_REG_OFFSET, 4U, 10U), /*!< FMC erase/program protection error interrupt flag bit */ + FMC_INT_FLAG_END = FMC_REGIDX_BITS(FMC_STAT_REG_OFFSET, 5U, 12U), /*!< FMC end of operation interrupt flag bit */ +} fmc_interrupt_flag_enum; + +/* unlock key */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ + +/* FMC wait state counter */ +#define WS_WSCNT(regval) (BITS(0, 2) & ((uint32_t)(regval))) +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ + +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ + +/* option bytes reset or not entering deep sleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ + +/* option bytes reset or not entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ + +/* option bytes boot bank value */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ + +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ + +/* read protect configure */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ + +/* OB_SPC */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ + +/* OB_USER */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ + +/* OB_WP0 */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ + +/* OB_WP1 */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ + +/* OB_WP2 */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ + +/* OB_WP3 */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ + +/* option bytes write protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ + +/* FMC timeout */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ + +/* FMC BANK address */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ +#define SRAM_SIZE (*(uint16_t *)0x1FFFF7E2U) /*!< SRAM size*/ + +/* function declarations */ +/* FMC main memory programming functions */ +/* set the FMC wait state counter */ +void fmc_wscnt_set(uint32_t wscnt); +/* unlock the main FMC operation */ +void fmc_unlock(void); +/* lock the main FMC operation */ +void fmc_lock(void); +/* FMC erase page */ +fmc_state_enum fmc_page_erase(uint32_t page_address); +/* FMC erase whole chip */ +fmc_state_enum fmc_mass_erase(void); +/* FMC program a word at the corresponding address */ +fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); +/* FMC program a half word at the corresponding address */ +fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); + +/* FMC option bytes programming functions */ +/* unlock the option byte operation */ +void ob_unlock(void); +/* lock the option byte operation */ +void ob_lock(void); +/* erase the FMC option byte */ +fmc_state_enum ob_erase(void); +/* enable write protection */ +fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); +/* configure security protection */ +fmc_state_enum ob_security_protection_config(uint8_t ob_spc); +/* program the FMC user option byte */ +fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); +/* program the FMC data option byte */ +fmc_state_enum ob_data_program(uint32_t address, uint8_t data); +/* get OB_USER in register FMC_OBSTAT */ +uint8_t ob_user_get(void); +/* get OB_DATA in register FMC_OBSTAT */ +uint16_t ob_data_get(void); +/* get the FMC option byte write protection */ +uint32_t ob_write_protection_get(void); +/* get FMC option byte security protection state */ +FlagStatus ob_spc_get(void); + +/* FMC interrupts and flags management functions */ +/* enable FMC interrupt */ +void fmc_interrupt_enable(uint32_t interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(uint32_t interrupt); +/* check flag is set or not */ +FlagStatus fmc_flag_get(uint32_t flag); +/* clear the FMC flag */ +void fmc_flag_clear(uint32_t flag); +/* get FMC interrupt flag state */ +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +/* clear FMC interrupt flag state */ +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); +/* return the FMC state */ +fmc_state_enum fmc_state_get(void); +/* check FMC ready or not */ +fmc_state_enum fmc_ready_wait(uint32_t timeout); + +#endif /* GD32VF103_FMC_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.c new file mode 100644 index 00000000..b30b3e5b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.c @@ -0,0 +1,151 @@ +/*! + \file gd32vf103_fwdgt.c + \brief FWDGT driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_fwdgt.h" + +/* write value to FWDGT_CTL_CMD bit field */ +#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_div: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_div; + + timeout = FWDGT_RLD_TIMEOUT; + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status){ + return ERROR; + } + FWDGT_RLD = RLD_RLD(reload_value); + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + + return SUCCESS; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + if(FWDGT_STAT & flag){ + return SET; + } + + return RESET; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.h new file mode 100644 index 00000000..3c041e51 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_fwdgt.h @@ -0,0 +1,109 @@ +/*! + \file gd32vf103_fwdgt.h + \brief definitions for the FWDGT + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_FWDGT_H +#define GD32VF103_FWDGT_H + +#include "gd32vf103.h" + +/* FWDGT definitions */ +#define FWDGT FWDGT_BASE /*!< FWDGT base address */ + +/* registers definitions */ +#define FWDGT_CTL REG32((FWDGT) + 0x00000000U) /*!< FWDGT control register */ +#define FWDGT_PSC REG32((FWDGT) + 0x00000004U) /*!< FWDGT prescaler register */ +#define FWDGT_RLD REG32((FWDGT) + 0x00000008U) /*!< FWDGT reload register */ +#define FWDGT_STAT REG32((FWDGT) + 0x0000000CU) /*!< FWDGT status register */ + +/* bits definitions */ +/* FWDGT_CTL */ +#define FWDGT_CTL_CMD BITS(0, 15) /*!< FWDGT command value */ + +/* FWDGT_PSC */ +#define FWDGT_PSC_PSC BITS(0, 2) /*!< FWDGT prescaler divider value */ + +/* FWDGT_RLD */ +#define FWDGT_RLD_RLD BITS(0, 11) /*!< FWDGT counter reload value */ + +/* FWDGT_STAT */ +#define FWDGT_STAT_PUD BIT(0) /*!< FWDGT prescaler divider value update */ +#define FWDGT_STAT_RUD BIT(1) /*!< FWDGT counter reload value update */ + +/* constants definitions */ +/* psc register value */ +#define PSC_PSC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0)) +#define FWDGT_PSC_DIV4 ((uint8_t)PSC_PSC(0)) /*!< FWDGT prescaler set to 4 */ +#define FWDGT_PSC_DIV8 ((uint8_t)PSC_PSC(1)) /*!< FWDGT prescaler set to 8 */ +#define FWDGT_PSC_DIV16 ((uint8_t)PSC_PSC(2)) /*!< FWDGT prescaler set to 16 */ +#define FWDGT_PSC_DIV32 ((uint8_t)PSC_PSC(3)) /*!< FWDGT prescaler set to 32 */ +#define FWDGT_PSC_DIV64 ((uint8_t)PSC_PSC(4)) /*!< FWDGT prescaler set to 64 */ +#define FWDGT_PSC_DIV128 ((uint8_t)PSC_PSC(5)) /*!< FWDGT prescaler set to 128 */ +#define FWDGT_PSC_DIV256 ((uint8_t)PSC_PSC(6)) /*!< FWDGT prescaler set to 256 */ + +/* control value */ +#define FWDGT_WRITEACCESS_ENABLE ((uint16_t)0x5555U) /*!< FWDGT_CTL bits write access enable value */ +#define FWDGT_WRITEACCESS_DISABLE ((uint16_t)0x0000U) /*!< FWDGT_CTL bits write access disable value */ +#define FWDGT_KEY_RELOAD ((uint16_t)0xAAAAU) /*!< FWDGT_CTL bits fwdgt counter reload value */ +#define FWDGT_KEY_ENABLE ((uint16_t)0xCCCCU) /*!< FWDGT_CTL bits fwdgt counter enable value */ + +/* FWDGT timeout value */ +#define FWDGT_PSC_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_PSC register write operation state flag timeout */ +#define FWDGT_RLD_TIMEOUT ((uint32_t)0x000FFFFFU) /*!< FWDGT_RLD register write operation state flag timeout */ + +/* FWDGT flag definitions */ +#define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ +#define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ + +/* function declarations */ +/* enable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_enable(void); +/* disable write access to FWDGT_PSC and FWDGT_RLD */ +void fwdgt_write_disable(void); +/* start the free watchdog timer counter */ +void fwdgt_enable(void); + +/* reload the counter of FWDGT */ +void fwdgt_counter_reload(void); +/* configure counter reload value, and prescaler divider value */ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); + +/* get flag state of FWDGT */ +FlagStatus fwdgt_flag_get(uint16_t flag); + +#endif /* GD32VF103_FWDGT_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.c new file mode 100644 index 00000000..05f482bd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.c @@ -0,0 +1,502 @@ +/*! + \file gd32vf103_gpio.c + \brief GPIO driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_gpio.h" + +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ +#define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ +#define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ +#define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ +#define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ +#define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/ + +/*! + \brief reset GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[out] none + \retval none +*/ +void gpio_deinit(uint32_t gpio_periph) +{ + switch (gpio_periph) { + case GPIOA: + /* reset GPIOA */ + rcu_periph_reset_enable(RCU_GPIOARST); + rcu_periph_reset_disable(RCU_GPIOARST); + break; + case GPIOB: + /* reset GPIOB */ + rcu_periph_reset_enable(RCU_GPIOBRST); + rcu_periph_reset_disable(RCU_GPIOBRST); + break; + case GPIOC: + /* reset GPIOC */ + rcu_periph_reset_enable(RCU_GPIOCRST); + rcu_periph_reset_disable(RCU_GPIOCRST); + break; + case GPIOD: + /* reset GPIOD */ + rcu_periph_reset_enable(RCU_GPIODRST); + rcu_periph_reset_disable(RCU_GPIODRST); + break; + case GPIOE: + /* reset GPIOE */ + rcu_periph_reset_enable(RCU_GPIOERST); + rcu_periph_reset_disable(RCU_GPIOERST); + break; + default: + break; + } +} + +/*! + \brief reset alternate function I/O(AFIO) + \param[in] none + \param[out] none + \retval none +*/ +void gpio_afio_deinit(void) +{ + rcu_periph_reset_enable(RCU_AFRST); + rcu_periph_reset_disable(RCU_AFRST); +} + +/*! + \brief GPIO parameter initialization + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] mode: gpio pin mode + only one parameter can be selected which is shown as below: + \arg GPIO_MODE_AIN: analog input mode + \arg GPIO_MODE_IN_FLOATING: floating input mode + \arg GPIO_MODE_IPD: pull-down input mode + \arg GPIO_MODE_IPU: pull-up input mode + \arg GPIO_MODE_OUT_OD: GPIO output with open-drain + \arg GPIO_MODE_OUT_PP: GPIO output with push-pull + \arg GPIO_MODE_AF_OD: AFIO output with open-drain + \arg GPIO_MODE_AF_PP: AFIO output with push-pull + \param[in] speed: gpio output max speed value + only one parameter can be selected which is shown as below: + \arg GPIO_OSPEED_10MHZ: output max speed 10MHz + \arg GPIO_OSPEED_2MHZ: output max speed 2MHz + \arg GPIO_OSPEED_50MHZ: output max speed 50MHz + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + + \param[out] none + \retval none +*/ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, + uint32_t pin) +{ + uint16_t i; + uint32_t temp_mode = 0U; + uint32_t reg = 0U; + + /* GPIO mode configuration */ + temp_mode = (uint32_t) (mode & ((uint32_t) 0x0FU)); + + /* GPIO speed configuration */ + if (((uint32_t) 0x00U) != ((uint32_t) mode & ((uint32_t) 0x10U))) { + /* output mode max speed:10MHz,2MHz,50MHz */ + temp_mode |= (uint32_t) speed; + } + + /* configure the eight low port pins with GPIO_CTL0 */ + for (i = 0U; i < 8U; i++) { + if ((1U << i) & pin) { + reg = GPIO_CTL0(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i, temp_mode); + + /* set IPD or IPU */ + if (GPIO_MODE_IPD == mode) { + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin); + } else { + /* set the corresponding OCTL bit */ + if (GPIO_MODE_IPU == mode) { + GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } + } + /* configure the eight high port pins with GPIO_CTL1 */ + for (i = 8U; i < 16U; i++) { + if ((1U << i) & pin) { + reg = GPIO_CTL1(gpio_periph); + + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(i - 8U); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(i - 8U, temp_mode); + + /* set IPD or IPU */ + if (GPIO_MODE_IPD == mode) { + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin); + } else { + /* set the corresponding OCTL bit */ + if (GPIO_MODE_IPU == mode) { + GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } + } +} + +/*! + \brief set GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BOP(gpio_periph) = (uint32_t) pin; +} + +/*! + \brief reset GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) +{ + GPIO_BC(gpio_periph) = (uint32_t) pin; +} + +/*! + \brief write data to the specified GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[in] bit_value: SET or RESET + only one parameter can be selected which is shown as below: + \arg RESET: clear the port pin + \arg SET: set the port pin + \param[out] none + \retval none +*/ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) +{ + if (RESET != bit_value) { + GPIO_BOP(gpio_periph) = (uint32_t) pin; + } else { + GPIO_BC(gpio_periph) = (uint32_t) pin; + } +} + +/*! + \brief write data to the specified GPIO port + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] data: specify the value to be written to the port output data register + \param[out] none + \retval none +*/ +void gpio_port_write(uint32_t gpio_periph, uint16_t data) +{ + GPIO_OCTL(gpio_periph) = (uint32_t) data; +} + +/*! + \brief get GPIO pin input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval input status of gpio pin: SET or RESET +*/ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin) +{ + if ((uint32_t) RESET != (GPIO_ISTAT(gpio_periph) & (pin))) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief get GPIO port input status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[out] none + \retval input status of gpio all pins +*/ +uint16_t gpio_input_port_get(uint32_t gpio_periph) +{ + return (uint16_t) (GPIO_ISTAT(gpio_periph)); +} + +/*! + \brief get GPIO pin output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval output status of gpio pin: SET or RESET +*/ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) +{ + if ((uint32_t) RESET != (GPIO_OCTL(gpio_periph) & (pin))) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief get GPIO port output status + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[out] none + \retval output status of gpio all pins +*/ +uint16_t gpio_output_port_get(uint32_t gpio_periph) +{ + return ((uint16_t) GPIO_OCTL(gpio_periph)); +} + +/*! + \brief configure GPIO pin remap + \param[in] gpio_remap: select the pin to remap + only one parameter can be selected which are shown as below: + \arg GPIO_SPI0_REMAP: SPI0 remapping + \arg GPIO_I2C0_REMAP: I2C0 remapping + \arg GPIO_USART0_REMAP: USART0 remapping + \arg GPIO_USART1_REMAP: USART1 remapping + \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping + \arg GPIO_USART2_FULL_REMAP: USART2 full remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping + \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping + \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping + \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping + \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping + \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping + \arg GPIO_TIMER3_REMAP: TIMER3 remapping + \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping + \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping + \arg GPIO_PD01_REMAP: PD01 remapping + \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping + \arg GPIO_CAN1_REMAP: CAN1 remapping + \arg GPIO_SWJ_NONJTRST_REMAP: JTAG-DP,but without NJTRST + \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled + \arg GPIO_SPI2_REMAP: SPI2 remapping + \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping + \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) +{ + uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; + + if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) { + /* get AFIO_PCF1 regiter value */ + temp_reg = AFIO_PCF1; + } else { + /* get AFIO_PCF0 regiter value */ + temp_reg = AFIO_PCF0; + } + + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; + + /* judge pin remap type */ + if ((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) + == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))) { + temp_reg &= PCF_SWJCFG_MASK; + AFIO_PCF0 &= PCF_SWJCFG_MASK; + } else if (PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)) { + remap2 = ((uint32_t) 0x03U) << temp_mask; + temp_reg &= ~remap2; + temp_reg |= ~PCF_SWJCFG_MASK; + } else { + temp_reg &= ~(remap1 << ((remap >> 0x15U) * 0x10U)); + temp_reg |= ~PCF_SWJCFG_MASK; + } + + /* set pin remap value */ + if (DISABLE != newvalue) { + temp_reg |= (remap1 << ((remap >> 0x15U) * 0x10U)); + } + + if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) { + /* set AFIO_PCF1 regiter value */ + AFIO_PCF1 = temp_reg; + } else { + /* set AFIO_PCF0 regiter value */ + AFIO_PCF0 = temp_reg; + } +} + +/*! + \brief select GPIO pin exti sources + \param[in] gpio_outputport: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_PORT_SOURCE_GPIOA: output port source A + \arg GPIO_PORT_SOURCE_GPIOB: output port source B + \arg GPIO_PORT_SOURCE_GPIOC: output port source C + \arg GPIO_PORT_SOURCE_GPIOD: output port source D + \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \param[in] gpio_outputpin: GPIO_PIN_SOURCE_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) +{ + uint32_t source = 0U; + source = ((uint32_t) 0x0FU) + << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); + + /* select EXTI sources */ + if (GPIO_PIN_SOURCE_4 > output_pin) { + /* select EXTI0/EXTI1/EXTI2/EXTI3 */ + AFIO_EXTISS0 &= ~source; + AFIO_EXTISS0 |= (((uint32_t) output_port) + << (AFIO_EXTI_SOURCE_FIELDS + * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } else if (GPIO_PIN_SOURCE_8 > output_pin) { + /* select EXTI4/EXTI5/EXTI6/EXTI7 */ + AFIO_EXTISS1 &= ~source; + AFIO_EXTISS1 |= (((uint32_t) output_port) + << (AFIO_EXTI_SOURCE_FIELDS + * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } else if (GPIO_PIN_SOURCE_12 > output_pin) { + /* select EXTI8/EXTI9/EXTI10/EXTI11 */ + AFIO_EXTISS2 &= ~source; + AFIO_EXTISS2 |= (((uint32_t) output_port) + << (AFIO_EXTI_SOURCE_FIELDS + * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } else { + /* select EXTI12/EXTI13/EXTI14/EXTI15 */ + AFIO_EXTISS3 &= ~source; + AFIO_EXTISS3 |= (((uint32_t) output_port) + << (AFIO_EXTI_SOURCE_FIELDS + * (output_pin & AFIO_EXTI_SOURCE_MASK))); + } +} + +/*! + \brief configure GPIO pin event output + \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PORT_GPIOA: event output port A + \arg GPIO_EVENT_PORT_GPIOB: event output port B + \arg GPIO_EVENT_PORT_GPIOC: event output port C + \arg GPIO_EVENT_PORT_GPIOD: event output port D + \arg GPIO_EVENT_PORT_GPIOE: event output port E + \param[in] output_pin: + only one parameter can be selected which are shown as below: + \arg GPIO_EVENT_PIN_x(x=0..15) + \param[out] none + \retval none +*/ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) +{ + uint32_t reg = 0U; + reg = AFIO_EC; + + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ + reg &= (uint32_t) (~(AFIO_EC_PORT | AFIO_EC_PIN)); + + reg |= (uint32_t) ((uint32_t) output_port << GPIO_OUTPUT_PORT_OFFSET); + reg |= (uint32_t) output_pin; + + AFIO_EC = reg; +} + +/*! + \brief enable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_enable(void) +{ + AFIO_EC |= AFIO_EC_EOE; +} + +/*! + \brief disable GPIO pin event output + \param[in] none + \param[out] none + \retval none +*/ +void gpio_event_output_disable(void) +{ + AFIO_EC &= (uint32_t) (~AFIO_EC_EOE); +} + +/*! + \brief lock GPIO pin + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E) + \param[in] pin: GPIO pin + one or more parameters can be selected which are shown as below: + \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL + \param[out] none + \retval none +*/ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) +{ + uint32_t lock = 0x00010000U; + lock |= pin; + + /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */ + GPIO_LOCK(gpio_periph) = (uint32_t) lock; + GPIO_LOCK(gpio_periph) = (uint32_t) pin; + GPIO_LOCK(gpio_periph) = (uint32_t) lock; + lock = GPIO_LOCK(gpio_periph); + lock = GPIO_LOCK(gpio_periph); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.h new file mode 100644 index 00000000..6106e33f --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_gpio.h @@ -0,0 +1,426 @@ +/*! + \file gd32vf103_gpio.h + \brief definitions for the GPIO + + \version 2019-06-5, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_GPIO_H +#define GD32VF103_GPIO_H + +#include "gd32vf103.h" + +/* GPIOx(x=A,B,C,D,E) definitions */ +#define GPIOA (GPIO_BASE + 0x00000000U) +#define GPIOB (GPIO_BASE + 0x00000400U) +#define GPIOC (GPIO_BASE + 0x00000800U) +#define GPIOD (GPIO_BASE + 0x00000C00U) +#define GPIOE (GPIO_BASE + 0x00001000U) + +/* AFIO definitions */ +#define AFIO AFIO_BASE + +/* registers definitions */ + +/* GPIO registers definitions */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ + +/* AFIO registers definitions */ +#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ + +/* bits definitions */ +/* GPIO_CTL0 */ +#define GPIO_CTL0_MD0 BITS(0, 1) /*!< port 0 mode bits */ +#define GPIO_CTL0_CTL0 BITS(2, 3) /*!< pin 0 configuration bits */ +#define GPIO_CTL0_MD1 BITS(4, 5) /*!< port 1 mode bits */ +#define GPIO_CTL0_CTL1 BITS(6, 7) /*!< pin 1 configuration bits */ +#define GPIO_CTL0_MD2 BITS(8, 9) /*!< port 2 mode bits */ +#define GPIO_CTL0_CTL2 BITS(10, 11) /*!< pin 2 configuration bits */ +#define GPIO_CTL0_MD3 BITS(12, 13) /*!< port 3 mode bits */ +#define GPIO_CTL0_CTL3 BITS(14, 15) /*!< pin 3 configuration bits */ +#define GPIO_CTL0_MD4 BITS(16, 17) /*!< port 4 mode bits */ +#define GPIO_CTL0_CTL4 BITS(18, 19) /*!< pin 4 configuration bits */ +#define GPIO_CTL0_MD5 BITS(20, 21) /*!< port 5 mode bits */ +#define GPIO_CTL0_CTL5 BITS(22, 23) /*!< pin 5 configuration bits */ +#define GPIO_CTL0_MD6 BITS(24, 25) /*!< port 6 mode bits */ +#define GPIO_CTL0_CTL6 BITS(26, 27) /*!< pin 6 configuration bits */ +#define GPIO_CTL0_MD7 BITS(28, 29) /*!< port 7 mode bits */ +#define GPIO_CTL0_CTL7 BITS(30, 31) /*!< pin 7 configuration bits */ + +/* GPIO_CTL1 */ +#define GPIO_CTL1_MD8 BITS(0, 1) /*!< port 8 mode bits */ +#define GPIO_CTL1_CTL8 BITS(2, 3) /*!< pin 8 configuration bits */ +#define GPIO_CTL1_MD9 BITS(4, 5) /*!< port 9 mode bits */ +#define GPIO_CTL1_CTL9 BITS(6, 7) /*!< pin 9 configuration bits */ +#define GPIO_CTL1_MD10 BITS(8, 9) /*!< port 10 mode bits */ +#define GPIO_CTL1_CTL10 BITS(10, 11) /*!< pin 10 configuration bits */ +#define GPIO_CTL1_MD11 BITS(12, 13) /*!< port 11 mode bits */ +#define GPIO_CTL1_CTL11 BITS(14, 15) /*!< pin 11 configuration bits */ +#define GPIO_CTL1_MD12 BITS(16, 17) /*!< port 12 mode bits */ +#define GPIO_CTL1_CTL12 BITS(18, 19) /*!< pin 12 configuration bits */ +#define GPIO_CTL1_MD13 BITS(20, 21) /*!< port 13 mode bits */ +#define GPIO_CTL1_CTL13 BITS(22, 23) /*!< pin 13 configuration bits */ +#define GPIO_CTL1_MD14 BITS(24, 25) /*!< port 14 mode bits */ +#define GPIO_CTL1_CTL14 BITS(26, 27) /*!< pin 14 configuration bits */ +#define GPIO_CTL1_MD15 BITS(28, 29) /*!< port 15 mode bits */ +#define GPIO_CTL1_CTL15 BITS(30, 31) /*!< pin 15 configuration bits */ + +/* GPIO_ISTAT */ +#define GPIO_ISTAT_ISTAT0 BIT(0) /*!< pin 0 input status */ +#define GPIO_ISTAT_ISTAT1 BIT(1) /*!< pin 1 input status */ +#define GPIO_ISTAT_ISTAT2 BIT(2) /*!< pin 2 input status */ +#define GPIO_ISTAT_ISTAT3 BIT(3) /*!< pin 3 input status */ +#define GPIO_ISTAT_ISTAT4 BIT(4) /*!< pin 4 input status */ +#define GPIO_ISTAT_ISTAT5 BIT(5) /*!< pin 5 input status */ +#define GPIO_ISTAT_ISTAT6 BIT(6) /*!< pin 6 input status */ +#define GPIO_ISTAT_ISTAT7 BIT(7) /*!< pin 7 input status */ +#define GPIO_ISTAT_ISTAT8 BIT(8) /*!< pin 8 input status */ +#define GPIO_ISTAT_ISTAT9 BIT(9) /*!< pin 9 input status */ +#define GPIO_ISTAT_ISTAT10 BIT(10) /*!< pin 10 input status */ +#define GPIO_ISTAT_ISTAT11 BIT(11) /*!< pin 11 input status */ +#define GPIO_ISTAT_ISTAT12 BIT(12) /*!< pin 12 input status */ +#define GPIO_ISTAT_ISTAT13 BIT(13) /*!< pin 13 input status */ +#define GPIO_ISTAT_ISTAT14 BIT(14) /*!< pin 14 input status */ +#define GPIO_ISTAT_ISTAT15 BIT(15) /*!< pin 15 input status */ + +/* GPIO_OCTL */ +#define GPIO_OCTL_OCTL0 BIT(0) /*!< pin 0 output bit */ +#define GPIO_OCTL_OCTL1 BIT(1) /*!< pin 1 output bit */ +#define GPIO_OCTL_OCTL2 BIT(2) /*!< pin 2 output bit */ +#define GPIO_OCTL_OCTL3 BIT(3) /*!< pin 3 output bit */ +#define GPIO_OCTL_OCTL4 BIT(4) /*!< pin 4 output bit */ +#define GPIO_OCTL_OCTL5 BIT(5) /*!< pin 5 output bit */ +#define GPIO_OCTL_OCTL6 BIT(6) /*!< pin 6 output bit */ +#define GPIO_OCTL_OCTL7 BIT(7) /*!< pin 7 output bit */ +#define GPIO_OCTL_OCTL8 BIT(8) /*!< pin 8 output bit */ +#define GPIO_OCTL_OCTL9 BIT(9) /*!< pin 9 output bit */ +#define GPIO_OCTL_OCTL10 BIT(10) /*!< pin 10 output bit */ +#define GPIO_OCTL_OCTL11 BIT(11) /*!< pin 11 output bit */ +#define GPIO_OCTL_OCTL12 BIT(12) /*!< pin 12 output bit */ +#define GPIO_OCTL_OCTL13 BIT(13) /*!< pin 13 output bit */ +#define GPIO_OCTL_OCTL14 BIT(14) /*!< pin 14 output bit */ +#define GPIO_OCTL_OCTL15 BIT(15) /*!< pin 15 output bit */ + +/* GPIO_BOP */ +#define GPIO_BOP_BOP0 BIT(0) /*!< pin 0 set bit */ +#define GPIO_BOP_BOP1 BIT(1) /*!< pin 1 set bit */ +#define GPIO_BOP_BOP2 BIT(2) /*!< pin 2 set bit */ +#define GPIO_BOP_BOP3 BIT(3) /*!< pin 3 set bit */ +#define GPIO_BOP_BOP4 BIT(4) /*!< pin 4 set bit */ +#define GPIO_BOP_BOP5 BIT(5) /*!< pin 5 set bit */ +#define GPIO_BOP_BOP6 BIT(6) /*!< pin 6 set bit */ +#define GPIO_BOP_BOP7 BIT(7) /*!< pin 7 set bit */ +#define GPIO_BOP_BOP8 BIT(8) /*!< pin 8 set bit */ +#define GPIO_BOP_BOP9 BIT(9) /*!< pin 9 set bit */ +#define GPIO_BOP_BOP10 BIT(10) /*!< pin 10 set bit */ +#define GPIO_BOP_BOP11 BIT(11) /*!< pin 11 set bit */ +#define GPIO_BOP_BOP12 BIT(12) /*!< pin 12 set bit */ +#define GPIO_BOP_BOP13 BIT(13) /*!< pin 13 set bit */ +#define GPIO_BOP_BOP14 BIT(14) /*!< pin 14 set bit */ +#define GPIO_BOP_BOP15 BIT(15) /*!< pin 15 set bit */ +#define GPIO_BOP_CR0 BIT(16) /*!< pin 0 clear bit */ +#define GPIO_BOP_CR1 BIT(17) /*!< pin 1 clear bit */ +#define GPIO_BOP_CR2 BIT(18) /*!< pin 2 clear bit */ +#define GPIO_BOP_CR3 BIT(19) /*!< pin 3 clear bit */ +#define GPIO_BOP_CR4 BIT(20) /*!< pin 4 clear bit */ +#define GPIO_BOP_CR5 BIT(21) /*!< pin 5 clear bit */ +#define GPIO_BOP_CR6 BIT(22) /*!< pin 6 clear bit */ +#define GPIO_BOP_CR7 BIT(23) /*!< pin 7 clear bit */ +#define GPIO_BOP_CR8 BIT(24) /*!< pin 8 clear bit */ +#define GPIO_BOP_CR9 BIT(25) /*!< pin 9 clear bit */ +#define GPIO_BOP_CR10 BIT(26) /*!< pin 10 clear bit */ +#define GPIO_BOP_CR11 BIT(27) /*!< pin 11 clear bit */ +#define GPIO_BOP_CR12 BIT(28) /*!< pin 12 clear bit */ +#define GPIO_BOP_CR13 BIT(29) /*!< pin 13 clear bit */ +#define GPIO_BOP_CR14 BIT(30) /*!< pin 14 clear bit */ +#define GPIO_BOP_CR15 BIT(31) /*!< pin 15 clear bit */ + +/* GPIO_BC */ +#define GPIO_BC_CR0 BIT(0) /*!< pin 0 clear bit */ +#define GPIO_BC_CR1 BIT(1) /*!< pin 1 clear bit */ +#define GPIO_BC_CR2 BIT(2) /*!< pin 2 clear bit */ +#define GPIO_BC_CR3 BIT(3) /*!< pin 3 clear bit */ +#define GPIO_BC_CR4 BIT(4) /*!< pin 4 clear bit */ +#define GPIO_BC_CR5 BIT(5) /*!< pin 5 clear bit */ +#define GPIO_BC_CR6 BIT(6) /*!< pin 6 clear bit */ +#define GPIO_BC_CR7 BIT(7) /*!< pin 7 clear bit */ +#define GPIO_BC_CR8 BIT(8) /*!< pin 8 clear bit */ +#define GPIO_BC_CR9 BIT(9) /*!< pin 9 clear bit */ +#define GPIO_BC_CR10 BIT(10) /*!< pin 10 clear bit */ +#define GPIO_BC_CR11 BIT(11) /*!< pin 11 clear bit */ +#define GPIO_BC_CR12 BIT(12) /*!< pin 12 clear bit */ +#define GPIO_BC_CR13 BIT(13) /*!< pin 13 clear bit */ +#define GPIO_BC_CR14 BIT(14) /*!< pin 14 clear bit */ +#define GPIO_BC_CR15 BIT(15) /*!< pin 15 clear bit */ + +/* GPIO_LOCK */ +#define GPIO_LOCK_LK0 BIT(0) /*!< pin 0 lock bit */ +#define GPIO_LOCK_LK1 BIT(1) /*!< pin 1 lock bit */ +#define GPIO_LOCK_LK2 BIT(2) /*!< pin 2 lock bit */ +#define GPIO_LOCK_LK3 BIT(3) /*!< pin 3 lock bit */ +#define GPIO_LOCK_LK4 BIT(4) /*!< pin 4 lock bit */ +#define GPIO_LOCK_LK5 BIT(5) /*!< pin 5 lock bit */ +#define GPIO_LOCK_LK6 BIT(6) /*!< pin 6 lock bit */ +#define GPIO_LOCK_LK7 BIT(7) /*!< pin 7 lock bit */ +#define GPIO_LOCK_LK8 BIT(8) /*!< pin 8 lock bit */ +#define GPIO_LOCK_LK9 BIT(9) /*!< pin 9 lock bit */ +#define GPIO_LOCK_LK10 BIT(10) /*!< pin 10 lock bit */ +#define GPIO_LOCK_LK11 BIT(11) /*!< pin 11 lock bit */ +#define GPIO_LOCK_LK12 BIT(12) /*!< pin 12 lock bit */ +#define GPIO_LOCK_LK13 BIT(13) /*!< pin 13 lock bit */ +#define GPIO_LOCK_LK14 BIT(14) /*!< pin 14 lock bit */ +#define GPIO_LOCK_LK15 BIT(15) /*!< pin 15 lock bit */ +#define GPIO_LOCK_LKK BIT(16) /*!< pin sequence lock key */ + +/* AFIO_EC */ +#define AFIO_EC_PIN BITS(0, 3) /*!< event output pin selection */ +#define AFIO_EC_PORT BITS(4, 6) /*!< event output port selection */ +#define AFIO_EC_EOE BIT(7) /*!< event output enable */ + +/* AFIO_PCF0 */ +#define AFIO_PCF0_SPI0_REMAP BIT(0) /*!< SPI0 remapping */ +#define AFIO_PCF0_I2C0_REMAP BIT(1) /*!< I2C0 remapping */ +#define AFIO_PCF0_USART0_REMAP BIT(2) /*!< USART0 remapping */ +#define AFIO_PCF0_USART1_REMAP BIT(3) /*!< USART1 remapping */ +#define AFIO_PCF0_USART2_REMAP BITS(4, 5) /*!< USART2 remapping */ +#define AFIO_PCF0_TIMER0_REMAP BITS(6, 7) /*!< TIMER0 remapping */ +#define AFIO_PCF0_TIMER1_REMAP BITS(8, 9) /*!< TIMER1 remapping */ +#define AFIO_PCF0_TIMER2_REMAP BITS(10, 11) /*!< TIMER2 remapping */ +#define AFIO_PCF0_TIMER3_REMAP BIT(12) /*!< TIMER3 remapping */ +#define AFIO_PCF0_CAN_REMAP BITS(13, 14) /*!< CAN remapping */ +#define AFIO_PCF0_PD01_REMAP BIT(15) /*!< port D0/port D1 mapping on OSC_IN/OSC_OUT */ +#define AFIO_PCF0_TIMER4CH3_IREMAP BIT(16) /*!< TIMER3 channel3 internal remapping */ +#define AFIO_PCF0_SWJ_CFG BITS(24, 26) /*!< serial wire JTAG configuration */ +#define AFIO_PCF0_SPI2_REMAP BIT(28) /*!< SPI2/I2S2 remapping */ +#define AFIO_PCF0_TIMER1_ITI1_REMAP BIT(29) /*!< TIMER1 internal trigger 1 remapping */ + +/* AFIO_EXTISS0 */ +#define AFIO_EXTI0_SS BITS(0, 3) /*!< EXTI 0 sources selection */ +#define AFIO_EXTI1_SS BITS(4, 7) /*!< EXTI 1 sources selection */ +#define AFIO_EXTI2_SS BITS(8, 11) /*!< EXTI 2 sources selection */ +#define AFIO_EXTI3_SS BITS(12, 15) /*!< EXTI 3 sources selection */ + +/* AFIO_EXTISS1 */ +#define AFIO_EXTI4_SS BITS(0, 3) /*!< EXTI 4 sources selection */ +#define AFIO_EXTI5_SS BITS(4, 7) /*!< EXTI 5 sources selection */ +#define AFIO_EXTI6_SS BITS(8, 11) /*!< EXTI 6 sources selection */ +#define AFIO_EXTI7_SS BITS(12, 15) /*!< EXTI 7 sources selection */ + +/* AFIO_EXTISS2 */ +#define AFIO_EXTI8_SS BITS(0, 3) /*!< EXTI 8 sources selection */ +#define AFIO_EXTI9_SS BITS(4, 7) /*!< EXTI 9 sources selection */ +#define AFIO_EXTI10_SS BITS(8, 11) /*!< EXTI 10 sources selection */ +#define AFIO_EXTI11_SS BITS(12, 15) /*!< EXTI 11 sources selection */ + +/* AFIO_EXTISS3 */ +#define AFIO_EXTI12_SS BITS(0, 3) /*!< EXTI 12 sources selection */ +#define AFIO_EXTI13_SS BITS(4, 7) /*!< EXTI 13 sources selection */ +#define AFIO_EXTI14_SS BITS(8, 11) /*!< EXTI 14 sources selection */ +#define AFIO_EXTI15_SS BITS(12, 15) /*!< EXTI 15 sources selection */ + +/* AFIO_PCF1 */ +#define AFIO_PCF1_EXMC_NADV BIT(10) /*!< EXMC_NADV connect/disconnect */ + +/* constants definitions */ +typedef FlagStatus bit_status; + +/* GPIO mode values set */ +#define GPIO_MODE_SET(n, mode) ((uint32_t)((uint32_t)(mode) << (4U * (n)))) +#define GPIO_MODE_MASK(n) (0xFU << (4U * (n))) + +/* GPIO mode definitions */ +#define GPIO_MODE_AIN ((uint8_t)0x00U) /*!< analog input mode */ +#define GPIO_MODE_IN_FLOATING ((uint8_t)0x04U) /*!< floating input mode */ +#define GPIO_MODE_IPD ((uint8_t)0x28U) /*!< pull-down input mode */ +#define GPIO_MODE_IPU ((uint8_t)0x48U) /*!< pull-up input mode */ +#define GPIO_MODE_OUT_OD ((uint8_t)0x14U) /*!< GPIO output with open-drain */ +#define GPIO_MODE_OUT_PP ((uint8_t)0x10U) /*!< GPIO output with push-pull */ +#define GPIO_MODE_AF_OD ((uint8_t)0x1CU) /*!< AFIO output with open-drain */ +#define GPIO_MODE_AF_PP ((uint8_t)0x18U) /*!< AFIO output with push-pull */ + +/* GPIO output max speed value */ +#define GPIO_OSPEED_10MHZ ((uint8_t)0x01U) /*!< output max speed 10MHz */ +#define GPIO_OSPEED_2MHZ ((uint8_t)0x02U) /*!< output max speed 2MHz */ +#define GPIO_OSPEED_50MHZ ((uint8_t)0x03U) /*!< output max speed 50MHz */ + +/* GPIO event output port definitions */ +#define GPIO_EVENT_PORT_GPIOA ((uint8_t)0x00U) /*!< event output port A */ +#define GPIO_EVENT_PORT_GPIOB ((uint8_t)0x01U) /*!< event output port B */ +#define GPIO_EVENT_PORT_GPIOC ((uint8_t)0x02U) /*!< event output port C */ +#define GPIO_EVENT_PORT_GPIOD ((uint8_t)0x03U) /*!< event output port D */ +#define GPIO_EVENT_PORT_GPIOE ((uint8_t)0x04U) /*!< event output port E */ + +/* GPIO output port source definitions */ +#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00U) /*!< output port source A */ +#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01U) /*!< output port source B */ +#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02U) /*!< output port source C */ +#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03U) /*!< output port source D */ +#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04U) /*!< output port source E */ + +/* GPIO event output pin definitions */ +#define GPIO_EVENT_PIN_0 ((uint8_t)0x00U) /*!< GPIO event pin 0 */ +#define GPIO_EVENT_PIN_1 ((uint8_t)0x01U) /*!< GPIO event pin 1 */ +#define GPIO_EVENT_PIN_2 ((uint8_t)0x02U) /*!< GPIO event pin 2 */ +#define GPIO_EVENT_PIN_3 ((uint8_t)0x03U) /*!< GPIO event pin 3 */ +#define GPIO_EVENT_PIN_4 ((uint8_t)0x04U) /*!< GPIO event pin 4 */ +#define GPIO_EVENT_PIN_5 ((uint8_t)0x05U) /*!< GPIO event pin 5 */ +#define GPIO_EVENT_PIN_6 ((uint8_t)0x06U) /*!< GPIO event pin 6 */ +#define GPIO_EVENT_PIN_7 ((uint8_t)0x07U) /*!< GPIO event pin 7 */ +#define GPIO_EVENT_PIN_8 ((uint8_t)0x08U) /*!< GPIO event pin 8 */ +#define GPIO_EVENT_PIN_9 ((uint8_t)0x09U) /*!< GPIO event pin 9 */ +#define GPIO_EVENT_PIN_10 ((uint8_t)0x0AU) /*!< GPIO event pin 10 */ +#define GPIO_EVENT_PIN_11 ((uint8_t)0x0BU) /*!< GPIO event pin 11 */ +#define GPIO_EVENT_PIN_12 ((uint8_t)0x0CU) /*!< GPIO event pin 12 */ +#define GPIO_EVENT_PIN_13 ((uint8_t)0x0DU) /*!< GPIO event pin 13 */ +#define GPIO_EVENT_PIN_14 ((uint8_t)0x0EU) /*!< GPIO event pin 14 */ +#define GPIO_EVENT_PIN_15 ((uint8_t)0x0FU) /*!< GPIO event pin 15 */ + +/* GPIO output pin source definitions */ +#define GPIO_PIN_SOURCE_0 ((uint8_t)0x00U) /*!< GPIO pin source 0 */ +#define GPIO_PIN_SOURCE_1 ((uint8_t)0x01U) /*!< GPIO pin source 1 */ +#define GPIO_PIN_SOURCE_2 ((uint8_t)0x02U) /*!< GPIO pin source 2 */ +#define GPIO_PIN_SOURCE_3 ((uint8_t)0x03U) /*!< GPIO pin source 3 */ +#define GPIO_PIN_SOURCE_4 ((uint8_t)0x04U) /*!< GPIO pin source 4 */ +#define GPIO_PIN_SOURCE_5 ((uint8_t)0x05U) /*!< GPIO pin source 5 */ +#define GPIO_PIN_SOURCE_6 ((uint8_t)0x06U) /*!< GPIO pin source 6 */ +#define GPIO_PIN_SOURCE_7 ((uint8_t)0x07U) /*!< GPIO pin source 7 */ +#define GPIO_PIN_SOURCE_8 ((uint8_t)0x08U) /*!< GPIO pin source 8 */ +#define GPIO_PIN_SOURCE_9 ((uint8_t)0x09U) /*!< GPIO pin source 9 */ +#define GPIO_PIN_SOURCE_10 ((uint8_t)0x0AU) /*!< GPIO pin source 10 */ +#define GPIO_PIN_SOURCE_11 ((uint8_t)0x0BU) /*!< GPIO pin source 11 */ +#define GPIO_PIN_SOURCE_12 ((uint8_t)0x0CU) /*!< GPIO pin source 12 */ +#define GPIO_PIN_SOURCE_13 ((uint8_t)0x0DU) /*!< GPIO pin source 13 */ +#define GPIO_PIN_SOURCE_14 ((uint8_t)0x0EU) /*!< GPIO pin source 14 */ +#define GPIO_PIN_SOURCE_15 ((uint8_t)0x0FU) /*!< GPIO pin source 15 */ + +/* GPIO pin definitions */ +#define GPIO_PIN_0 BIT(0) /*!< GPIO pin 0 */ +#define GPIO_PIN_1 BIT(1) /*!< GPIO pin 1 */ +#define GPIO_PIN_2 BIT(2) /*!< GPIO pin 2 */ +#define GPIO_PIN_3 BIT(3) /*!< GPIO pin 3 */ +#define GPIO_PIN_4 BIT(4) /*!< GPIO pin 4 */ +#define GPIO_PIN_5 BIT(5) /*!< GPIO pin 5 */ +#define GPIO_PIN_6 BIT(6) /*!< GPIO pin 6 */ +#define GPIO_PIN_7 BIT(7) /*!< GPIO pin 7 */ +#define GPIO_PIN_8 BIT(8) /*!< GPIO pin 8 */ +#define GPIO_PIN_9 BIT(9) /*!< GPIO pin 9 */ +#define GPIO_PIN_10 BIT(10) /*!< GPIO pin 10 */ +#define GPIO_PIN_11 BIT(11) /*!< GPIO pin 11 */ +#define GPIO_PIN_12 BIT(12) /*!< GPIO pin 12 */ +#define GPIO_PIN_13 BIT(13) /*!< GPIO pin 13 */ +#define GPIO_PIN_14 BIT(14) /*!< GPIO pin 14 */ +#define GPIO_PIN_15 BIT(15) /*!< GPIO pin 15 */ +#define GPIO_PIN_ALL BITS(0, 15) /*!< GPIO pin all */ + +/* GPIO remap definitions */ +#define GPIO_SPI0_REMAP ((uint32_t)0x00000001U) /*!< SPI0 remapping */ +#define GPIO_I2C0_REMAP ((uint32_t)0x00000002U) /*!< I2C0 remapping */ +#define GPIO_USART0_REMAP ((uint32_t)0x00000004U) /*!< USART0 remapping */ +#define GPIO_USART1_REMAP ((uint32_t)0x00000008U) /*!< USART1 remapping */ +#define GPIO_USART2_PARTIAL_REMAP ((uint32_t)0x00140010U) /*!< USART2 partial remapping */ +#define GPIO_USART2_FULL_REMAP ((uint32_t)0x00140030U) /*!< USART2 full remapping */ +#define GPIO_TIMER0_PARTIAL_REMAP ((uint32_t)0x00160040U) /*!< TIMER0 partial remapping */ +#define GPIO_TIMER0_FULL_REMAP ((uint32_t)0x001600C0U) /*!< TIMER0 full remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP0 ((uint32_t)0x00180100U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_PARTIAL_REMAP1 ((uint32_t)0x00180200U) /*!< TIMER1 partial remapping */ +#define GPIO_TIMER1_FULL_REMAP ((uint32_t)0x00180300U) /*!< TIMER1 full remapping */ +#define GPIO_TIMER2_PARTIAL_REMAP ((uint32_t)0x001A0800U) /*!< TIMER2 partial remapping */ +#define GPIO_TIMER2_FULL_REMAP ((uint32_t)0x001A0C00U) /*!< TIMER2 full remapping */ +#define GPIO_TIMER3_REMAP ((uint32_t)0x00001000U) /*!< TIMER3 remapping */ +#define GPIO_CAN0_PARTIAL_REMAP ((uint32_t)0x001D4000U) /*!< CAN0 partial remapping */ +#define GPIO_CAN0_FULL_REMAP ((uint32_t)0x001D6000U) /*!< CAN0 full remapping */ +#define GPIO_PD01_REMAP ((uint32_t)0x00008000U) /*!< PD01 remapping */ +#define GPIO_TIMER4CH3_IREMAP ((uint32_t)0x00200001U) /*!< TIMER4 channel3 internal remapping */ +#define GPIO_CAN1_REMAP ((uint32_t)0x00200040U) /*!< CAN1 remapping */ +#define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< JTAG-DP,but without NJTRST */ +#define GPIO_SWJ_DISABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled */ +#define GPIO_SPI2_REMAP ((uint32_t)0x00201100U) /*!< SPI2 remapping */ +#define GPIO_TIMER1ITI1_REMAP ((uint32_t)0x00202000U) /*!< TIMER1 internal trigger 1 remapping */ +#define GPIO_EXMC_NADV_REMAP ((uint32_t)0x80000400U) /*!< EXMC_NADV connect/disconnect */ + +/* function declarations */ +/* reset GPIO port */ +void gpio_deinit(uint32_t gpio_periph); +/* reset alternate function I/O(AFIO) */ +void gpio_afio_deinit(void); +/* GPIO parameter initialization */ +void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); + +/* set GPIO pin bit */ +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); +/* reset GPIO pin bit */ +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); +/* write data to the specified GPIO pin */ +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); +/* write data to the specified GPIO port */ +void gpio_port_write(uint32_t gpio_periph, uint16_t data); + +/* get GPIO pin input status */ +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port input status */ +uint16_t gpio_input_port_get(uint32_t gpio_periph); +/* get GPIO pin output status */ +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); +/* get GPIO port output status */ +uint16_t gpio_output_port_get(uint32_t gpio_periph); + +/* configure GPIO pin remap */ +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); + +/* select GPIO pin exti sources */ +void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); +/* configure GPIO pin event output */ +void gpio_event_output_config(uint8_t output_port, uint8_t output_pin); +/* enable GPIO pin event output */ +void gpio_event_output_enable(void); +/* disable GPIO pin event output */ +void gpio_event_output_disable(void); + +/* lock GPIO pin bit */ +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); + +#endif /* GD32VF103_GPIO_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_hw.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_hw.c new file mode 100644 index 00000000..fc564958 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_hw.c @@ -0,0 +1,195 @@ +/*! + \file gd32vf103_hw.c + \brief USB hardware configuration for GD32VF103 + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_timer.h" +#include +#include +#include +#define TIM_MSEC_DELAY 0x01 +#define TIM_USEC_DELAY 0x02 + +__IO uint32_t delay_time = 0; +__IO uint32_t timer_prescaler; +__IO uint32_t usbfs_prescaler = 0; + +static void hw_time_set(uint8_t unit); +static void hw_delay(uint32_t ntime, uint8_t unit); + +/*! + \brief configure USB clock + \param[in] none + \param[out] none + \retval none +*/ +void usb_rcu_config(void) { + uint32_t system_clock = rcu_clock_freq_get(CK_SYS); + + if (system_clock == 48000000) { + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1; + timer_prescaler = 3; + } else if (system_clock == 72000000) { + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV1_5; + timer_prescaler = 5; + } else if (system_clock == 96000000) { + usbfs_prescaler = RCU_CKUSB_CKPLL_DIV2; + timer_prescaler = 7; + } else { + /* reserved */ + } + + rcu_usb_clock_config(usbfs_prescaler); + rcu_periph_clock_enable(RCU_USBFS); +} + +/*! + \brief configure USB interrupt + \param[in] none + \param[out] none + \retval none +*/ +void usb_intr_config(void) { + eclic_irq_enable((uint8_t)USBFS_IRQn, 1, 0); + + /* enable the power module clock */ + rcu_periph_clock_enable(RCU_PMU); + + /* USB wakeup EXTI line configuration */ + exti_interrupt_flag_clear(EXTI_18); + exti_init(EXTI_18, EXTI_INTERRUPT, EXTI_TRIG_RISING); + exti_interrupt_enable(EXTI_18); + + eclic_irq_enable((uint8_t)USBFS_WKUP_IRQn, 3, 0); +} + +/*! + \brief initializes delay unit using Timer2 + \param[in] none + \param[out] none + \retval none +*/ +void usb_timer_init(void) { + rcu_periph_clock_enable(RCU_TIMER2); + + eclic_irq_enable(TIMER2_IRQn, 2, 0); +} + +/*! + \brief delay in micro seconds + \param[in] usec: value of delay required in micro seconds + \param[out] none + \retval none +*/ +void usb_udelay(const uint32_t usec) { + hw_delay(usec, TIM_USEC_DELAY); +} + +/*! + \brief delay in milli seconds + \param[in] msec: value of delay required in milli seconds + \param[out] none + \retval none +*/ +void usb_mdelay(const uint32_t msec) { + hw_delay(msec, TIM_MSEC_DELAY); +} + +/*! + \brief time base IRQ + \param[in] none + \param[out] none + \retval none +*/ +void usb_timer_irq(void) { + if (RESET != timer_flag_get(TIMER2, TIMER_FLAG_UP)) { + timer_flag_clear(TIMER2, TIMER_FLAG_UP); + + if (delay_time > 0x00U) { + delay_time--; + } else { + timer_disable(TIMER2); + } + } +} + +/*! + \brief delay routine based on TIM0 + \param[in] nTime: delay Time + \param[in] unit: delay Time unit = mili sec / micro sec + \param[out] none + \retval none +*/ +static void hw_delay(uint32_t ntime, uint8_t unit) { + delay_time = ntime; + + hw_time_set(unit); + + while (0U != delay_time) { + } + + timer_disable(TIMER2); +} + +/*! + \brief configures TIM0 for delay routine based on TIM0 + \param[in] unit: msec /usec + \param[out] none + \retval none +*/ +static void hw_time_set(uint8_t unit) { + timer_parameter_struct timer_initpara; + + rcu_periph_clock_enable(RCU_TIMER2); + timer_deinit(TIMER2); + + if (TIM_USEC_DELAY == unit) { + timer_initpara.period = 11; + } else if (TIM_MSEC_DELAY == unit) { + timer_initpara.period = 11999; + } + + timer_initpara.prescaler = timer_prescaler; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER2, &timer_initpara); + + timer_update_event_enable(TIMER2); + timer_interrupt_enable(TIMER2, TIMER_INT_UP); + timer_flag_clear(TIMER2, TIMER_FLAG_UP); + timer_update_source_config(TIMER2, TIMER_UPDATE_SRC_GLOBAL); + + /* TIMER2 counter enable */ + timer_enable(TIMER2); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c new file mode 100644 index 00000000..04cf7be5 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c @@ -0,0 +1,730 @@ +/*! + \file gd32vf103_i2c.c + \brief I2C driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_i2c.h" + +/* I2C register bit mask */ +#define I2CCLK_MAX ((uint32_t)0x00000036U) /*!< i2cclk maximum value */ +#define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ +#define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ +#define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ +#define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ + +/* I2C register bit offset */ +#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ + +/*! + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none + */ +void i2c_deinit(uint32_t i2c_periph) +{ + switch (i2c_periph) { + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } +} + +/*! + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none + */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) +{ + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; + + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t) (pclk1 / 1000000U); + if (freq >= I2CCLK_MAX) { + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if (100000U >= clkspeed) { + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t) ((pclk1 / 1000000U) + 1U); + if (risetime >= I2CCLK_MAX) { + I2C_RT(i2c_periph) = I2CCLK_MAX; + } else if (risetime <= I2CCLK_MIN) { + I2C_RT(i2c_periph) = I2CCLK_MIN; + } else { + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t) (pclk1 / (clkspeed * 2U)); + if (clkc < 0x04U) { + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + } else if (400000U >= clkspeed) { + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U)/(uint32_t)1000U)+(uint32_t)1U); + if (I2C_DTCY_2 == dutycyc){ + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if (0U == (clkc & I2C_CKCFG_CLKC)) { + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + } else { + /* fast mode plus, the maximum SCL rise time is 120ns */ + I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U)+(uint32_t) 1U); + if (I2C_DTCY_2 == dutycyc) { + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + /* enable fast mode */ + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + /* enable I2C fast mode plus */ + I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN; + } +} + +/*! + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none + */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat, uint32_t addr) +{ + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); +} + +/*! + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none + */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) +{ + if (I2C_SMBUS_HOST == type) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } +} + +/*! + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none + */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) +{ + if (I2C_ACK_ENABLE == ack) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } +} + +/*! + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none + */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) +{ + /* configure I2C POAP position */ + if (I2C_ACKPOS_NEXT == pos) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } +} + +/*! + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none + */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirection) +{ + /* master is a transmitter or a receiver */ + if (I2C_TRANSMITTER == trandirection) { + addr = addr & I2C_TRANSMITTER; + } else { + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; +} + +/*! + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none +*/ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) +{ + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); +} + +/*! + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none +*/ +void i2c_dualaddr_disable(uint32_t i2c_periph) +{ + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); +} + +/*! + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none + */ +void i2c_enable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +} + +/*! + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none + */ +void i2c_disable(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +} + +/*! + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none + */ +void i2c_start_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +} + +/*! + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none + */ +void i2c_stop_on_bus(uint32_t i2c_periph) +{ + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +} + +/*! + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none + */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) +{ + I2C_DATA(i2c_periph) = DATA_TRANS(data); +} + +/*! + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received + */ +uint8_t i2c_data_receive(uint32_t i2c_periph) +{ + return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph)); +} + +/*! + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none + */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +{ + /* configure I2C DMA function */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none + */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) +{ + /* configure DMA last transfer */ + uint32_t ctl = 0U; + + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; +} + +/*! + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none + */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) +{ + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none + */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) +{ + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none + */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) +{ + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none + */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) +{ + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none + */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) +{ + /* whether to transfer PEC */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value + */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph) +{ + return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>> STAT1_PECV_OFFSET); +} + +/*! + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none + */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +{ + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none + */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) +{ + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; +} + +/*! + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) +{ + if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none + */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) +{ + uint32_t temp; + if (I2C_FLAG_ADDSEND == flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } +} + +/*! + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none + */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none + */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) +{ + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag)& BIT(I2C_BIT_POS2(int_flag))); + + if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { + if (intenable && bufie) { + intenable = 1U; + } else { + intenable = 0U; + } + } + if ((0U != flagstatus) && (0U != intenable)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none + */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) +{ + uint32_t temp; + if (I2C_INT_FLAG_ADDSEND == int_flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.h new file mode 100644 index 00000000..1c67f076 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.h @@ -0,0 +1,347 @@ +/*! + \file gd32vf103_i2c.h + \brief definitions for the I2C + + \version 2019-06-05, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_I2C_H +#define GD32VF103_I2C_H + +#include "gd32vf103.h" + +/* I2Cx(x=0,1) definitions */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ + +/* registers definitions */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ +#define I2C_FMPCFG(i2cx) REG32((i2cx) + 0x90U) /*!< I2C fast-mode-plus configure register */ +/* bits definitions */ +/* I2Cx_CTL0 */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ + +/* I2Cx_CTL1 */ +#define I2C_CTL1_I2CCLK BITS(0, 5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ + +/* I2Cx_SADDR0 */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1, 7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8, 9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ + +/* I2Cx_SADDR1 */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1, 7) /*!< second I2C address for the slave in dual-address mode */ + +/* I2Cx_DATA */ +#define I2C_DATA_TRB BITS(0, 7) /*!< 8-bit data register */ + +/* I2Cx_STAT0 */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ + +/* I2Cx_STAT1 */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8, 15) /*!< packet error checking value */ + +/* I2Cx_CKCFG */ +#define I2C_CKCFG_CLKC BITS(0, 11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ + +/* I2Cx_RT */ +#define I2C_RT_RISETIME BITS(0, 5) /*!< maximum rise time in fast/standard mode (Master mode) */ + +/* I2Cx_FMPCFG */ +#define I2C_FMPCFG_FMPEN BIT(0) /*!< fast mode plus enable bit */ + +/* constants definitions */ +/* define the I2C bit position and its register index offset */ +#define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset)&0xFFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val)&0x1FU) +#define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16) | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) +#define I2C_BIT_POS2(val) (((uint32_t)(val)&0x1F0000U) >> 16) + +/* register offset */ +#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ + +/* I2C flags */ +typedef enum { + /* flags in STAT0 register */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + /* flags in STAT1 register */ + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TR = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMODF = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U), /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +} i2c_flag_enum; + +/* I2C interrupt flags */ +typedef enum { + /* interrupt flags in CTL1 register */ + I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ + I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ + I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ + I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ + I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ + I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ + I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ + I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ + I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ +} i2c_interrupt_flag_enum; + +/* I2C interrupt enable or disable */ +typedef enum { + /* interrupt in CTL1 register */ + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ +} i2c_interrupt_enum; + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ + +/* SMBus/I2C mode switch and SMBus type selection */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ + +/* I2C transfer direction */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ + +/* whether or not to send an ACK */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ + +/* I2C POAP position*/ +#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ + +/* I2C dual-address mode switch */ +#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ +#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ + +/* whether or not to stretch SCL low */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< SCL stretching is disabled */ + +/* whether or not to response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ + +/* software reset I2C */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ + +/* I2C DMA mode configure */ +/* DMA mode switch */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ + +/* flag indicating DMA last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ + +/* I2C PEC configure */ +/* PEC enable */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ + +/* PEC transfer */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ + +/* I2C SMBus configure */ +/* issue or not alert through SMBA pin */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ + +/* ARP protocol in SMBus switch */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP enable */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP disable */ + +/* transmit I2C data */ +#define DATA_TRANS(regval) (BITS(0, 7) & ((uint32_t)(regval) << 0)) + +/* receive I2C data */ +#define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) + +/* I2C duty cycle in fast mode */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ + +/* address mode for the I2C slave */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ + +/* function declarations */ +/* reset I2C */ +void i2c_deinit(uint32_t i2c_periph); +/* configure I2C clock */ +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); +/* configure I2C address */ +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); +/* SMBus type selection */ +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); +/* whether or not to send an ACK */ +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); +/* configure I2C POAP position */ +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos); +/* master sends slave address */ +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection); +/* enable dual-address mode */ +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t dualaddr); +/* disable dual-address mode */ +void i2c_dualaddr_disable(uint32_t i2c_periph); +/* enable I2C */ +void i2c_enable(uint32_t i2c_periph); +/* disable I2C */ +void i2c_disable(uint32_t i2c_periph); + +/* generate a START condition on I2C bus */ +void i2c_start_on_bus(uint32_t i2c_periph); +/* generate a STOP condition on I2C bus */ +void i2c_stop_on_bus(uint32_t i2c_periph); +/* I2C transmit data function */ +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); +/* I2C receive data function */ +uint8_t i2c_data_receive(uint32_t i2c_periph); +/* enable I2C DMA mode */ +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure whether next DMA EOT is DMA last transfer or not */ +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); +/* whether to stretch SCL low when data is not ready in slave mode */ +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); +/* whether or not to response to a general call */ +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); +/* software reset I2C */ +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); + +/* I2C PEC calculation on or off */ +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); +/* I2C whether to transfer PEC value */ +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); +/* packet error checking value */ +uint8_t i2c_pec_value_get(uint32_t i2c_periph); +/* I2C issue alert through SMBA pin */ +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); +/* I2C ARP protocol in SMBus switch */ +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); + +/* check I2C flag is set or not */ +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); +/* clear I2C flag */ +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); +/* enable I2C interrupt */ +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* disable I2C interrupt */ +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); +/* check I2C interrupt flag */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); +/* clear I2C interrupt flag */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); + +#endif /* GD32VF103_I2C_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.c new file mode 100644 index 00000000..19317e77 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.c @@ -0,0 +1,54 @@ +/*! + \file gd32vf103_it.c + \brief main interrupt service routines + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_it.h" + +/*! + \brief this function handles USBD interrupt + \param[in] none + \param[out] none + \retval none +*/ +void USBFS_IRQHandler(void) { +} + +/*! + \brief this function handles timer2 updata interrupt request. + \param[in] none + \param[out] none + \retval none +*/ +void TIMER2_IRQHandler(void) { + // usb_timer_irq(); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.h new file mode 100644 index 00000000..56f18704 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_it.h @@ -0,0 +1,51 @@ +/*! + \file gd32vf103_it.h + \brief the header file of the ISR + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_IT_H +#define GD32VF103_IT_H + +#include "gd32vf103.h" + +/* function declarations */ +/* this function handles USB wakeup interrupt handler */ +void USBFS_WKUP_IRQHandler(void); +/* this function handles USBFS IRQ Handler */ +void USBFS_IRQHandler(void); + +#endif /* GD32VF103_IT_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_libopt.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_libopt.h new file mode 100644 index 00000000..c4488c8b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_libopt.h @@ -0,0 +1,63 @@ +/*! + \file gd32vf103_libopt.h + \brief library optional for gd32vf103 + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_LIBOPT_H +#define GD32VF103_LIBOPT_H + +#include "gd32vf103_adc.h" +#include "gd32vf103_bkp.h" +#include "gd32vf103_crc.h" +#include "gd32vf103_dbg.h" +#include "gd32vf103_dma.h" +#include "gd32vf103_eclic.h" +#include "gd32vf103_exti.h" +#include "gd32vf103_fmc.h" +#include "gd32vf103_fwdgt.h" +#include "gd32vf103_gpio.h" +#include "gd32vf103_i2c.h" +#include "gd32vf103_pmu.h" +#include "gd32vf103_rcu.h" +#include "gd32vf103_rtc.h" +#include "gd32vf103_spi.h" +#include "gd32vf103_timer.h" +#include "gd32vf103_usart.h" +#include "gd32vf103_wwdgt.h" +#include "n200_func.h" + +#endif /* GD32VF103_LIBOPT_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.c new file mode 100644 index 00000000..e487baa8 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.c @@ -0,0 +1,270 @@ +/*! + \file gd32vf103_pmu.c + \brief PMU driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_pmu.h" +#include "riscv_encoding.h" + +/*! + \brief reset PMU register + \param[in] none + \param[out] none + \retval none +*/ +void pmu_deinit(void) +{ + /* reset PMU */ + rcu_periph_reset_enable(RCU_PMURST); + rcu_periph_reset_disable(RCU_PMURST); +} + +/*! + \brief select low voltage detector threshold + \param[in] lvdt_n: + only one parameter can be selected which is shown as below: + \arg PMU_LVDT_0: voltage threshold is 2.2V + \arg PMU_LVDT_1: voltage threshold is 2.3V + \arg PMU_LVDT_2: voltage threshold is 2.4V + \arg PMU_LVDT_3: voltage threshold is 2.5V + \arg PMU_LVDT_4: voltage threshold is 2.6V + \arg PMU_LVDT_5: voltage threshold is 2.7V + \arg PMU_LVDT_6: voltage threshold is 2.8V + \arg PMU_LVDT_7: voltage threshold is 2.9V + \param[out] none + \retval none +*/ +void pmu_lvd_select(uint32_t lvdt_n) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; + /* clear LVDT bits */ + PMU_CTL &= ~PMU_CTL_LVDT; + /* set LVDT bits according to lvdt_n */ + PMU_CTL |= lvdt_n; + /* enable LVD */ + PMU_CTL |= PMU_CTL_LVDEN; +} + +/*! + \brief disable PMU lvd + \param[in] none + \param[out] none + \retval none +*/ +void pmu_lvd_disable(void) +{ + /* disable LVD */ + PMU_CTL &= ~PMU_CTL_LVDEN; +} + +/*! + \brief PMU work at sleep mode + \param[in] sleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_sleepmode(uint8_t sleepmodecmd) +{ + /* clear sleepdeep bit of RISC-V system control register */ + clear_csr(0x811, 0x1); + + /* select WFI or WFE command to enter sleep mode */ + if(WFI_CMD == sleepmodecmd){ + __WFI(); + }else{ + clear_csr(mstatus, MSTATUS_MIE); + set_csr(0x810, 0x1); + __WFI(); + clear_csr(0x810, 0x1); + set_csr(mstatus, MSTATUS_MIE); + } +} + +/*! + \brief PMU work at deepsleep mode + \param[in] ldo: + only one parameter can be selected which is shown as below: + \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode + \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode + \param[in] deepsleepmodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +{ + /* clear stbmod and ldolp bits */ + PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); + /* set ldolp bit according to pmu_ldo */ + PMU_CTL |= ldo; + /* set CSR_SLEEPVALUE bit of RISC-V system control register */ + set_csr(0x811, 0x1); + /* select WFI or WFE command to enter deepsleep mode */ + if(WFI_CMD == deepsleepmodecmd){ + __WFI(); + }else{ + clear_csr(mstatus, MSTATUS_MIE); + set_csr(0x810, 0x1); + __WFI(); + clear_csr(0x810, 0x1); + set_csr(mstatus, MSTATUS_MIE); + } + /* reset sleepdeep bit of RISC-V system control register */ + clear_csr(0x811, 0x1); +} + +/*! + \brief pmu work at standby mode + \param[in] standbymodecmd: + only one parameter can be selected which is shown as below: + \arg WFI_CMD: use WFI command + \arg WFE_CMD: use WFE command + \param[out] none + \retval none +*/ +void pmu_to_standbymode(uint8_t standbymodecmd) +{ + /* set CSR_SLEEPVALUE bit of RISC-V system control register */ + set_csr(0x811, 0x1); + + /* set stbmod bit */ + PMU_CTL |= PMU_CTL_STBMOD; + + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + + /* select WFI or WFE command to enter standby mode */ + if(WFI_CMD == standbymodecmd){ + __WFI(); + }else{ + clear_csr(mstatus, MSTATUS_MIE); + set_csr(0x810, 0x1); + __WFI(); + clear_csr(0x810, 0x1); + set_csr(mstatus, MSTATUS_MIE); + } + clear_csr(0x811, 0x1); +} + +/*! + \brief enable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_enable(void) +{ + PMU_CS |= PMU_CS_WUPEN; +} + +/*! + \brief disable wakeup pin + \param[in] none + \param[out] none + \retval none +*/ +void pmu_wakeup_pin_disable(void) +{ + PMU_CS &= ~PMU_CS_WUPEN; +} + +/*! + \brief enable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_enable(void) +{ + PMU_CTL |= PMU_CTL_BKPWEN; +} + +/*! + \brief disable write access to the registers in backup domain + \param[in] none + \param[out] none + \retval none +*/ +void pmu_backup_write_disable(void) +{ + PMU_CTL &= ~PMU_CTL_BKPWEN; +} + +/*! + \brief get flag state + \param[in] flag: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_WAKEUP: wakeup flag + \arg PMU_FLAG_STANDBY: standby flag + \arg PMU_FLAG_LVD: lvd flag + \param[out] none + \retval FlagStatus SET or RESET +*/ +FlagStatus pmu_flag_get(uint32_t flag) +{ + if(PMU_CS & flag){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag bit + \param[in] flag_reset: + only one parameter can be selected which is shown as below: + \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag + \arg PMU_FLAG_RESET_STANDBY: reset standby flag + \param[out] none + \retval none +*/ +void pmu_flag_clear(uint32_t flag_reset) +{ + switch(flag_reset){ + case PMU_FLAG_RESET_WAKEUP: + /* reset wakeup flag */ + PMU_CTL |= PMU_CTL_WURST; + break; + case PMU_FLAG_RESET_STANDBY: + /* reset standby flag */ + PMU_CTL |= PMU_CTL_STBRST; + break; + default : + break; + } +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.h new file mode 100644 index 00000000..4a88893c --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_pmu.h @@ -0,0 +1,130 @@ +/*! + \file gd32vf103_pmu.h + \brief definitions for the PMU + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_PMU_H +#define GD32VF103_PMU_H + +#include "gd32vf103.h" + +/* PMU definitions */ +#define PMU PMU_BASE /*!< PMU base address */ + +/* registers definitions */ +#define PMU_CTL REG32((PMU) + 0x00U) /*!< PMU control register */ +#define PMU_CS REG32((PMU) + 0x04U) /*!< PMU control and status register */ + +/* bits definitions */ +/* PMU_CTL */ +#define PMU_CTL_LDOLP BIT(0) /*!< LDO low power mode */ +#define PMU_CTL_STBMOD BIT(1) /*!< standby mode */ +#define PMU_CTL_WURST BIT(2) /*!< wakeup flag reset */ +#define PMU_CTL_STBRST BIT(3) /*!< standby flag reset */ +#define PMU_CTL_LVDEN BIT(4) /*!< low voltage detector enable */ +#define PMU_CTL_LVDT BITS(5, 7) /*!< low voltage detector threshold */ +#define PMU_CTL_BKPWEN BIT(8) /*!< backup domain write enable */ + +/* PMU_CS */ +#define PMU_CS_WUF BIT(0) /*!< wakeup flag */ +#define PMU_CS_STBF BIT(1) /*!< standby flag */ +#define PMU_CS_LVDF BIT(2) /*!< low voltage detector status flag */ +#define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ + +/* constants definitions */ +/* PMU low voltage detector threshold definitions */ +#define CTL_LVDT(regval) (BITS(5, 7) & ((uint32_t)(regval) << 5)) +#define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ +#define PMU_LVDT_1 CTL_LVDT(1) /*!< voltage threshold is 2.3V */ +#define PMU_LVDT_2 CTL_LVDT(2) /*!< voltage threshold is 2.4V */ +#define PMU_LVDT_3 CTL_LVDT(3) /*!< voltage threshold is 2.5V */ +#define PMU_LVDT_4 CTL_LVDT(4) /*!< voltage threshold is 2.6V */ +#define PMU_LVDT_5 CTL_LVDT(5) /*!< voltage threshold is 2.7V */ +#define PMU_LVDT_6 CTL_LVDT(6) /*!< voltage threshold is 2.8V */ +#define PMU_LVDT_7 CTL_LVDT(7) /*!< voltage threshold is 2.9V */ + +/* PMU flag definitions */ +#define PMU_FLAG_WAKEUP PMU_CS_WUF /*!< wakeup flag status */ +#define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ +#define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ + +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + +/* PMU flag reset definitions */ +#define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ +#define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ + +/* PMU command constants definitions */ +#define WFI_CMD ((uint8_t)0x00U) /*!< use WFI command */ +#define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ + +/* function declarations */ +/* reset PMU registers */ +void pmu_deinit(void); + +/* select low voltage detector threshold */ +void pmu_lvd_select(uint32_t lvdt_n); +/* disable PMU lvd */ +void pmu_lvd_disable(void); + +/* set PMU mode */ +/* PMU work at sleep mode */ +void pmu_to_sleepmode(uint8_t sleepmodecmd); +/* PMU work at deepsleep mode */ +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); +/* PMU work at standby mode */ +void pmu_to_standbymode(uint8_t standbymodecmd); +/* enable PMU wakeup pin */ +void pmu_wakeup_pin_enable(void); +/* disable PMU wakeup pin */ +void pmu_wakeup_pin_disable(void); + +/* backup related functions */ +/* enable write access to the registers in backup domain */ +void pmu_backup_write_enable(void); +/* disable write access to the registers in backup domain */ +void pmu_backup_write_disable(void); + +/* flag functions */ +/* get flag state */ +FlagStatus pmu_flag_get(uint32_t flag); +/* clear flag bit */ +void pmu_flag_clear(uint32_t flag_reset); + +#endif /* GD32VF103_PMU_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.c new file mode 100644 index 00000000..3c1a999e --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.c @@ -0,0 +1,1111 @@ +/*! + \file gd32vf103_rcu.c + \brief RCU driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_rcu.h" + +/* define clock source */ +#define SEL_IRC8M ((uint16_t)0U) +#define SEL_HXTAL ((uint16_t)1U) +#define SEL_PLL ((uint16_t)2U) + +/* define startup timeout count */ +#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) +#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) + +/*! + \brief deinitialize the RCU + \param[in] none + \param[out] none + \retval none +*/ +void rcu_deinit(void) +{ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + rcu_osci_stab_wait(RCU_IRC8M); + + /* reset CFG0 register */ + RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4); + /* reset CTL register */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + RCU_CTL &= ~RCU_CTL_HXTALBPS; + RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); + /* reset INT and CFG1 register */ + RCU_INT = 0x00ff0000U; + RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | + RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL); +} + +/*! + \brief enable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock + \arg RCU_AF : alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1): ADC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_enable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock + \param[in] periph: RCU peripherals, refer to rcu_periph_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock + \arg RCU_AF: alternate function clock + \arg RCU_CRC: CRC clock + \arg RCU_DMAx (x=0,1): DMA clock + \arg RCU_USBFS: USBFS clock + \arg RCU_EXMC: EXMC clock + \arg RCU_TIMERx (x=0,1,2,3,4,5,6): TIMER clock + \arg RCU_WWDGT: WWDGT clock + \arg RCU_SPIx (x=0,1,2): SPI clock + \arg RCU_USARTx (x=0,1,2): USART clock + \arg RCU_UARTx (x=3,4): UART clock + \arg RCU_I2Cx (x=0,1): I2C clock + \arg RCU_CANx (x=0,1): CAN clock + \arg RCU_PMU: PMU clock + \arg RCU_DAC: DAC clock + \arg RCU_RTC: RTC clock + \arg RCU_ADCx (x=0,1): ADC clock + \arg RCU_BKPI: BKP interface clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_disable(rcu_periph_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief enable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief disable the peripherals clock when sleep mode + \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum + only one parameter can be selected which is shown as below: + \arg RCU_FMC_SLP: FMC clock + \arg RCU_SRAM_SLP: SRAM clock + \param[out] none + \retval none +*/ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) +{ + RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); +} + +/*! + \brief reset the peripherals + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief disable reset the peripheral + \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum + only one parameter can be selected which is shown as below: + \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports + \arg RCU_AFRST : reset alternate function clock + \arg RCU_USBFSRST: reset USBFS + \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6): reset TIMER + \arg RCU_WWDGTRST: reset WWDGT + \arg RCU_SPIxRST (x=0,1,2): reset SPI + \arg RCU_USARTxRST (x=0,1,2): reset USART + \arg RCU_UARTxRST (x=3,4): reset UART + \arg RCU_I2CxRST (x=0,1): reset I2C + \arg RCU_CANxRST (x=0,1): reset CAN + \arg RCU_PMURST: reset PMU + \arg RCU_DACRST: reset DAC + \arg RCU_ADCxRST (x=0,1): reset ADC + \arg RCU_BKPIRST: reset BKPI + \param[out] none + \retval none +*/ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) +{ + RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); +} + +/*! + \brief reset the BKP domain + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_enable(void) +{ + RCU_BDCTL |= RCU_BDCTL_BKPRST; +} + +/*! + \brief disable the BKP domain reset + \param[in] none + \param[out] none + \retval none +*/ +void rcu_bkp_reset_disable(void) +{ + RCU_BDCTL &= ~RCU_BDCTL_BKPRST; +} + +/*! + \brief configure the system clock source + \param[in] ck_sys: system clock source select + only one parameter can be selected which is shown as below: + \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source + \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source + \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source + \param[out] none + \retval none +*/ +void rcu_system_clock_source_config(uint32_t ck_sys) +{ + uint32_t reg; + + reg = RCU_CFG0; + /* reset the SCS bits and set according to ck_sys */ + reg &= ~RCU_CFG0_SCS; + RCU_CFG0 = (reg | ck_sys); +} + +/*! + \brief get the system clock source + \param[in] none + \param[out] none + \retval which clock is selected as CK_SYS source + \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source + \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source + \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source +*/ +uint32_t rcu_system_clock_source_get(void) +{ + return (RCU_CFG0 & RCU_CFG0_SCSS); +} + +/*! + \brief configure the AHB clock prescaler selection + \param[in] ck_ahb: AHB clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 + \param[out] none + \retval none +*/ +void rcu_ahb_clock_config(uint32_t ck_ahb) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the AHBPSC bits and set according to ck_ahb */ + reg &= ~RCU_CFG0_AHBPSC; + RCU_CFG0 = (reg | ck_ahb); +} + +/*! + \brief configure the APB1 clock prescaler selection + \param[in] ck_apb1: APB1 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 + \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 + \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 + \param[out] none + \retval none +*/ +void rcu_apb1_clock_config(uint32_t ck_apb1) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB1PSC and set according to ck_apb1 */ + reg &= ~RCU_CFG0_APB1PSC; + RCU_CFG0 = (reg | ck_apb1); +} + +/*! + \brief configure the APB2 clock prescaler selection + \param[in] ck_apb2: APB2 clock prescaler selection + only one parameter can be selected which is shown as below: + \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 + \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 + \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 + \param[out] none + \retval none +*/ +void rcu_apb2_clock_config(uint32_t ck_apb2) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the APB2PSC and set according to ck_apb2 */ + reg &= ~RCU_CFG0_APB2PSC; + RCU_CFG0 = (reg | ck_apb2); +} + +/*! + \brief configure the CK_OUT0 clock source + \param[in] ckout0_src: CK_OUT0 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_CKOUT0SRC_NONE: no clock selected + \arg RCU_CKOUT0SRC_CKSYS: system clock selected + \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected + \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected + \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected + \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected + \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected + \arg RCU_CKOUT0SRC_EXT1: EXT1 selected + \arg RCU_CKOUT0SRC_CKPLL2: PLL2 selected + \param[out] none + \retval none +*/ +void rcu_ckout0_config(uint32_t ckout0_src) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* reset the CKOUT0SRC, set according to ckout0_src */ + reg &= ~RCU_CFG0_CKOUT0SEL; + RCU_CFG0 = (reg | ckout0_src); +} + +/*! + \brief configure the main PLL clock + \param[in] pll_src: PLL clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL + \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL_MULx (x = 2..14, 6.5, 16..32) + \param[out] none + \retval none +*/ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) +{ + uint32_t reg = 0U; + + reg = RCU_CFG0; + + /* PLL clock source and multiplication factor configuration */ + reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + reg |= (pll_src | pll_mul); + + RCU_CFG0 = reg; +} + +/*! + \brief configure the PREDV0 division factor and clock source + \param[in] predv0_source: PREDV0 input clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0SRC_HXTAL: HXTAL selected as PREDV0 input source clock + \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock + \param[in] predv0_div: PREDV0 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV0_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset PREDV0SEL and PREDV0 bits */ + reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); + /* set the PREDV0SEL and PREDV0 division factor */ + reg |= (predv0_source | predv0_div); + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PREDV1 division factor + \param[in] predv1_div: PREDV1 division factor + only one parameter can be selected which is shown as below: + \arg RCU_PREDV1_DIVx, x = 1..16 + \param[out] none + \retval none +*/ +void rcu_predv1_config(uint32_t predv1_div) +{ + uint32_t reg = 0U; + + reg = RCU_CFG1; + /* reset the PREDV1 bits */ + reg &= ~RCU_CFG1_PREDV1; + /* set the PREDV1 division factor */ + reg |= predv1_div; + + RCU_CFG1 = reg; +} + +/*! + \brief configure the PLL1 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL1_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll1_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL1MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the PLL2 clock + \param[in] pll_mul: PLL clock multiplication factor + only one parameter can be selected which is shown as below: + \arg RCU_PLL2_MULx (x = 8..16, 20) + \param[out] none + \retval none +*/ +void rcu_pll2_config(uint32_t pll_mul) +{ + RCU_CFG1 &= ~RCU_CFG1_PLL2MF; + RCU_CFG1 |= pll_mul; +} + +/*! + \brief configure the ADC prescaler factor + \param[in] adc_psc: ADC prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 + \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 + \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 + \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 + \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 + \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 + \param[out] none + \retval none +*/ +void rcu_adc_clock_config(uint32_t adc_psc) +{ + uint32_t reg0; + + /* reset the ADCPSC bits */ + reg0 = RCU_CFG0; + reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); + + /* set the ADC prescaler factor */ + switch(adc_psc){ + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; + } + + /* set the register */ + RCU_CFG0 = reg0; +} + +/*! + \brief configure the USBFS prescaler factor + \param[in] usb_psc: USB prescaler factor + only one parameter can be selected which is shown as below: + \arg RCU_CKUSB_CKPLL_DIV1_5: USBFS prescaler select CK_PLL/1.5 + \arg RCU_CKUSB_CKPLL_DIV1: USBFS prescaler select CK_PLL/1 + \arg RCU_CKUSB_CKPLL_DIV2_5: USBFS prescaler select CK_PLL/2.5 + \arg RCU_CKUSB_CKPLL_DIV2: USBFS prescaler select CK_PLL/2 + \param[out] none + \retval none +*/ +void rcu_usb_clock_config(uint32_t usb_psc) +{ + uint32_t reg; + + reg = RCU_CFG0; + + /* configure the USBFS prescaler factor */ + reg &= ~RCU_CFG0_USBFSPSC; + RCU_CFG0 = (reg | usb_psc); +} + +/*! + \brief configure the RTC clock source selection + \param[in] rtc_clock_source: RTC clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_RTCSRC_NONE: no clock selected + \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock + \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock + \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock + \param[out] none + \retval none +*/ +void rcu_rtc_clock_config(uint32_t rtc_clock_source) +{ + uint32_t reg; + + reg = RCU_BDCTL; + /* reset the RTCSRC bits and set according to rtc_clock_source */ + reg &= ~RCU_BDCTL_RTCSRC; + RCU_BDCTL = (reg | rtc_clock_source); +} + +/*! + \brief configure the I2S1 clock source selection + \param[in] i2s_clock_source: I2S1 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock + \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock + \param[out] none + \retval none +*/ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S1SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S1SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief configure the I2S2 clock source selection + \param[in] i2s_clock_source: I2S2 clock source selection + only one parameter can be selected which is shown as below: + \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock + \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock + \param[out] none + \retval none +*/ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source) +{ + uint32_t reg; + + reg = RCU_CFG1; + /* reset the I2S2SEL bit and set according to i2s_clock_source */ + reg &= ~RCU_CFG1_I2S2SEL; + RCU_CFG1 = (reg | i2s_clock_source); +} + +/*! + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_flag_get(rcu_flag_enum flag) +{ + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} + +/*! + \brief get the clock stabilization interrupt and ckm flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \param[out] none + \retval none +*/ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) +{ + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); +} + +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); +} + +/*! + \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \param[out] none + \retval ErrStatus: SUCCESS or ERROR +*/ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) +{ + uint32_t stb_cnt = 0U; + ErrStatus reval = ERROR; + FlagStatus osci_stat = RESET; + + switch(osci){ + /* wait HXTAL stable */ + case RCU_HXTAL: + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait LXTAL stable */ + case RCU_LXTAL: + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC8M stable */ + case RCU_IRC8M: + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + reval = SUCCESS; + } + break; + + /* wait IRC40K stable */ + case RCU_IRC40K: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + reval = SUCCESS; + } + break; + + /* wait PLL stable */ + case RCU_PLL_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + reval = SUCCESS; + } + break; + /* wait PLL1 stable */ + case RCU_PLL1_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + reval = SUCCESS; + } + break; + /* wait PLL2 stable */ + case RCU_PLL2_CK: + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); + stb_cnt++; + } + + /* check whether flag is set or not */ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + reval = SUCCESS; + } + break; + + default: + break; + } + + /* return value */ + return reval; +} + +/*! + \brief turn on the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \param[out] none + \retval none +*/ +void rcu_osci_on(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief turn off the oscillator + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) + \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) + \arg RCU_PLL_CK: phase locked loop(PLL) + \arg RCU_PLL1_CK: phase locked loop 1 + \arg RCU_PLL2_CK: phase locked loop 2 + \param[out] none + \retval none +*/ +void rcu_osci_off(rcu_osci_type_enum osci) +{ + RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); +} + +/*! + \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* enable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg | RCU_CTL_HXTALBPS); + break; + /* enable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + break; + default: + break; + } +} + +/*! + \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it + \param[in] osci: oscillator types, refer to rcu_osci_type_enum + only one parameter can be selected which is shown as below: + \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) + \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) + \param[out] none + \retval none +*/ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) +{ + uint32_t reg; + + switch(osci){ + /* disable HXTAL to bypass mode */ + case RCU_HXTAL: + reg = RCU_CTL; + RCU_CTL &= ~RCU_CTL_HXTALEN; + RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); + break; + /* disable LXTAL to bypass mode */ + case RCU_LXTAL: + reg = RCU_BDCTL; + RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; + RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); + break; + case RCU_IRC8M: + case RCU_IRC40K: + case RCU_PLL_CK: + case RCU_PLL1_CK: + case RCU_PLL2_CK: + break; + default: + break; + } +} + +/*! + \brief enable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ + +void rcu_hxtal_clock_monitor_enable(void) +{ + RCU_CTL |= RCU_CTL_CKMEN; +} + +/*! + \brief disable the HXTAL clock monitor + \param[in] none + \param[out] none + \retval none +*/ +void rcu_hxtal_clock_monitor_disable(void) +{ + RCU_CTL &= ~RCU_CTL_CKMEN; +} + +/*! + \brief set the IRC8M adjust value + \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F + \param[out] none + \retval none +*/ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) +{ + uint32_t reg; + + reg = RCU_CTL; + /* reset the IRC8MADJ bits and set according to irc8m_adjval */ + reg &= ~RCU_CTL_IRC8MADJ; + RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); +} + +/*! + \brief deep-sleep mode voltage select + \param[in] dsvol: deep sleep mode voltage + only one parameter can be selected which is shown as below: + \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V + \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V + \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V + \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V + \param[out] none + \retval none +*/ +void rcu_deepsleep_voltage_set(uint32_t dsvol) +{ + dsvol &= RCU_DSV_DSLPVS; + RCU_DSV = dsvol; +} + +/*! + \brief get the system clock, bus and peripheral clock frequency + \param[in] clock: the clock frequency which to get + only one parameter can be selected which is shown as below: + \arg CK_SYS: system clock frequency + \arg CK_AHB: AHB clock frequency + \arg CK_APB1: APB1 clock frequency + \arg CK_APB2: APB2 clock frequency + \param[out] none + \retval clock frequency of system, AHB, APB1, APB2 +*/ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) +{ + uint32_t sws, ck_freq = 0U; + uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; + uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; + uint32_t predv0, predv1, pll1mf; + + /* exponent of AHB, APB1 and APB2 clock divider */ + uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + sws = GET_BITS(RCU_CFG0, 2, 3); + switch(sws){ + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + cksys_freq = IRC8M_VALUE; + break; + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + cksys_freq = HXTAL_VALUE; + break; + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if(RCU_PLLSRC_HXTAL == pllsel) { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + /* source clock use PLL1 */ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if(17U == pll1mf){ + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + }else{ + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE/2U; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + pllmf |= 0x10U; + } + if(pllmf < 15U){ + pllmf += 2U; + }else{ + pllmf += 1U; + } + + cksys_freq = ck_src * pllmf; + + if(15U == pllmf){ + /* PLL source clock multiply by 6.5 */ + cksys_freq = ck_src * 6U + ck_src / 2U; + } + + break; + /* IRC8M is selected as CK_SYS */ + default: + cksys_freq = IRC8M_VALUE; + break; + } + + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + ahb_freq = cksys_freq >> clk_exp; + + /* calculate APB1 clock frequency */ + idx = GET_BITS(RCU_CFG0, 8, 10); + clk_exp = apb1_exp[idx]; + apb1_freq = ahb_freq >> clk_exp; + + /* calculate APB2 clock frequency */ + idx = GET_BITS(RCU_CFG0, 11, 13); + clk_exp = apb2_exp[idx]; + apb2_freq = ahb_freq >> clk_exp; + + /* return the clocks frequency */ + switch(clock){ + case CK_SYS: + ck_freq = cksys_freq; + break; + case CK_AHB: + ck_freq = ahb_freq; + break; + case CK_APB1: + ck_freq = apb1_freq; + break; + case CK_APB2: + ck_freq = apb2_freq; + break; + default: + break; + } + return ck_freq; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.h new file mode 100644 index 00000000..f197744d --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rcu.h @@ -0,0 +1,721 @@ +/*! + \file gd32vf103_rcu.h + \brief definitions for the RCU + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_RCU_H +#define GD32VF103_RCU_H + +#include "gd32vf103.h" + +/* RCU definitions */ +#define RCU RCU_BASE + +/* registers definitions */ + +#define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ +#define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ +#define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ +#define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ +#define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ +#define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ +#define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ +#define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ +#define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ +#define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ +#define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ +#define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ +#define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ + +/* bits definitions */ +/* RCU_CTL */ +#define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ +#define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ +#define RCU_CTL_IRC8MADJ BITS(3, 7) /*!< high speed internal oscillator clock trim adjust value */ +#define RCU_CTL_IRC8MCALIB BITS(8, 15) /*!< high speed internal oscillator calibration value register */ +#define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ +#define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ +#define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ +#define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ +#define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ +#define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ +#define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ +#define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ +#define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ +#define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ + +#define RCU_CFG0_SCS BITS(0, 1) /*!< system clock switch */ +#define RCU_CFG0_SCSS BITS(2, 3) /*!< system clock switch status */ +#define RCU_CFG0_AHBPSC BITS(4, 7) /*!< AHB prescaler selection */ +#define RCU_CFG0_APB1PSC BITS(8, 10) /*!< APB1 prescaler selection */ +#define RCU_CFG0_APB2PSC BITS(11, 13) /*!< APB2 prescaler selection */ +#define RCU_CFG0_ADCPSC BITS(14, 15) /*!< ADC prescaler selection */ +#define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ +#define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ +#define RCU_CFG0_PLLMF BITS(18, 21) /*!< PLL clock multiplication factor */ +#define RCU_CFG0_USBFSPSC BITS(22, 23) /*!< USBFS clock prescaler selection */ +#define RCU_CFG0_CKOUT0SEL BITS(24, 27) /*!< CKOUT0 clock source selection */ +#define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ +#define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ + +/* RCU_INT */ +#define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ +#define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ +#define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ +#define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ +#define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ +#define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ +#define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ +#define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ +#define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ +#define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ +#define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ +#define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ +#define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ +#define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ +#define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ +#define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ +#define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ +#define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ +#define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ +#define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ +#define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ +#define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ +#define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ + +/* RCU_APB2RST */ +#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ +#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ +#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ +#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ +#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ +#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ +#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ +#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ +#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ +#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ +#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ + +/* RCU_APB1RST */ +#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ +#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ +#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ +#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ +#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ +#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ + +#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ +#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ +#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ +#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ +#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ +#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ +#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ +#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ +#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ +#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ +#define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ +#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ +#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ +#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ + +/* RCU_AHBEN */ +#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ +#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ +#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ +#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ +#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ +#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ +#define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ + +/* RCU_APB2EN */ +#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ +#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ +#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ +#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ +#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ +#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ +#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ +#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ +#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ +#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ +#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ + +/* RCU_APB1EN */ +#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ +#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ +#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ +#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ +#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ +#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ +#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ +#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ +#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ +#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ +#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ +#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ +#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ +#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ +#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ +#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ +#define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ +#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ +#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ +#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ + +/* RCU_BDCTL */ +#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ +#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ +#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ +#define RCU_BDCTL_RTCSRC BITS(8, 9) /*!< RTC clock entry selection */ +#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ +#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ + +/* RCU_RSTSCK */ +#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ +#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ +#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ +#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ +#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ +#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ +#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ +#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ +#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ + +/* RCU_AHBRST */ +#define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ + +/* RCU_CFG1 */ +#define RCU_CFG1_PREDV0 BITS(0, 3) /*!< PREDV0 division factor */ +#define RCU_CFG1_PREDV1 BITS(4, 7) /*!< PREDV1 division factor */ +#define RCU_CFG1_PLL1MF BITS(8, 11) /*!< PLL1 clock multiplication factor */ +#define RCU_CFG1_PLL2MF BITS(12, 15) /*!< PLL2 clock multiplication factor */ +#define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ +#define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ +#define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ + +/* RCU_DSV */ +#define RCU_DSV_DSLPVS BITS(0, 1) /*!< deep-sleep mode voltage select */ + +/* constants definitions */ +/* define the peripheral clock enable bit position and its register index offset */ +#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) +#define RCU_BIT_POS(val) ((uint32_t)(val)&0x1FU) + +/* register offset */ +/* peripherals enable */ +#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ +#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ +#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ + +/* peripherals reset */ +#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ +#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ +#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ +#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ + +/* clock control */ +#define CTL_REG_OFFSET 0x00U /*!< control register offset */ +#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ + +/* clock stabilization and stuck interrupt */ +#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ + +/* configuration register */ +#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ +#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ + +/* peripheral clock enable */ +typedef enum { + /* AHB peripherals */ + RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ + RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ + RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ + RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ + RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ + /* APB1 peripherals */ + RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ + RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ + RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ + RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ + RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ + RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ + RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ + RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ + RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ + RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ + RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ + RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ + RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ + RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ + RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ + RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ + RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ + RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ + RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ + RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ + /* APB2 peripherals */ + RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ + RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ + RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ + RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ + RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ + RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ + RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ + RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ + RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ + RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ + RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ +} rcu_periph_enum; + +/* peripheral clock enable when sleep mode*/ +typedef enum { + /* AHB peripherals */ + RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ + RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ +} rcu_periph_sleep_enum; + +/* peripherals reset */ +typedef enum { + /* AHB peripherals */ + RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ + /* APB1 peripherals */ + RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ + RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ + RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ + RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ + RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ + RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ + RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ + RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ + RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ + RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ + RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ + RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ + RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ + RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ + RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ + RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ + RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ + RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ + RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ + RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ + /* APB2 peripherals */ + RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ + RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ + RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ + RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ + RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ + RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ + RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ + RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ + RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ + RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ + RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ +} rcu_periph_reset_enum; + +/* clock stabilization and peripheral reset flags */ +typedef enum { + /* clock stabilization flags */ + RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ + RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ + RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ + RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ + RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ + RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ + /* reset source flags */ + RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ + RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ + RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ + RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ + RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ + RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ +} rcu_flag_enum; + +/* clock stabilization and ckm interrupt flags */ +typedef enum { + RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ + RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ + RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ + RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ + RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ + RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ + RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ + RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ +} rcu_int_flag_enum; + +/* clock stabilization and stuck interrupt flags clear */ +typedef enum { + RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ + RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ + RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ + RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ + RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ +} rcu_int_flag_clear_enum; + +/* clock stabilization interrupt enable or disable */ +typedef enum { + RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ + RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ + RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ + RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ + RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ + RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ + RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ +} rcu_int_enum; + +/* oscillator types */ +typedef enum { + RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ + RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ + RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ + RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ + RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ + RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ +} rcu_osci_type_enum; + +/* rcu clock frequency */ +typedef enum { + CK_SYS = 0, /*!< system clock */ + CK_AHB, /*!< AHB clock */ + CK_APB1, /*!< APB1 clock */ + CK_APB2, /*!< APB2 clock */ +} rcu_clock_freq_enum; + +/* RCU_CFG0 register bit define */ +/* system clock source select */ +#define CFG0_SCS(regval) (BITS(0, 1) & ((uint32_t)(regval) << 0)) +#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ +#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ +#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ + +/* system clock source select status */ +#define CFG0_SCSS(regval) (BITS(2, 3) & ((uint32_t)(regval) << 2)) +#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ +#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ +#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ + +/* AHB prescaler selection */ +#define CFG0_AHBPSC(regval) (BITS(4, 7) & ((uint32_t)(regval) << 4)) +#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ +#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ +#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ +#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ +#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ +#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ +#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ +#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ +#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ + +/* APB1 prescaler selection */ +#define CFG0_APB1PSC(regval) (BITS(8, 10) & ((uint32_t)(regval) << 8)) +#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ +#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ +#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ +#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ +#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ + +/* APB2 prescaler selection */ +#define CFG0_APB2PSC(regval) (BITS(11, 13) & ((uint32_t)(regval) << 11)) +#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ +#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ +#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ +#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ +#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ + +/* ADC prescaler select */ +#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ +#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ +#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ +#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ +#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ +#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ + +/* PLL clock source selection */ +#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ +#define RCU_PLLSRC_HXTAL RCU_CFG0_PLLSEL /*!< HXTAL clock selected as source clock of PLL */ + +/* PLL clock multiplication factor */ +#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ + +#define CFG0_PLLMF(regval) (BITS(18, 21) & ((uint32_t)(regval) << 18)) +#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ +#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ +#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ +#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ +#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ +#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ +#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ +#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ +#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ +#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ +#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ +#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ +#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ +#define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ +#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ +#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ +#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ +#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ +#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ +#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ +#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ +#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ +#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ +#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ +#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ +#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ +#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ +#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ +#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ +#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ +#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ + +/* USBFS prescaler select */ +#define CFG0_USBPSC(regval) (BITS(22, 23) & ((uint32_t)(regval) << 22)) +#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBFS prescaler select CK_PLL/1.5 */ +#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBFS prescaler select CK_PLL/1 */ +#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBFS prescaler select CK_PLL/2.5 */ +#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBFS prescaler select CK_PLL/2 */ + +/* CKOUT0 clock source selection */ +#define CFG0_CKOUT0SEL(regval) (BITS(24, 27) & ((uint32_t)(regval) << 24)) +#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ +#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ +#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ +#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ +#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ +#define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ +#define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ +#define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected */ +#define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ + +/* RTC clock entry selection */ +#define BDCTL_RTCSRC(regval) (BITS(8, 9) & ((uint32_t)(regval) << 8)) +#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ +#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ +#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ +#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ + +/* PREDV0 division factor */ +#define CFG1_PREDV0(regval) (BITS(0, 3) & ((uint32_t)(regval) << 0)) +#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ +#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ +#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ +#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ +#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ +#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ +#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ +#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ +#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ +#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ +#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ +#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ +#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ +#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ +#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ +#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ + +/* PREDV1 division factor */ +#define CFG1_PREDV1(regval) (BITS(4, 7) & ((uint32_t)(regval) << 4)) +#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ +#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ +#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ +#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ +#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ +#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ +#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ +#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ +#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ +#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ +#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ +#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ +#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ +#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ +#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ +#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ + +/* PLL1 clock multiplication factor */ +#define CFG1_PLL1MF(regval) (BITS(8, 11) & ((uint32_t)(regval) << 8)) +#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ +#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ +#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ +#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ +#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ +#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ +#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ +#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ +#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ +#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ + +/* PLL2 clock multiplication factor */ +#define CFG1_PLL2MF(regval) (BITS(12, 15) & ((uint32_t)(regval) << 12)) +#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ +#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ +#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ +#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ +#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ +#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ +#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ +#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ +#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ +#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ + +/* PREDV0 input clock source selection */ +#define RCU_PREDV0SRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PREDV0 input source clock */ +#define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ + +/* I2S1 clock source selection */ +#define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ +#define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ + +/* I2S2 clock source selection */ +#define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ +#define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ + +/* deep-sleep mode voltage */ +#define DSV_DSLPVS(regval) (BITS(0, 1) & ((uint32_t)(regval) << 0)) +#define RCU_DEEPSLEEP_V_1_2 DSV_DSLPVS(0) /*!< core voltage is 1.2V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_1 DSV_DSLPVS(1) /*!< core voltage is 1.1V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(2) /*!< core voltage is 1.0V in deep-sleep mode */ +#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(3) /*!< core voltage is 0.9V in deep-sleep mode */ + +/* function declarations */ +/* initialization, peripheral clock enable/disable functions */ +/* deinitialize the RCU */ +void rcu_deinit(void); +/* enable the peripherals clock */ +void rcu_periph_clock_enable(rcu_periph_enum periph); +/* disable the peripherals clock */ +void rcu_periph_clock_disable(rcu_periph_enum periph); +/* enable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); +/* disable the peripherals clock when sleep mode */ +void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); +/* reset the peripherals */ +void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); +/* disable reset the peripheral */ +void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); +/* reset the BKP domain */ +void rcu_bkp_reset_enable(void); +/* disable the BKP domain reset */ +void rcu_bkp_reset_disable(void); + +/* clock configuration functions */ +/* configure the system clock source */ +void rcu_system_clock_source_config(uint32_t ck_sys); +/* get the system clock source */ +uint32_t rcu_system_clock_source_get(void); +/* configure the AHB prescaler selection */ +void rcu_ahb_clock_config(uint32_t ck_ahb); +/* configure the APB1 prescaler selection */ +void rcu_apb1_clock_config(uint32_t ck_apb1); +/* configure the APB2 prescaler selection */ +void rcu_apb2_clock_config(uint32_t ck_apb2); +/* configure the CK_OUT0 clock source and divider */ +void rcu_ckout0_config(uint32_t ckout0_src); +/* configure the PLL clock source selection and PLL multiply factor */ +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); + +/* configure the PREDV0 division factor and clock source */ +void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); +/* configure the PREDV1 division factor */ +void rcu_predv1_config(uint32_t predv1_div); +/* configure the PLL1 clock */ +void rcu_pll1_config(uint32_t pll_mul); +/* configure the PLL2 clock */ +void rcu_pll2_config(uint32_t pll_mul); + +/* peripheral clock configuration functions */ +/* configure the ADC division factor */ +void rcu_adc_clock_config(uint32_t adc_psc); +/* configure the USBD/USBFS prescaler factor */ +void rcu_usb_clock_config(uint32_t usb_psc); +/* configure the RTC clock source selection */ +void rcu_rtc_clock_config(uint32_t rtc_clock_source); + +/* configure the I2S1 clock source selection */ +void rcu_i2s1_clock_config(uint32_t i2s_clock_source); +/* configure the I2S2 clock source selection */ +void rcu_i2s2_clock_config(uint32_t i2s_clock_source); + +/* interrupt & flag functions */ +/* get the clock stabilization and periphral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); + +/* oscillator configuration functions */ +/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ +ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); +/* turn on the oscillator */ +void rcu_osci_on(rcu_osci_type_enum osci); +/* turn off the oscillator */ +void rcu_osci_off(rcu_osci_type_enum osci); +/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); +/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ +void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); +/* enable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_enable(void); +/* disable the HXTAL clock monitor */ +void rcu_hxtal_clock_monitor_disable(void); + +/* set the IRC8M adjust value */ +void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval); +/* set the deep sleep mode voltage */ +void rcu_deepsleep_voltage_set(uint32_t dsvol); + +/* get the system clock, bus and peripheral clock frequency */ +uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); + +#endif /* GD32VF103_RCU_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.c new file mode 100644 index 00000000..f67265bf --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.c @@ -0,0 +1,273 @@ +/*! + \file gd32vf103_rtc.c + \brief RTC driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_rtc.h" + +/* RTC register high / low bits mask */ +#define RTC_HIGH_BITS_MASK ((uint32_t)0x000F0000U) /* RTC high bits mask */ +#define RTC_LOW_BITS_MASK ((uint32_t)0x0000FFFFU) /* RTC low bits mask */ + +/* RTC register high bits offset */ +#define RTC_HIGH_BITS_OFFSET ((uint32_t)16U) + +/*! + \brief enter RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_enter(void) +{ + RTC_CTL |= RTC_CTL_CMF; +} + +/*! + \brief exit RTC configuration mode + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration_mode_exit(void) +{ + RTC_CTL &= ~RTC_CTL_CMF; +} + +/*! + \brief set RTC counter value + \param[in] cnt: RTC counter value + \param[out] none + \retval none +*/ +void rtc_counter_set(uint32_t cnt) +{ + rtc_configuration_mode_enter(); + /* set the RTC counter high bits */ + RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET); + /* set the RTC counter low bits */ + RTC_CNTL = (cnt & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief set RTC prescaler value + \param[in] psc: RTC prescaler value + \param[out] none + \retval none +*/ +void rtc_prescaler_set(uint32_t psc) +{ + rtc_configuration_mode_enter(); + /* set the RTC prescaler high bits */ + RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET); + /* set the RTC prescaler low bits */ + RTC_PSCL = (psc & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ + } +} + +/*! + \brief set RTC alarm value + \param[in] alarm: RTC alarm value + \param[out] none + \retval none +*/ +void rtc_alarm_config(uint32_t alarm) +{ + rtc_configuration_mode_enter(); + /* set the alarm high bits */ + RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET); + /* set the alarm low bits */ + RTC_ALRML = (alarm & RTC_LOW_BITS_MASK); + rtc_configuration_mode_exit(); +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + +/*! + \brief get RTC divider value + \param[in] none + \param[out] none + \retval RTC divider value +*/ +uint32_t rtc_divider_get(void) +{ + uint32_t temp = 0x00U; + + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); + temp |= RTC_DIVL; + return temp; +} + +/*! + \brief get RTC flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \param[out] none + \retval none +*/ +void rtc_flag_clear(uint32_t flag) +{ + /* clear RTC flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief get RTC interrupt flag status + \param[in] flag: specify which flag status to get + only one parameter can be selected which is shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval SET or RESET +*/ +FlagStatus rtc_interrupt_flag_get(uint32_t flag) +{ + if(RESET != (RTC_CTL & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear RTC interrupt flag status + \param[in] flag: specify which flag status to clear + one or more parameters can be selected which are shown as below: + \arg RTC_INT_FLAG_SECOND: second interrupt flag + \arg RTC_INT_FLAG_ALARM: alarm interrupt flag + \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \param[out] none + \retval none +*/ +void rtc_interrupt_flag_clear(uint32_t flag) +{ + /* clear RTC interrupt flag */ + RTC_CTL &= ~flag; +} + +/*! + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_enable(uint32_t interrupt) +{ + RTC_INTEN |= interrupt; +} + +/*! + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt + \param[out] none + \retval none +*/ +void rtc_interrupt_disable(uint32_t interrupt) +{ + RTC_INTEN &= ~interrupt; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.h new file mode 100644 index 00000000..dd6b0c07 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_rtc.h @@ -0,0 +1,153 @@ +/*! + \file gd32vf103_rtc.h + \brief definitions for the RTC + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_RTC_H +#define GD32VF103_RTC_H + +#include "gd32vf103.h" + +/* RTC definitions */ +#define RTC RTC_BASE + +/* registers definitions */ +#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ + +/* bits definitions */ +/* RTC_INTEN */ +#define RTC_INTEN_SCIE BIT(0) /*!< second interrupt enable */ +#define RTC_INTEN_ALRMIE BIT(1) /*!< alarm interrupt enable */ +#define RTC_INTEN_OVIE BIT(2) /*!< overflow interrupt enable */ + +/* RTC_CTL */ +#define RTC_CTL_SCIF BIT(0) /*!< second interrupt flag */ +#define RTC_CTL_ALRMIF BIT(1) /*!< alarm interrupt flag */ +#define RTC_CTL_OVIF BIT(2) /*!< overflow interrupt flag */ +#define RTC_CTL_RSYNF BIT(3) /*!< registers synchronized flag */ +#define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ +#define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ + +/* RTC_PSCH */ +#define RTC_PSCH_PSC BITS(0, 3) /*!< prescaler high value */ + +/* RTC_PSCL */ +#define RTC_PSCL_PSC BITS(0, 15) /*!< prescaler low value */ + +/* RTC_DIVH */ +#define RTC_DIVH_DIV BITS(0, 3) /*!< divider high value */ + +/* RTC_DIVL */ +#define RTC_DIVL_DIV BITS(0, 15) /*!< divider low value */ + +/* RTC_CNTH */ +#define RTC_CNTH_CNT BITS(0, 15) /*!< counter high value */ + +/* RTC_CNTL */ +#define RTC_CNTL_CNT BITS(0, 15) /*!< counter low value */ + +/* RTC_ALRMH */ +#define RTC_ALRMH_ALRM BITS(0, 15) /*!< alarm high value */ + +/* RTC_ALRML */ +#define RTC_ALRML_ALRM BITS(0, 15) /*!< alarm low value */ + +/* constants definitions */ +/* RTC interrupt enable or disable definitions */ +#define RTC_INT_SECOND RTC_INTEN_SCIE /*!< second interrupt enable */ +#define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ +#define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ + +/* RTC interrupt flag definitions */ +#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ + +/* RTC flag definitions */ +#define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ +#define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ +#define RTC_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ +#define RTC_FLAG_RSYN RTC_CTL_RSYNF /*!< registers synchronized flag */ +#define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ + +/* function declarations */ +/* initialization functions */ +/* enter RTC configuration mode */ +void rtc_configuration_mode_enter(void); +/* exit RTC configuration mode */ +void rtc_configuration_mode_exit(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); + +/* operation functions */ +/* wait RTC last write operation finished flag set */ +void rtc_lwoff_wait(void); +/* wait RTC registers synchronized flag set */ +void rtc_register_sync_wait(void); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); +/* get RTC counter value */ +uint32_t rtc_counter_get(void); +/* get RTC divider value */ +uint32_t rtc_divider_get(void); + +/* flag & interrupt functions */ +/* get RTC flag status */ +FlagStatus rtc_flag_get(uint32_t flag); +/* clear RTC flag status */ +void rtc_flag_clear(uint32_t flag); +/* get RTC interrupt flag status */ +FlagStatus rtc_interrupt_flag_get(uint32_t flag); +/* clear RTC interrupt flag status */ +void rtc_interrupt_flag_clear(uint32_t flag); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); + +#endif /* GD32VF103_RTC_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.c new file mode 100644 index 00000000..6bfb5709 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.c @@ -0,0 +1,766 @@ +/*! + \file gd32vf103_spi.c + \brief SPI driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_spi.h" + +/* SPI/I2S parameter initialization mask */ +#define SPI_INIT_MASK ((uint32_t)0x00003040U) /*!< SPI parameter initialization mask */ +#define I2S_INIT_MASK ((uint32_t)0x0000F047U) /*!< I2S parameter initialization mask */ + +/* I2S clock source selection, multiplication and division mask */ +#define I2S1_CLOCK_SEL ((uint32_t)0x00020000U) /* I2S1 clock source selection */ +#define I2S2_CLOCK_SEL ((uint32_t)0x00040000U) /* I2S2 clock source selection */ +#define I2S_CLOCK_MUL_MASK ((uint32_t)0x0000F000U) /* I2S clock multiplication mask */ +#define I2S_CLOCK_DIV_MASK ((uint32_t)0x000000F0U) /* I2S clock division mask */ + +/* default value and offset */ +#define SPI_I2SPSC_DEFAULT_VALUE ((uint32_t)0x00000002U) /* default value of SPI_I2SPSC register */ +#define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ +#define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ + +/*! + \brief reset SPI and I2S + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_i2s_deinit(uint32_t spi_periph) +{ + switch(spi_periph){ + case SPI0: + /* reset SPI0 */ + rcu_periph_reset_enable(RCU_SPI0RST); + rcu_periph_reset_disable(RCU_SPI0RST); + break; + case SPI1: + /* reset SPI1 and I2S1 */ + rcu_periph_reset_enable(RCU_SPI1RST); + rcu_periph_reset_disable(RCU_SPI1RST); + break; + case SPI2: + /* reset SPI2 and I2S2 */ + rcu_periph_reset_enable(RCU_SPI2RST); + rcu_periph_reset_disable(RCU_SPI2RST); + break; + default : + break; + } +} + +/*! + \brief initialize the parameters of SPI struct with the default values + \param[in] spi_struct: SPI parameter stuct + \param[out] none + \retval none +*/ +void spi_struct_para_init(spi_parameter_struct* spi_struct) +{ + /* set the SPI struct with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_struct->prescale = SPI_PSC_2; +} + +/*! + \brief initialize SPI parameter + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] spi_struct: SPI parameter initialization stuct members of the structure + and the member values are shown as below: + device_mode: SPI_MASTER, SPI_SLAVE + trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, + SPI_TRANSMODE_BDRECEIVE, SPI_TRANSMODE_BDTRANSMIT + frame_size: SPI_FRAMESIZE_16BIT, SPI_FRAMESIZE_8BIT + nss: SPI_NSS_SOFT, SPI_NSS_HARD + endian: SPI_ENDIAN_MSB, SPI_ENDIAN_LSB + clock_polarity_phase: SPI_CK_PL_LOW_PH_1EDGE, SPI_CK_PL_HIGH_PH_1EDGE + SPI_CK_PL_LOW_PH_2EDGE, SPI_CK_PL_HIGH_PH_2EDGE + prescale: SPI_PSC_n (n=2,4,8,16,32,64,128,256) + \param[out] none + \retval none +*/ +void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) +{ + uint32_t reg = 0U; + reg = SPI_CTL0(spi_periph); + reg &= SPI_INIT_MASK; + + /* select SPI as master or slave */ + reg |= spi_struct->device_mode; + /* select SPI transfer mode */ + reg |= spi_struct->trans_mode; + /* select SPI frame size */ + reg |= spi_struct->frame_size; + /* select SPI NSS use hardware or software */ + reg |= spi_struct->nss; + /* select SPI LSB or MSB */ + reg |= spi_struct->endian; + /* select SPI polarity and phase */ + reg |= spi_struct->clock_polarity_phase; + /* select SPI prescale to adjust transmit speed */ + reg |= spi_struct->prescale; + + /* write to SPI_CTL0 register */ + SPI_CTL0(spi_periph) = (uint32_t)reg; + + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SSEL); +} + +/*! + \brief enable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_enable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SPIEN; +} + +/*! + \brief disable SPI + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_disable(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SPIEN); +} + +/*! + \brief initialize I2S parameter + \param[in] spi_periph: SPIx(x=1,2) + \param[in] mode: I2S operation mode + only one parameter can be selected which is shown as below: + \arg I2S_MODE_SLAVETX: I2S slave transmit mode + \arg I2S_MODE_SLAVERX: I2S slave receive mode + \arg I2S_MODE_MASTERTX: I2S master transmit mode + \arg I2S_MODE_MASTERRX: I2S master receive mode + \param[in] standard: I2S standard + only one parameter can be selected which is shown as below: + \arg I2S_STD_PHILLIPS: I2S phillips standard + \arg I2S_STD_MSB: I2S MSB standard + \arg I2S_STD_LSB: I2S LSB standard + \arg I2S_STD_PCMSHORT: I2S PCM short standard + \arg I2S_STD_PCMLONG: I2S PCM long standard + \param[in] ckpl: I2S idle state clock polarity + only one parameter can be selected which is shown as below: + \arg I2S_CKPL_LOW: I2S clock polarity low level + \arg I2S_CKPL_HIGH: I2S clock polarity high level + \param[out] none + \retval none +*/ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl) +{ + uint32_t reg = 0U; + reg = SPI_I2SCTL(spi_periph); + reg &= I2S_INIT_MASK; + + /* enable I2S mode */ + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + /* select I2S mode */ + reg |= (uint32_t)mode; + /* select I2S standard */ + reg |= (uint32_t)standard; + /* select I2S polarity */ + reg |= (uint32_t)ckpl; + + /* write to SPI_I2SCTL register */ + SPI_I2SCTL(spi_periph) = (uint32_t)reg; +} + +/*! + \brief configure I2S prescaler + \param[in] spi_periph: SPIx(x=1,2) + \param[in] audiosample: I2S audio sample rate + only one parameter can be selected which is shown as below: + \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz + \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz + \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz + \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz + \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz + \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz + \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz + \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz + \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz + \param[in] frameformat: I2S data length and channel length + only one parameter can be selected which is shown as below: + \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit + \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit + \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit + \param[in] mckout: I2S master clock output + only one parameter can be selected which is shown as below: + \arg I2S_MCKOUT_ENABLE: I2S master clock output enable + \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \param[out] none + \retval none +*/ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) +{ + uint32_t i2sdiv = 2U, i2sof = 0U; + uint32_t clks = 0U; + uint32_t i2sclock = 0U; + + /* deinit SPI_I2SPSC register */ + SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; + + /* get the I2S clock source */ + if(SPI1 == ((uint32_t)spi_periph)){ + /* I2S1 clock source selection */ + clks = I2S1_CLOCK_SEL; + }else{ + /* I2S2 clock source selection */ + clks = I2S2_CLOCK_SEL; + } + + if(0U != (RCU_CFG1 & clks)){ + /* get RCU PLL2 clock multiplication factor */ + clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); + + if((clks > 5U) && (clks < 15U)){ + /* multiplier is between 8 and 16 */ + clks += 2U; + }else{ + if(15U == clks){ + /* multiplier is 20 */ + clks = 20U; + } + } + + /* get the PREDV1 value */ + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + /* calculate I2S clock based on PLL2 and PREDV1 */ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + }else{ + /* get system clock */ + i2sclock = rcu_clock_freq_get(CK_SYS); + } + + /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout){ + clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); + }else{ + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ + clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); + }else{ + clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } + } + + /* remove the floating point */ + clks = (clks + 5U) / 10U; + i2sof = (clks & 0x00000001U); + i2sdiv = ((clks - i2sof) / 2U); + i2sof = (i2sof << 8U); + + /* set the default values */ + if((i2sdiv < 2U) || (i2sdiv > 255U)){ + i2sdiv = 2U; + i2sof = 0U; + } + /* configure SPI_I2SPSC */ + SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | mckout); + + /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ + SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; +} + +/*! + \brief enable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_enable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; +} + +/*! + \brief disable I2S + \param[in] spi_periph: SPIx(x=1,2) + \param[out] none + \retval none +*/ +void i2s_disable(uint32_t spi_periph) +{ + SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); +} + +/*! + \brief enable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSDRV; +} + +/*! + \brief disable SPI NSS output + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_output_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSDRV); +} + +/*! + \brief SPI NSS pin high level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_high(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_SWNSS; +} + +/*! + \brief SPI NSS pin low level in software mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nss_internal_low(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_SWNSS); +} + +/*! + \brief enable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; + }else{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; + } +} + +/*! + \brief disable SPI DMA send or receive + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] dma: SPI DMA mode + only one parameter can be selected which is shown as below: + \arg SPI_DMA_TRANSMIT: SPI transmit data using DMA + \arg SPI_DMA_RECEIVE: SPI receive data using DMA + \param[out] none + \retval none +*/ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma) +{ + if(SPI_DMA_TRANSMIT == dma){ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); + }else{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); + } +} + +/*! + \brief configure SPI/I2S data frame format + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] frame_format: SPI frame size + only one parameter can be selected which is shown as below: + \arg SPI_FRAMESIZE_16BIT: SPI frame size is 16 bits + \arg SPI_FRAMESIZE_8BIT: SPI frame size is 8 bits + \param[out] none + \retval none +*/ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format) +{ + /* clear SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_FF16); + /* configure SPI_CTL0_FF16 bit */ + SPI_CTL0(spi_periph) |= (uint32_t)frame_format; +} + +/*! + \brief SPI transmit data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] data: 16-bit data + \param[out] none + \retval none +*/ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data) +{ + SPI_DATA(spi_periph) = (uint32_t)data; +} + +/*! + \brief SPI receive data + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit data +*/ +uint16_t spi_i2s_data_receive(uint32_t spi_periph) +{ + return ((uint16_t)SPI_DATA(spi_periph)); +} + +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ + /* set the transmit-only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + }else{ + /* set the receive-only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + +/*! + \brief set SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc_poly: CRC polynomial value + \param[out] none + \retval none +*/ +void spi_crc_polynomial_set(uint32_t spi_periph,uint16_t crc_poly) +{ + /* enable SPI CRC */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; + + /* set SPI CRC polynomial */ + SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; +} + +/*! + \brief get SPI CRC polynomial + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval 16-bit CRC polynomial +*/ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph) +{ + return ((uint16_t)SPI_CRCPOLY(spi_periph)); +} + +/*! + \brief turn on CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_on(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; +} + +/*! + \brief turn off CRC function + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_off(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) &= (uint32_t)(~SPI_CTL0_CRCEN); +} + +/*! + \brief SPI next data is CRC value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_next(uint32_t spi_periph) +{ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCNT; +} + +/*! + \brief get SPI CRC send value or receive value + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] crc: SPI crc value + only one parameter can be selected which is shown as below: + \arg SPI_CRC_TX: get transmit crc value + \arg SPI_CRC_RX: get receive crc value + \param[out] none + \retval 16-bit CRC value +*/ +uint16_t spi_crc_get(uint32_t spi_periph,uint8_t crc) +{ + if(SPI_CRC_TX == crc){ + return ((uint16_t)(SPI_TCRC(spi_periph))); + }else{ + return ((uint16_t)(SPI_RCRC(spi_periph))); + } +} + +/*! + \brief enable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TMOD; +} + +/*! + \brief disable SPI TI mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_ti_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TMOD); +} + +/*! + \brief enable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_enable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_NSSP; +} + +/*! + \brief disable SPI NSS pulse mode + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_nssp_mode_disable(uint32_t spi_periph) +{ + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_NSSP); +} + + +/*! + \brief enable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; + break; + default: + break; + } +} + +/*! + \brief disable SPI and I2S interrupt + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt + \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt + \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + transmission underrun error and format error interrupt + \param[out] none + \retval none +*/ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) +{ + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_TBE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_RBNE: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); + break; + /* SPI/I2S error */ + case SPI_I2S_INT_ERR: + SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); + break; + default: + break; + } +} + +/*! + \brief get SPI and I2S interrupt flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] interrupt: SPI/I2S interrupt flag status + only one parameter can be selected which is shown as below: + \arg SPI_I2S_INT_FLAG_TBE: transmit buffer empty interrupt flag + \arg SPI_I2S_INT_FLAG_RBNE: receive buffer not empty interrupt flag + \arg SPI_I2S_INT_FLAG_RXORERR: overrun interrupt flag + \arg SPI_INT_FLAG_CONFERR: config error interrupt flag + \arg SPI_INT_FLAG_CRCERR: CRC error interrupt flag + \arg I2S_INT_FLAG_TXURERR: underrun error interrupt flag + \arg SPI_I2S_INT_FLAG_FERR: format error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) +{ + uint32_t reg1 = SPI_STAT(spi_periph); + uint32_t reg2 = SPI_CTL1(spi_periph); + + switch(interrupt){ + /* SPI/I2S transmit buffer empty interrupt */ + case SPI_I2S_INT_FLAG_TBE: + reg1 = reg1 & SPI_STAT_TBE; + reg2 = reg2 & SPI_CTL1_TBEIE; + break; + /* SPI/I2S receive buffer not empty interrupt */ + case SPI_I2S_INT_FLAG_RBNE: + reg1 = reg1 & SPI_STAT_RBNE; + reg2 = reg2 & SPI_CTL1_RBNEIE; + break; + /* SPI/I2S overrun interrupt */ + case SPI_I2S_INT_FLAG_RXORERR: + reg1 = reg1 & SPI_STAT_RXORERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI config error interrupt */ + case SPI_INT_FLAG_CONFERR: + reg1 = reg1 & SPI_STAT_CONFERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI CRC error interrupt */ + case SPI_INT_FLAG_CRCERR: + reg1 = reg1 & SPI_STAT_CRCERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* I2S underrun error interrupt */ + case I2S_INT_FLAG_TXURERR: + reg1 = reg1 & SPI_STAT_TXURERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + /* SPI/I2S format error interrupt */ + case SPI_I2S_INT_FLAG_FERR: + reg1 = reg1 & SPI_STAT_FERR; + reg2 = reg2 & SPI_CTL1_ERRIE; + break; + default: + break; + } + /* get SPI/I2S interrupt flag status */ + if((0U != reg1) && (0U != reg2)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + one or more parameters can be selected which are shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg SPI_FLAG_FERR: format error interrupt flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \arg I2S_FLAG_FERR: format error interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.h new file mode 100644 index 00000000..f229615c --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_spi.h @@ -0,0 +1,346 @@ +/*! + \file gd32vf103_spi.h + \brief definitions for the SPI + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_SPI_H +#define GD32VF103_SPI_H + +#include "gd32vf103.h" + +/* SPIx(x=0,1,2) definitions */ +#define SPI0 (SPI_BASE + 0x0000F800U) +#define SPI1 SPI_BASE +#define SPI2 (SPI_BASE + 0x00000400U) + +/* SPI registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ + +/* bits definitions */ +/* SPI_CTL0 */ +#define SPI_CTL0_CKPH BIT(0) /*!< clock phase selection*/ +#define SPI_CTL0_CKPL BIT(1) /*!< clock polarity selection */ +#define SPI_CTL0_MSTMOD BIT(2) /*!< master mode enable */ +#define SPI_CTL0_PSC BITS(3, 5) /*!< master clock prescaler selection */ +#define SPI_CTL0_SPIEN BIT(6) /*!< SPI enable*/ +#define SPI_CTL0_LF BIT(7) /*!< LSB first mode */ +#define SPI_CTL0_SWNSS BIT(8) /*!< NSS pin selection in NSS software mode */ +#define SPI_CTL0_SWNSSEN BIT(9) /*!< NSS software mode selection */ +#define SPI_CTL0_RO BIT(10) /*!< receive only */ +#define SPI_CTL0_FF16 BIT(11) /*!< data frame size */ +#define SPI_CTL0_CRCNT BIT(12) /*!< CRC next transfer */ +#define SPI_CTL0_CRCEN BIT(13) /*!< CRC calculation enable */ +#define SPI_CTL0_BDOEN BIT(14) /*!< bidirectional transmit output enable*/ +#define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ + +/* SPI_CTL1 */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ +#define SPI_CTL1_NSSP BIT(3) /*!< SPI NSS pulse mode enable */ +#define SPI_CTL1_TMOD BIT(4) /*!< SPI TI mode enable */ +#define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ +#define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ +#define SPI_CTL1_TBEIE BIT(7) /*!< transmit buffer empty interrupt enable */ + +/* SPI_STAT */ +#define SPI_STAT_RBNE BIT(0) /*!< receive buffer not empty */ +#define SPI_STAT_TBE BIT(1) /*!< transmit buffer empty */ +#define SPI_STAT_I2SCH BIT(2) /*!< I2S channel side */ +#define SPI_STAT_TXURERR BIT(3) /*!< I2S transmission underrun error bit */ +#define SPI_STAT_CRCERR BIT(4) /*!< SPI CRC error bit */ +#define SPI_STAT_CONFERR BIT(5) /*!< SPI configuration error bit */ +#define SPI_STAT_RXORERR BIT(6) /*!< SPI reception overrun error bit */ +#define SPI_STAT_TRANS BIT(7) /*!< transmitting on-going bit */ +#define SPI_STAT_FERR BIT(8) /*!< format error bit */ + +/* SPI_DATA */ +#define SPI_DATA_DATA BITS(0, 15) /*!< data transfer register */ + +/* SPI_CRCPOLY */ +#define SPI_CRCPOLY_CRCPOLY BITS(0, 15) /*!< CRC polynomial value */ + +/* SPI_RCRC */ +#define SPI_RCRC_RCRC BITS(0, 15) /*!< RX CRC value */ + +/* SPI_TCRC */ +#define SPI_TCRC_TCRC BITS(0, 15) /*!< TX CRC value */ + +/* SPI_I2SCTL */ +#define SPI_I2SCTL_CHLEN BIT(0) /*!< channel length */ +#define SPI_I2SCTL_DTLEN BITS(1, 2) /*!< data length */ +#define SPI_I2SCTL_CKPL BIT(3) /*!< idle state clock polarity */ +#define SPI_I2SCTL_I2SSTD BITS(4, 5) /*!< I2S standard selection */ +#define SPI_I2SCTL_PCMSMOD BIT(7) /*!< PCM frame synchronization mode */ +#define SPI_I2SCTL_I2SOPMOD BITS(8, 9) /*!< I2S operation mode */ +#define SPI_I2SCTL_I2SEN BIT(10) /*!< I2S enable */ +#define SPI_I2SCTL_I2SSEL BIT(11) /*!< I2S mode selection */ + +/* SPI_I2SPSC */ +#define SPI_I2SPSC_DIV BITS(0, 7) /*!< dividing factor for the prescaler */ +#define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ +#define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ + +/* constants definitions */ +/* SPI and I2S parameter struct definitions */ +typedef struct +{ + uint32_t device_mode; /*!< SPI master or slave */ + uint32_t trans_mode; /*!< SPI transtype */ + uint32_t frame_size; /*!< SPI frame size */ + uint32_t nss; /*!< SPI NSS control by handware or software */ + uint32_t endian; /*!< SPI big endian or little endian */ + uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ + uint32_t prescale; /*!< SPI prescale factor */ +} spi_parameter_struct; + +/* SPI mode definitions */ +#define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ +#define SPI_SLAVE ((uint32_t)0x00000000U) /*!< SPI as slave */ + +/* SPI bidirectional transfer direction */ +#define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ + +/* SPI transmit type */ +#define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ +#define SPI_TRANSMODE_RECEIVEONLY SPI_CTL0_RO /*!< SPI only receive data */ +#define SPI_TRANSMODE_BDRECEIVE SPI_CTL0_BDEN /*!< bidirectional receive data */ +#define SPI_TRANSMODE_BDTRANSMIT (SPI_CTL0_BDEN | SPI_CTL0_BDOEN) /*!< bidirectional transmit data*/ + +/* SPI frame size */ +#define SPI_FRAMESIZE_16BIT SPI_CTL0_FF16 /*!< SPI frame size is 16 bits */ +#define SPI_FRAMESIZE_8BIT ((uint32_t)0x00000000U) /*!< SPI frame size is 8 bits */ + +/* SPI NSS control mode */ +#define SPI_NSS_SOFT SPI_CTL0_SWNSSEN /*!< SPI NSS control by software */ +#define SPI_NSS_HARD ((uint32_t)0x00000000U) /*!< SPI NSS control by hardware */ + +/* SPI transmit way */ +#define SPI_ENDIAN_MSB ((uint32_t)0x00000000U) /*!< SPI transmit way is big endian: transmit MSB first */ +#define SPI_ENDIAN_LSB SPI_CTL0_LF /*!< SPI transmit way is little endian: transmit LSB first */ + +/* SPI clock phase and polarity */ +#define SPI_CK_PL_LOW_PH_1EDGE ((uint32_t)0x00000000U) /*!< SPI clock polarity is low level and phase is first edge */ +#define SPI_CK_PL_HIGH_PH_1EDGE SPI_CTL0_CKPL /*!< SPI clock polarity is high level and phase is first edge */ +#define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ +#define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ + +/* SPI clock prescale factor */ +#define CTL0_PSC(regval) (BITS(3, 5) & ((uint32_t)(regval) << 3)) +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ + +/* I2S audio sample rate */ +#define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ +#define I2S_AUDIOSAMPLE_11K ((uint32_t)11025U) /*!< I2S audio sample rate is 11KHz */ +#define I2S_AUDIOSAMPLE_16K ((uint32_t)16000U) /*!< I2S audio sample rate is 16KHz */ +#define I2S_AUDIOSAMPLE_22K ((uint32_t)22050U) /*!< I2S audio sample rate is 22KHz */ +#define I2S_AUDIOSAMPLE_32K ((uint32_t)32000U) /*!< I2S audio sample rate is 32KHz */ +#define I2S_AUDIOSAMPLE_44K ((uint32_t)44100U) /*!< I2S audio sample rate is 44KHz */ +#define I2S_AUDIOSAMPLE_48K ((uint32_t)48000U) /*!< I2S audio sample rate is 48KHz */ +#define I2S_AUDIOSAMPLE_96K ((uint32_t)96000U) /*!< I2S audio sample rate is 96KHz */ +#define I2S_AUDIOSAMPLE_192K ((uint32_t)192000U) /*!< I2S audio sample rate is 192KHz */ + +/* I2S frame format */ +#define I2SCTL_DTLEN(regval) (BITS(1, 2) & ((uint32_t)(regval) << 1)) +#define I2S_FRAMEFORMAT_DT16B_CH16B I2SCTL_DTLEN(0) /*!< I2S data length is 16 bit and channel length is 16 bit */ +#define I2S_FRAMEFORMAT_DT16B_CH32B (I2SCTL_DTLEN(0) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 16 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT24B_CH32B (I2SCTL_DTLEN(1) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 24 bit and channel length is 32 bit */ +#define I2S_FRAMEFORMAT_DT32B_CH32B (I2SCTL_DTLEN(2) | SPI_I2SCTL_CHLEN) /*!< I2S data length is 32 bit and channel length is 32 bit */ + +/* I2S master clock output */ +#define I2S_MCKOUT_DISABLE ((uint32_t)0x00000000U) /*!< I2S master clock output disable */ +#define I2S_MCKOUT_ENABLE SPI_I2SPSC_MCKOEN /*!< I2S master clock output enable */ + +/* I2S operation mode */ +#define I2SCTL_I2SOPMOD(regval) (BITS(8, 9) & ((uint32_t)(regval) << 8)) +#define I2S_MODE_SLAVETX I2SCTL_I2SOPMOD(0) /*!< I2S slave transmit mode */ +#define I2S_MODE_SLAVERX I2SCTL_I2SOPMOD(1) /*!< I2S slave receive mode */ +#define I2S_MODE_MASTERTX I2SCTL_I2SOPMOD(2) /*!< I2S master transmit mode */ +#define I2S_MODE_MASTERRX I2SCTL_I2SOPMOD(3) /*!< I2S master receive mode */ + +/* I2S standard */ +#define I2SCTL_I2SSTD(regval) (BITS(4, 5) & ((uint32_t)(regval) << 4)) +#define I2S_STD_PHILLIPS I2SCTL_I2SSTD(0) /*!< I2S phillips standard */ +#define I2S_STD_MSB I2SCTL_I2SSTD(1) /*!< I2S MSB standard */ +#define I2S_STD_LSB I2SCTL_I2SSTD(2) /*!< I2S LSB standard */ +#define I2S_STD_PCMSHORT I2SCTL_I2SSTD(3) /*!< I2S PCM short standard */ +#define I2S_STD_PCMLONG (I2SCTL_I2SSTD(3) | SPI_I2SCTL_PCMSMOD) /*!< I2S PCM long standard */ + +/* I2S clock polarity */ +#define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ +#define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ + +/* SPI DMA constants definitions */ +#define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ +#define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ + +/* SPI CRC constants definitions */ +#define SPI_CRC_TX ((uint8_t)0x00U) /*!< SPI transmit CRC value */ +#define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ + +/* SPI/I2S interrupt enable/disable constants definitions */ +#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ + +/* SPI/I2S interrupt flag constants definitions */ +#define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt flag */ +#define SPI_I2S_INT_FLAG_RXORERR ((uint8_t)0x02U) /*!< overrun interrupt flag */ +#define SPI_INT_FLAG_CONFERR ((uint8_t)0x03U) /*!< config error interrupt flag */ +#define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ +#define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ +#define SPI_I2S_INT_FLAG_FERR ((uint8_t)0x06U) /*!< format error interrupt flag */ + +/* SPI/I2S flag definitions */ +#define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ +#define SPI_FLAG_CONFERR SPI_STAT_CONFERR /*!< mode config error flag */ +#define SPI_FLAG_RXORERR SPI_STAT_RXORERR /*!< receive overrun error flag */ +#define SPI_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define SPI_FLAG_FERR SPI_STAT_FERR /*!< format error interrupt flag */ +#define I2S_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ +#define I2S_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ +#define I2S_FLAG_CH SPI_STAT_I2SCH /*!< channel side flag */ +#define I2S_FLAG_TXURERR SPI_STAT_TXURERR /*!< underrun error flag */ +#define I2S_FLAG_RXORERR SPI_STAT_RXORERR /*!< overrun error flag */ +#define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ +#define I2S_FLAG_FERR SPI_STAT_FERR /*!< format error interrupt flag */ + +/* function declarations */ +/* SPI/I2S deinitialization and initialization functions */ +/* reset SPI and I2S */ +void spi_i2s_deinit(uint32_t spi_periph); +/* initialize the parameters of SPI struct with the default values */ +void spi_struct_para_init(spi_parameter_struct *spi_struct); +/* initialize SPI parameter */ +void spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct); +/* enable SPI */ +void spi_enable(uint32_t spi_periph); +/* disable SPI */ +void spi_disable(uint32_t spi_periph); + +/* initialize I2S parameter */ +void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl); +/* configure I2S prescaler */ +void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +/* enable I2S */ +void i2s_enable(uint32_t spi_periph); +/* disable I2S */ +void i2s_disable(uint32_t spi_periph); + +/* NSS functions */ +/* enable SPI NSS output */ +void spi_nss_output_enable(uint32_t spi_periph); +/* disable SPI NSS output */ +void spi_nss_output_disable(uint32_t spi_periph); +/* SPI NSS pin high level in software mode */ +void spi_nss_internal_high(uint32_t spi_periph); +/* SPI NSS pin low level in software mode */ +void spi_nss_internal_low(uint32_t spi_periph); + +/* DMA communication */ +/* enable SPI DMA */ +void spi_dma_enable(uint32_t spi_periph, uint8_t dma); +/* disable SPI DMA */ +void spi_dma_disable(uint32_t spi_periph, uint8_t dma); + +/* normal mode communication */ +/* configure SPI/I2S data frame format */ +void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* SPI transmit data */ +void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); +/* SPI receive data */ +uint16_t spi_i2s_data_receive(uint32_t spi_periph); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); + +/* SPI CRC functions */ +/* set SPI CRC polynomial */ +void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly); +/* get SPI CRC polynomial */ +uint16_t spi_crc_polynomial_get(uint32_t spi_periph); +/* turn on SPI CRC function */ +void spi_crc_on(uint32_t spi_periph); +/* turn off SPI CRC function */ +void spi_crc_off(uint32_t spi_periph); +/* SPI next data is CRC value */ +void spi_crc_next(uint32_t spi_periph); +/* get SPI CRC send value or receive value */ +uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); + +/* SPI TI mode functions */ +/* enable SPI TI mode */ +void spi_ti_mode_enable(uint32_t spi_periph); +/* disable SPI TI mode */ +void spi_ti_mode_disable(uint32_t spi_periph); + +/* SPI NSS pulse mode functions */ +/* enable SPI NSS pulse mode */ +void spi_nssp_mode_enable(uint32_t spi_periph); +/* disable SPI NSS pulse mode */ +void spi_nssp_mode_disable(uint32_t spi_periph); +/* flag and interrupt functions */ +/* enable SPI and I2S interrupt */ +void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); +/* disable SPI and I2S interrupt */ +void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S interrupt status */ +FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +#endif /* GD32VF103_SPI_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.c new file mode 100644 index 00000000..e297adfc --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.c @@ -0,0 +1,1966 @@ +/*! + \file gd32vf103_timer.c + \brief TIMER driver + + \version 2019-06-05, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#include "gd32vf103_timer.h" + +/* TIMER init parameter mask */ +#define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ +#define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ +#define CLOCKDIVISION_MASK ((uint32_t)0x00000300U) /*!< TIMER init parameter clock division value mask */ + +/*! + \brief deinit a timer + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_deinit(uint32_t timer_periph) +{ + switch(timer_periph){ + case TIMER0: + /* reset TIMER0 */ + rcu_periph_reset_enable(RCU_TIMER0RST); + rcu_periph_reset_disable(RCU_TIMER0RST); + break; + case TIMER1: + /* reset TIMER1 */ + rcu_periph_reset_enable(RCU_TIMER1RST); + rcu_periph_reset_disable(RCU_TIMER1RST); + break; + case TIMER2: + /* reset TIMER2 */ + rcu_periph_reset_enable(RCU_TIMER2RST); + rcu_periph_reset_disable(RCU_TIMER2RST); + break; + case TIMER3: + /* reset TIMER3 */ + rcu_periph_reset_enable(RCU_TIMER3RST); + rcu_periph_reset_disable(RCU_TIMER3RST); + break; + case TIMER4: + /* reset TIMER4 */ + rcu_periph_reset_enable(RCU_TIMER4RST); + rcu_periph_reset_disable(RCU_TIMER4RST); + break; + case TIMER5: + /* reset TIMER5 */ + rcu_periph_reset_enable(RCU_TIMER5RST); + rcu_periph_reset_disable(RCU_TIMER5RST); + break; + case TIMER6: + /* reset TIMER6 */ + rcu_periph_reset_enable(RCU_TIMER6RST); + rcu_periph_reset_disable(RCU_TIMER6RST); + break; + + default: + break; + } +} + +/*! + \brief initialize TIMER init parameter struct with a default value + \param[in] initpara: init parameter struct + \param[out] none + \retval none +*/ +void timer_struct_para_init(timer_parameter_struct* initpara) +{ + /* initialize the init parameter struct member with the default value */ + initpara->prescaler = 0U; + initpara->alignedmode = TIMER_COUNTER_EDGE; + initpara->counterdirection = TIMER_COUNTER_UP; + initpara->period = 65535U; + initpara->clockdivision = TIMER_CKDIV_DIV1; + initpara->repetitioncounter = 0U; +} + +/*! + \brief initialize TIMER counter + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] initpara: init parameter struct + prescaler: prescaler value of the counter clock, 0~65535 + alignedmode: TIMER_COUNTER_EDGE, TIMER_COUNTER_CENTER_DOWN, TIMER_COUNTER_CENTER_UP, + TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP, TIMER_COUNTER_DOWN + period: counter auto reload value, 0~65535 + clockdivision: TIMER_CKDIV_DIV1, TIMER_CKDIV_DIV2, TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value, 0~255 + \param[out] none + \retval none +*/ +void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +{ + /* configure the counter prescaler value */ + TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; + + /* configure the counter direction and aligned mode */ + if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) + || (TIMER3 == timer_periph) || (TIMER4 == timer_periph) ){ + TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + }else{ + TIMER_CTL0(timer_periph) &= (uint32_t)(~ TIMER_CTL0_DIR); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); + } + + /* configure the autoreload value */ + TIMER_CAR(timer_periph) = (uint32_t)initpara->period; + + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + /* reset the CKDIV bit */ + TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); + TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); + } + + if (TIMER0 == timer_periph) { + /* configure the repetition counter value */ + TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; + } + + /* generate an update event */ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; +} + +/*! + \brief enable a timer + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief disable a timer + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CEN; +} + +/*! + \brief enable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief disable the auto reload shadow function + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_auto_reload_shadow_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_ARSE; +} + +/*! + \brief enable the update event + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_update_event_enable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPDIS; +} + +/*! + \brief disable the update event + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval none +*/ +void timer_update_event_disable(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t) TIMER_CTL0_UPDIS; +} + +/*! + \brief set TIMER counter alignment mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] aligned: + only one parameter can be selected which is shown as below: + \arg TIMER_COUNTER_EDGE: edge-aligned mode + \arg TIMER_COUNTER_CENTER_DOWN: center-aligned and counting down assert mode + \arg TIMER_COUNTER_CENTER_UP: center-aligned and counting up assert mode + \arg TIMER_COUNTER_CENTER_BOTH: center-aligned and counting up/down assert mode + \param[out] none + \retval none +*/ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) +{ + TIMER_CTL0(timer_periph) &= (uint32_t)(~TIMER_CTL0_CAM); + TIMER_CTL0(timer_periph) |= (uint32_t)aligned; +} + +/*! + \brief set TIMER counter up direction + \param[in] timer_periph: TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_counter_up_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief set TIMER counter down direction + \param[in] timer_periph: TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_counter_down_direction(uint32_t timer_periph) +{ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_DIR; +} + +/*! + \brief configure TIMER prescaler + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] prescaler: prescaler value + \param[in] pscreload: prescaler reload mode + only one parameter can be selected which is shown as below: + \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now + \arg TIMER_PSC_RELOAD_UPDATE: the prescaler is loaded at the next update event + \param[out] none + \retval none +*/ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) +{ + TIMER_PSC(timer_periph) = (uint32_t)prescaler; + + if(TIMER_PSC_RELOAD_NOW == pscreload){ + TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; + } +} + +/*! + \brief configure TIMER repetition register value + \param[in] timer_periph: TIMERx(x=0) + \param[in] repetition: the counter repetition value, 0~255 + \param[out] none + \retval none +*/ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) +{ + TIMER_CREP(timer_periph) = (uint32_t)repetition; +} + +/*! + \brief configure TIMER autoreload register value + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] autoreload: the counter auto-reload value + \param[out] none + \retval none +*/ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload) +{ + TIMER_CAR(timer_periph) = (uint32_t)autoreload; +} + +/*! + \brief configure TIMER counter register value + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] counter: the counter value + \param[out] none + \retval none +*/ +void timer_counter_value_config(uint32_t timer_periph, uint16_t counter) +{ + TIMER_CNT(timer_periph) = (uint32_t)counter; +} + +/*! + \brief read TIMER counter value + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval counter value +*/ +uint32_t timer_counter_read(uint32_t timer_periph) +{ + uint32_t count_value = 0U; + count_value = TIMER_CNT(timer_periph); + return (count_value); +} + +/*! + \brief read TIMER prescaler value + \param[in] timer_periph: TIMERx(x=0..6) + \param[out] none + \retval prescaler register value +*/ +uint16_t timer_prescaler_read(uint32_t timer_periph) +{ + uint16_t prescaler_value = 0U; + prescaler_value = (uint16_t) (TIMER_PSC(timer_periph)); + return (prescaler_value); +} + +/*! + \brief configure TIMER single pulse mode + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] spmode: + only one parameter can be selected which is shown as below: + \arg TIMER_SP_MODE_SINGLE: single pulse mode + \arg TIMER_SP_MODE_REPETITIVE: repetitive pulse mode + \param[out] none + \retval none +*/ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) +{ + if(TIMER_SP_MODE_SINGLE == spmode){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; + }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER update source + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] update: + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATE_SRC_GLOBAL: update generate by setting of UPG bit or the counter overflow/underflow, + or the slave mode controller trigger + \arg TIMER_UPDATE_SRC_REGULAR: update generate only by counter overflow/underflow + \param[out] none + \retval none +*/ +void timer_update_source_config(uint32_t timer_periph, uint32_t update) +{ + if(TIMER_UPDATE_SRC_REGULAR == update){ + TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; + }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; + }else{ + /* illegal parameters */ + } +} + + +/*! + \brief enable the TIMER DMA + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] dma: specify which DMA to enable + one or more parameters can be selected which are shown as below: + \arg TIMER_DMA_UPD: update DMA enable, TIMERx(x=0..6) + \arg TIMER_DMA_CH0D: channel 0 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH1D: channel 1 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH2D: channel 2 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH3D: channel 3 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CMTD: channel commutation DMA request enable, TIMERx(x=0) + \arg TIMER_DMA_TRGD: trigger DMA enable, TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; +} + +/*! + \brief disable the TIMER DMA + \param[in] timer_periph: TIMERxTIMERx(x=0..6) + \param[in] dma: specify which DMA to disbale + one or more parameters can be selected which are shown as below: + \arg TIMER_DMA_UPD: update DMA enable, TIMERx(x=0..6) + \arg TIMER_DMA_CH0D: channel 0 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH1D: channel 1 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH2D: channel 2 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CH3D: channel 3 DMA enable, TIMERx(x=0..4) + \arg TIMER_DMA_CMTD: channel commutation DMA request enable, TIMERx(x=0) + \arg TIMER_DMA_TRGD: trigger DMA enable, TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); +} + +/*! + \brief channel DMA request source selection + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] dma_request: channel DMA request source selection + only one parameter can be selected which is shown as below: + \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel n is sent when channel n event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel n is sent when update event occurs + \param[out] none + \retval none +*/ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) +{ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; + }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure the TIMER DMA transfer + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] dma_baseaddr: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATA_CTL0: DMA transfer address is TIMER_CTL0, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CTL1: DMA transfer address is TIMER_CTL1, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_SMCFG: DMA transfer address is TIMER_SMCFG, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_DMAINTEN: DMA transfer address is TIMER_DMAINTEN, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_INTF: DMA transfer address is TIMER_INTF, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_SWEVG: DMA transfer address is TIMER_SWEVG, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CHCTL0: DMA transfer address is TIMER_CHCTL0, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CHCTL1: DMA transfer address is TIMER_CHCTL1, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CHCTL2: DMA transfer address is TIMER_CHCTL2, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CNT: DMA transfer address is TIMER_CNT, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_PSC: DMA transfer address is TIMER_PSC, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CAR: DMA transfer address is TIMER_CAR, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CREP: DMA transfer address is TIMER_CREP, TIMERx(x=0) + \arg TIMER_DMACFG_DMATA_CH0CV: DMA transfer address is TIMER_CH0CV, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CH1CV: DMA transfer address is TIMER_CH1CV, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CH2CV: DMA transfer address is TIMER_CH2CV, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CH3CV: DMA transfer address is TIMER_CH3CV, TIMERx(x=0..4) + \arg TIMER_DMACFG_DMATA_CCHP: DMA transfer address is TIMER_CCHP, TIMERx(x=0) + \arg TIMER_DMACFG_DMATA_DMACFG: DMA transfer address is TIMER_DMACFG, TIMERx(x=0..4) + \param[in] dma_lenth: + only one parameter can be selected which is shown as below: + \arg TIMER_DMACFG_DMATC_xTRANSFER(x=1..6): DMA transfer x time + \param[out] none + \retval none +*/ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) +{ + TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); +} + +/*! + \brief software generate events + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] event: the timer software event generation sources + one or more parameters can be selected which are shown as below: + \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..6) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4) + \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0) + \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4) + \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event) +{ + TIMER_SWEVG(timer_periph) |= (uint32_t)event; +} + +/*! + \brief initialize TIMER break parameter struct with a default value + \param[in] breakpara: TIMER break parameter struct + \param[out] none + \retval none +*/ +void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +{ + /* initialize the break parameter struct member with the default value */ + breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; + breakpara->ideloffstate = TIMER_IOS_STATE_DISABLE; + breakpara->deadtime = 0U; + breakpara->breakpolarity = TIMER_BREAK_POLARITY_LOW; + breakpara->outputautostate = TIMER_OUTAUTO_DISABLE; + breakpara->protectmode = TIMER_CCHP_PROT_OFF; + breakpara->breakstate = TIMER_BREAK_DISABLE; +} + +/*! + \brief configure TIMER break function + \param[in] timer_periph: TIMERx(x=0) + \param[in] breakpara: TIMER break parameter struct + runoffstate: TIMER_ROS_STATE_ENABLE, TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE, TIMER_IOS_STATE_DISABLE + deadtime: 0~255 + breakpolarity: TIMER_BREAK_POLARITY_LOW, TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE, TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF, TIMER_CCHP_PROT_0, TIMER_CCHP_PROT_1, TIMER_CCHP_PROT_2 + breakstate: TIMER_BREAK_ENABLE, TIMER_BREAK_DISABLE + \param[out] none + \retval none +*/ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +{ + TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | + ((uint32_t)(breakpara->ideloffstate))| + ((uint32_t)(breakpara->deadtime)) | + ((uint32_t)(breakpara->breakpolarity)) | + ((uint32_t)(breakpara->outputautostate)) | + ((uint32_t)(breakpara->protectmode)) | + ((uint32_t)(breakpara->breakstate))); +} + +/*! + \brief enable TIMER break function + \param[in] timer_periph: TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_break_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief disable TIMER break function + \param[in] timer_periph: TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_break_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_BRKEN; +} + +/*! + \brief enable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_automatic_output_enable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief disable TIMER output automatic function + \param[in] timer_periph: TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_automatic_output_disable(uint32_t timer_periph) +{ + TIMER_CCHP(timer_periph) &= ~(uint32_t)TIMER_CCHP_OAEN; +} + +/*! + \brief enable or disable TIMER primary output function + \param[in] timer_periph: TIMERx(x=0) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; + }else{ + TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); + } +} + +/*! + \brief enable or disable channel capture/compare control shadow register + \param[in] timer_periph: TIMERx(x=0) + \param[in] newvalue: ENABLE or DISABLE + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) +{ + if(ENABLE == newvalue){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; + }else{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); + } +} + +/*! + \brief configure TIMER channel control shadow register update control + \param[in] timer_periph: TIMERx(x=0) + \param[in] ccuctl: channel control shadow register update control + only one parameter can be selected which is shown as below: + \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \param[out] none + \retval none +*/ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) +{ + if(TIMER_UPDATECTL_CCU == ccuctl){ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); + }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief initialize TIMER channel output parameter struct with a default value + \param[in] ocpara: TIMER channel n output parameter struct + \param[out] none + \retval none +*/ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +{ + /* initialize the channel output parameter struct member with the default value */ + ocpara->outputstate = TIMER_CCX_DISABLE; + ocpara->outputnstate = TIMER_CCXN_DISABLE; + ocpara->ocpolarity = TIMER_OC_POLARITY_HIGH; + ocpara->ocnpolarity = TIMER_OCN_POLARITY_HIGH; + ocpara->ocidlestate = TIMER_OC_IDLE_STATE_LOW; + ocpara->ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +} + +/*! + \brief configure TIMER channel output function + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] ocpara: TIMER channeln output parameter struct + outputstate: TIMER_CCX_ENABLE, TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE, TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH, TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH, TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW, TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW, TIMER_OCN_IDLE_STATE_HIGH + \param[out] none + \retval none +*/ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputstate; + /* reset the CH0P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + /* set the CH0P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; + + if (TIMER0 == timer_periph) { + /* reset the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + /* set the CH0NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->outputnstate; + /* reset the CH0NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + /* set the CH0NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocnpolarity; + /* reset the ISO0 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0); + /* set the ISO0 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocidlestate; + /* reset the ISO0N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO0N); + /* set the ISO0N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)ocpara->ocnidlestate; + } + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH0MS; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 4U); + /* reset the CH1P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + /* set the CH1P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); + + if (TIMER0 == timer_periph) { + /* reset the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + /* set the CH1NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); + /* reset the ISO1 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); + /* set the ISO1 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); + /* reset the ISO1N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); + /* set the ISO1N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); + } + TIMER_CHCTL0(timer_periph) &= ~(uint32_t)TIMER_CHCTL0_CH1MS; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 8U); + /* reset the CH2P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + /* set the CH2P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); + + if (TIMER0 == timer_periph) { + /* reset the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + /* set the CH2NEN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); + /* reset the CH2NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + /* set the CH2NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); + /* reset the ISO2 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); + /* set the ISO2 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); + /* reset the ISO2N bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); + /* set the ISO2N bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); + } + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH2MS; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); + /* reset the CH3P bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + /* set the CH3P bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); + + if (TIMER0 == timer_periph) { + /* reset the ISO3 bit */ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); + /* set the ISO3 bit */ + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); + } + TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output compare mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] ocmode: channel output compare mode + only one parameter can be selected which is shown as below: + \arg TIMER_OC_MODE_TIMING: timing mode + \arg TIMER_OC_MODE_ACTIVE: active mode + \arg TIMER_OC_MODE_INACTIVE: inactive mode + \arg TIMER_OC_MODE_TOGGLE: toggle mode + \arg TIMER_OC_MODE_LOW: force low mode + \arg TIMER_OC_MODE_HIGH: force high mode + \arg TIMER_OC_MODE_PWM0: PWM mode 0 + \arg TIMER_OC_MODE_PWM1: PWM mode 1 + \param[out] none + \retval none +*/ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocmode; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output pulse value + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] pulse: channel output pulse value + \param[out] none + \retval none +*/ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CH0CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CH1CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CH2CV(timer_periph) = (uint32_t)pulse; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output shadow function + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] ocshadow: channel output shadow state + only one parameter can be selected which is shown as below: + \arg TIMER_OC_SHADOW_ENABLE: channel output shadow state enable + \arg TIMER_OC_SHADOW_DISABLE: channel output shadow state disable + \param[out] none + \retval none +*/ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMSEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocshadow; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMSEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocshadow) << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output fast function + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] ocfast: channel output fast function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_FAST_ENABLE: channel output fast function enable + \arg TIMER_OC_FAST_DISABLE: channel output fast function disable + \param[out] none + \retval none +*/ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMFEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)ocfast; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMFEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)ocfast << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output clear function + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] occlear: channel output clear function + only one parameter can be selected which is shown as below: + \arg TIMER_OC_CLEAR_ENABLE: channel output clear function enable + \arg TIMER_OC_CLEAR_DISABLE: channel output clear function disable + \param[out] none + \retval none +*/ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCEN); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)occlear; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCEN); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)occlear << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel output polarity + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] ocpolarity: channel output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OC_POLARITY_HIGH: channel output polarity is high + \arg TIMER_OC_POLARITY_LOW: channel output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocpolarity << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output polarity + \param[in] timer_periph: TIMERx(x=0) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0)) + \param[in] ocnpolarity: channel complementary output polarity + only one parameter can be selected which is shown as below: + \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high + \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnpolarity; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnpolarity << 8U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel enable state + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] state: TIMER channel enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable + \param[out] none + \retval none +*/ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)state; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 8U); + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)state << 12U); + break; + default: + break; + } +} + +/*! + \brief configure TIMER channel complementary output enable state + \param[in] timer_periph: TIMERx(x=0) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0 + \arg TIMER_CH_1: TIMER channel 1 + \arg TIMER_CH_2: TIMER channel 2 + \param[in] ocnstate: TIMER channel complementary output enable state + only one parameter can be selected which is shown as below: + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable + \param[out] none + \retval none +*/ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)ocnstate; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 4U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)ocnstate << 8U); + break; + default: + break; + } +} + +/*! + \brief initialize TIMER channel input parameter struct with a default value + \param[in] icpara: TIMER channel intput parameter struct + \param[out] none + \retval none +*/ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +{ + /* initialize the channel input parameter struct member with the default value */ + icpara->icpolarity = TIMER_IC_POLARITY_RISING; + icpara->icselection = TIMER_IC_SELECTION_DIRECTTI; + icpara->icprescaler = TIMER_IC_PSC_DIV1; + icpara->icfilter = 0U; +} + +/*! + \brief configure TIMER input capture parameter + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] icpara: TIMER channel intput parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, + TIMER_IC_SELECTION_ITS + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpara->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpara->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + break; + + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + /* reset the CH2EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2EN); + + /* reset the CH2P and CH2NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH2P | TIMER_CHCTL2_CH2NP)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 8U); + + /* reset the CH2MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection)); + + /* reset the CH2CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 4U); + + /* set the CH2EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH2EN; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + /* reset the CH3EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); + + /* reset the CH3P bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH3P)); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpara->icpolarity) << 12U); + + /* reset the CH3MS bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3MS); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icselection) << 8U); + + /* reset the CH3CAPFLT bit */ + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPFLT); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(icpara->icfilter) << 12U); + + /* set the CH3EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH3EN; + break; + default: + break; + } + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); +} + +/*! + \brief configure TIMER channel input capture prescaler value + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[in] prescaler: channel input capture prescaler value + only one parameter can be selected which is shown as below: + \arg TIMER_IC_PSC_DIV1: no prescaler + \arg TIMER_IC_PSC_DIV2: divided by 2 + \arg TIMER_IC_PSC_DIV4: divided by 4 + \arg TIMER_IC_PSC_DIV8: divided by 8 + \param[out] none + \retval none +*/ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) +{ + switch(channel){ + /* configure TIMER_CH_0 */ + case TIMER_CH_0: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); + TIMER_CHCTL0(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_1 */ + case TIMER_CH_1: + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPPSC); + TIMER_CHCTL0(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + /* configure TIMER_CH_2 */ + case TIMER_CH_2: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH2CAPPSC); + TIMER_CHCTL1(timer_periph) |= (uint32_t)prescaler; + break; + /* configure TIMER_CH_3 */ + case TIMER_CH_3: + TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3CAPPSC); + TIMER_CHCTL1(timer_periph) |= ((uint32_t)prescaler << 8U); + break; + default: + break; + } +} + +/*! + \brief read TIMER channel capture compare register value + \param[in] timer_periph: please refer to the following parameters + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4)) + \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4)) + \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4)) + \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4)) + \param[out] none + \retval channel capture compare register value +*/ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) +{ + uint32_t count_value = 0U; + + switch(channel){ + case TIMER_CH_0: + /* read TIMER channel 0 capture compare register value */ + count_value = TIMER_CH0CV(timer_periph); + break; + case TIMER_CH_1: + /* read TIMER channel 1 capture compare register value */ + count_value = TIMER_CH1CV(timer_periph); + break; + case TIMER_CH_2: + /* read TIMER channel 2 capture compare register value */ + count_value = TIMER_CH2CV(timer_periph); + break; + case TIMER_CH_3: + /* read TIMER channel 3 capture compare register value */ + count_value = TIMER_CH3CV(timer_periph); + break; + default: + break; + } + return (count_value); +} + +/*! + \brief configure TIMER input pwm capture function + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] channel: + only one parameter can be selected which is shown as below: + \arg TIMER_CH_0: TIMER channel 0 + \arg TIMER_CH_1: TIMER channel 1 + \param[in] icpwm: TIMER channel intput pwm parameter struct + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, + TIMER_IC_PSC_DIV8 + icfilter: 0~15 + \param[out] none + \retval none +*/ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +{ + uint16_t icpolarity = 0x0U; + uint16_t icselection = 0x0U; + + /* Set channel input polarity */ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + icpolarity = TIMER_IC_POLARITY_FALLING; + }else{ + icpolarity = TIMER_IC_POLARITY_RISING; + } + /* Set channel input mode selection */ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + icselection = TIMER_IC_SELECTION_INDIRECTTI; + }else{ + icselection = TIMER_IC_SELECTION_DIRECTTI; + } + + if(TIMER_CH_0 == channel){ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)(icpwm->icpolarity); + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(icpwm->icselection); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); + + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); + }else{ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + /* set the CH1P and CH1NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); + + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)icselection; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* set the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= ((uint32_t)(icpwm->icfilter) << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + /* configure TIMER channel input capture prescaler value */ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); + } +} + +/*! + \brief configure TIMER hall sensor mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] hallmode: + only one parameter can be selected which is shown as below: + \arg TIMER_HALLINTERFACE_ENABLE: TIMER hall sensor mode enable + \arg TIMER_HALLINTERFACE_DISABLE: TIMER hall sensor mode disable + \param[out] none + \retval none +*/ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +{ + if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; + }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief select TIMER input trigger source + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1(TIMERx(x=0..4)) + \arg TIMER_SMCFG_TRGSEL_ETIFP: filtered external trigger input(TIMERx(x=0..4)) + \param[out] none + \retval none +*/ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); + TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; +} + +/*! + \brief select TIMER master mode output trigger source + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] outrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..6)) + \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..6)) + \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..6)) + \arg TIMER_TRI_OUT_SRC_CH0: a capture or a compare match occurred in channel 0 as trigger output TRGO(TIMERx(x=0..4)) + \arg TIMER_TRI_OUT_SRC_O0CPRE: O0CPRE as trigger output(TIMERx(x=0..4)) + \arg TIMER_TRI_OUT_SRC_O1CPRE: O1CPRE as trigger output(TIMERx(x=0..4)) + \arg TIMER_TRI_OUT_SRC_O2CPRE: O2CPRE as trigger output(TIMERx(x=0..4)) + \arg TIMER_TRI_OUT_SRC_O3CPRE: O3CPRE as trigger output(TIMERx(x=0..4)) + \param[out] none + \retval none +*/ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger) +{ + TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_MMC); + TIMER_CTL1(timer_periph) |= (uint32_t)outrigger; +} + +/*! + \brief select TIMER slave mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] slavemode: + only one parameter can be selected which is shown as below: + \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable + \arg TIMER_ENCODER_MODE0: encoder mode 0 + \arg TIMER_ENCODER_MODE1: encoder mode 1 + \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_SLAVE_MODE_RESTART: restart mode + \arg TIMER_SLAVE_MODE_PAUSE: pause mode + \arg TIMER_SLAVE_MODE_EVENT: event mode + \arg TIMER_SLAVE_MODE_EXTERNAL0: external clock mode 0 + \param[out] none + \retval none +*/ + +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)slavemode; +} + +/*! + \brief configure TIMER master slave mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] masterslave: + only one parameter can be selected which is shown as below: + \arg TIMER_MASTER_SLAVE_MODE_ENABLE: master slave mode enable + \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable + \param[out] none + \retval none +*/ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) +{ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; + }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; + }else{ + /* illegal parameters */ + } +} + +/*! + \brief configure TIMER external trigger input + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) +{ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); + TIMER_SMCFG(timer_periph) |= (uint32_t)(extfilter << 8U); +} + +/*! + \brief configure TIMER quadrature decoder mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] decomode: + only one parameter can be selected which is shown as below: + \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \param[in] ic0polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[in] ic1polarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: capture rising edge + \arg TIMER_IC_POLARITY_FALLING: capture falling edge + \param[out] none + \retval none +*/ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity) +{ + /* configure the quadrature decoder mode */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + TIMER_SMCFG(timer_periph) |= (uint32_t)decomode; + /* configure input capture selection */ + TIMER_CHCTL0(timer_periph) &= (uint32_t)(((~(uint32_t)TIMER_CHCTL0_CH0MS)) & ((~(uint32_t)TIMER_CHCTL0_CH1MS))); + TIMER_CHCTL0(timer_periph) |= (uint32_t)(TIMER_IC_SELECTION_DIRECTTI | ((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U)); + /* configure channel input capture polarity */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) |= ((uint32_t)ic0polarity | ((uint32_t)ic1polarity << 4U)); +} + +/*! + \brief configure TIMER internal clock mode + \param[in] timer_periph: TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_internal_clock_config(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; +} + +/*! + \brief configure TIMER the internal trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] intrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2 + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3 + \param[out] none + \retval none +*/ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) +{ + timer_input_trigger_source_select(timer_periph, intrigger); + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external trigger as external clock input + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] extrigger: + only one parameter can be selected which is shown as below: + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_IC_POLARITY_RISING: active low or falling edge active + \arg TIMER_IC_POLARITY_FALLING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter) +{ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + /* reset the CH1EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); + /* reset the CH1NP bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); + /* set the CH1NP bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); + /* reset the CH1MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); + /* set the CH1MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); + /* reset the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); + /* set the CH1CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); + /* set the CH1EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; + }else{ + /* reset the CH0EN bit */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); + /* reset the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); + /* set the CH0P and CH0NP bits */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; + /* reset the CH0MS bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0MS); + /* set the CH0MS bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)TIMER_IC_SELECTION_DIRECTTI; + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPFLT); + /* reset the CH0CAPFLT bit */ + TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 4U); + /* set the CH0EN bit */ + TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; + } + /* select TIMER input trigger source */ + timer_input_trigger_source_select(timer_periph, extrigger); + /* reset the SMC bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_SMC); + /* set the SMC bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; +} + +/*! + \brief configure TIMER the external clock mode0 + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + /* reset the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + /* set the SMC bit,TRGS bit */ + TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); +} + +/*! + \brief configure TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4) + \param[in] extprescaler: + only one parameter can be selected which is shown as below: + \arg TIMER_EXT_TRI_PSC_OFF: no divided + \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 + \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 + \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 + \param[in] extpolarity: + only one parameter can be selected which is shown as below: + \arg TIMER_ETP_FALLING: active low or falling edge active + \arg TIMER_ETP_RISING: active high or rising edge active + \param[in] extfilter: a value between 0 and 15 + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) +{ + /* configure TIMER external trigger input */ + timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); + TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief disable TIMER the external clock mode1 + \param[in] timer_periph: TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_external_clock_mode1_disable(uint32_t timer_periph) +{ + TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; +} + +/*! + \brief enable the TIMER interrupt + \param[in] timer_periph: please refer to the following parameters + \param[in] interrupt: specify which interrupt to enable + one or more parameters can be selected which are shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..6) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH3: channel 3 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; +} + +/*! + \brief disable the TIMER interrupt + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] interrupt: specify which interrupt to disbale + one or more parameters can be selected which are shown as below: + \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..6) + \arg TIMER_INT_CH0: channel 0 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH1: channel 1 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH2: channel 2 interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_CH3: channel 3 interrupt enable , TIMERx(x=0..4) + \arg TIMER_INT_CMT: commutation interrupt enable, TIMERx(x=0) + \arg TIMER_INT_TRG: trigger interrupt enable, TIMERx(x=0..4) + \arg TIMER_INT_BRK: break interrupt enable, TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); +} + +/*! + \brief get timer interrupt flag + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] interrupt: the timer interrupt bits + only one parameter can be selected which is shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag, TIMERx(x=0..6) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag, TIMERx(x=0) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag, TIMERx(x=0) + \arg TIMER_INT_FLAG_BRK: break interrupt flag, TIMERx(x=0) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +{ + uint32_t val; + val = (TIMER_DMAINTEN(timer_periph) & interrupt); + if((RESET != (TIMER_INTF(timer_periph) & interrupt)) && (RESET != val)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER interrupt flag + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] interrupt: the timer interrupt bits + one or more parameters can be selected which are shown as below: + \arg TIMER_INT_FLAG_UP: update interrupt flag, TIMERx(x=0..6) + \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag, TIMERx(x=0) + \arg TIMER_INT_FLAG_TRG: trigger interrupt flag, TIMERx(x=0..4) + \arg TIMER_INT_FLAG_BRK: break interrupt flag, TIMERx(x=0) + \param[out] none + \retval none +*/ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); +} + +/*! + \brief get TIMER flags + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag, TIMERx(x=0..6) + \arg TIMER_FLAG_CH0: channel 0 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH1: channel 1 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH2: channel 2 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH3: channel 3 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CMT: channel commutation flag, TIMERx(x=0) + \arg TIMER_FLAG_TRG: trigger flag, TIMERx(x=0..4) + \arg TIMER_FLAG_BRK: break flag, TIMERx(x=0) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag, TIMERx(x=0..4) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: TIMERx(x=0..6) + \param[in] flag: the timer interrupt flags + one or more parameters can be selected which are shown as below: + \arg TIMER_FLAG_UP: update flag, TIMERx(x=0..6) + \arg TIMER_FLAG_CH0: channel 0 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH1: channel 1 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH2: channel 2 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH3: channel 3 flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CMT: channel commutation flag, TIMERx(x=0) + \arg TIMER_FLAG_TRG: trigger flag, TIMERx(x=0..4) + \arg TIMER_FLAG_BRK: break flag, TIMERx(x=0) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag, TIMERx(x=0..4) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag, TIMERx(x=0..4) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.h new file mode 100644 index 00000000..c6af194b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_timer.h @@ -0,0 +1,726 @@ +/*! + \file gd32vf103_timer.h + \brief definitions for the TIMER + + \version 2019-06-05, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_TIMER_H +#define GD32VF103_TIMER_H + +#include "gd32vf103.h" + +/* TIMERx(x=0..13) definitions */ +#define TIMER0 (TIMER_BASE + 0x00012C00U) +#define TIMER1 (TIMER_BASE + 0x00000000U) +#define TIMER2 (TIMER_BASE + 0x00000400U) +#define TIMER3 (TIMER_BASE + 0x00000800U) +#define TIMER4 (TIMER_BASE + 0x00000C00U) +#define TIMER5 (TIMER_BASE + 0x00001000U) +#define TIMER6 (TIMER_BASE + 0x00001400U) + +/* registers definitions */ +#define TIMER_CTL0(timerx) REG32((timerx) + 0x00U) /*!< TIMER control register 0 */ +#define TIMER_CTL1(timerx) REG32((timerx) + 0x04U) /*!< TIMER control register 1 */ +#define TIMER_SMCFG(timerx) REG32((timerx) + 0x08U) /*!< TIMER slave mode configuration register */ +#define TIMER_DMAINTEN(timerx) REG32((timerx) + 0x0CU) /*!< TIMER DMA and interrupt enable register */ +#define TIMER_INTF(timerx) REG32((timerx) + 0x10U) /*!< TIMER interrupt flag register */ +#define TIMER_SWEVG(timerx) REG32((timerx) + 0x14U) /*!< TIMER software event generation register */ +#define TIMER_CHCTL0(timerx) REG32((timerx) + 0x18U) /*!< TIMER channel control register 0 */ +#define TIMER_CHCTL1(timerx) REG32((timerx) + 0x1CU) /*!< TIMER channel control register 1 */ +#define TIMER_CHCTL2(timerx) REG32((timerx) + 0x20U) /*!< TIMER channel control register 2 */ +#define TIMER_CNT(timerx) REG32((timerx) + 0x24U) /*!< TIMER counter register */ +#define TIMER_PSC(timerx) REG32((timerx) + 0x28U) /*!< TIMER prescaler register */ +#define TIMER_CAR(timerx) REG32((timerx) + 0x2CU) /*!< TIMER counter auto reload register */ +#define TIMER_CREP(timerx) REG32((timerx) + 0x30U) /*!< TIMER counter repetition register */ +#define TIMER_CH0CV(timerx) REG32((timerx) + 0x34U) /*!< TIMER channel 0 capture/compare value register */ +#define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ +#define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ +#define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ +#define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ + +/* bits definitions */ +/* TIMER_CTL0 */ +#define TIMER_CTL0_CEN BIT(0) /*!< TIMER counter enable */ +#define TIMER_CTL0_UPDIS BIT(1) /*!< update disable */ +#define TIMER_CTL0_UPS BIT(2) /*!< update source */ +#define TIMER_CTL0_SPM BIT(3) /*!< single pulse mode */ +#define TIMER_CTL0_DIR BIT(4) /*!< timer counter direction */ +#define TIMER_CTL0_CAM BITS(5, 6) /*!< center-aligned mode selection */ +#define TIMER_CTL0_ARSE BIT(7) /*!< auto-reload shadow enable */ +#define TIMER_CTL0_CKDIV BITS(8, 9) /*!< clock division */ + +/* TIMER_CTL1 */ +#define TIMER_CTL1_CCSE BIT(0) /*!< commutation control shadow enable */ +#define TIMER_CTL1_CCUC BIT(2) /*!< commutation control shadow register update control */ +#define TIMER_CTL1_DMAS BIT(3) /*!< DMA request source selection */ +#define TIMER_CTL1_MMC BITS(4, 6) /*!< master mode control */ +#define TIMER_CTL1_TI0S BIT(7) /*!< channel 0 trigger input selection(hall mode selection) */ +#define TIMER_CTL1_ISO0 BIT(8) /*!< idle state of channel 0 output */ +#define TIMER_CTL1_ISO0N BIT(9) /*!< idle state of channel 0 complementary output */ +#define TIMER_CTL1_ISO1 BIT(10) /*!< idle state of channel 1 output */ +#define TIMER_CTL1_ISO1N BIT(11) /*!< idle state of channel 1 complementary output */ +#define TIMER_CTL1_ISO2 BIT(12) /*!< idle state of channel 2 output */ +#define TIMER_CTL1_ISO2N BIT(13) /*!< idle state of channel 2 complementary output */ +#define TIMER_CTL1_ISO3 BIT(14) /*!< idle state of channel 3 output */ + +/* TIMER_SMCFG */ +#define TIMER_SMCFG_SMC BITS(0, 2) /*!< slave mode control */ +#define TIMER_SMCFG_TRGS BITS(4, 6) /*!< trigger selection */ +#define TIMER_SMCFG_MSM BIT(7) /*!< master-slave mode */ +#define TIMER_SMCFG_ETFC BITS(8, 11) /*!< external trigger filter control */ +#define TIMER_SMCFG_ETPSC BITS(12, 13) /*!< external trigger prescaler */ +#define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ +#define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ + +/* TIMER_DMAINTEN */ +#define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ +#define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH1IE BIT(2) /*!< channel 1 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH2IE BIT(3) /*!< channel 2 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CH3IE BIT(4) /*!< channel 3 capture/compare interrupt enable */ +#define TIMER_DMAINTEN_CMTIE BIT(5) /*!< commutation interrupt request enable */ +#define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ +#define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ +#define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ +#define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ + +/* TIMER_INTF */ +#define TIMER_INTF_UPIF BIT(0) /*!< update interrupt flag */ +#define TIMER_INTF_CH0IF BIT(1) /*!< channel 0 capture/compare interrupt flag */ +#define TIMER_INTF_CH1IF BIT(2) /*!< channel 1 capture/compare interrupt flag */ +#define TIMER_INTF_CH2IF BIT(3) /*!< channel 2 capture/compare interrupt flag */ +#define TIMER_INTF_CH3IF BIT(4) /*!< channel 3 capture/compare interrupt flag */ +#define TIMER_INTF_CMTIF BIT(5) /*!< channel commutation interrupt flag */ +#define TIMER_INTF_TRGIF BIT(6) /*!< trigger interrupt flag */ +#define TIMER_INTF_BRKIF BIT(7) /*!< break interrupt flag */ +#define TIMER_INTF_CH0OF BIT(9) /*!< channel 0 over capture flag */ +#define TIMER_INTF_CH1OF BIT(10) /*!< channel 1 over capture flag */ +#define TIMER_INTF_CH2OF BIT(11) /*!< channel 2 over capture flag */ +#define TIMER_INTF_CH3OF BIT(12) /*!< channel 3 over capture flag */ + +/* TIMER_SWEVG */ +#define TIMER_SWEVG_UPG BIT(0) /*!< update event generate */ +#define TIMER_SWEVG_CH0G BIT(1) /*!< channel 0 capture or compare event generation */ +#define TIMER_SWEVG_CH1G BIT(2) /*!< channel 1 capture or compare event generation */ +#define TIMER_SWEVG_CH2G BIT(3) /*!< channel 2 capture or compare event generation */ +#define TIMER_SWEVG_CH3G BIT(4) /*!< channel 3 capture or compare event generation */ +#define TIMER_SWEVG_CMTG BIT(5) /*!< channel commutation event generation */ +#define TIMER_SWEVG_TRGG BIT(6) /*!< trigger event generation */ +#define TIMER_SWEVG_BRKG BIT(7) /*!< break event generation */ + +/* TIMER_CHCTL0 */ +/* output compare mode */ +#define TIMER_CHCTL0_CH0MS BITS(0, 1) /*!< channel 0 mode selection */ +#define TIMER_CHCTL0_CH0COMFEN BIT(2) /*!< channel 0 output compare fast enable */ +#define TIMER_CHCTL0_CH0COMSEN BIT(3) /*!< channel 0 output compare shadow enable */ +#define TIMER_CHCTL0_CH0COMCTL BITS(4, 6) /*!< channel 0 output compare control */ +#define TIMER_CHCTL0_CH0COMCEN BIT(7) /*!< channel 0 output compare clear enable */ +#define TIMER_CHCTL0_CH1MS BITS(8, 9) /*!< channel 1 mode selection */ +#define TIMER_CHCTL0_CH1COMFEN BIT(10) /*!< channel 1 output compare fast enable */ +#define TIMER_CHCTL0_CH1COMSEN BIT(11) /*!< channel 1 output compare shadow enable */ +#define TIMER_CHCTL0_CH1COMCTL BITS(12, 14) /*!< channel 1 output compare control */ +#define TIMER_CHCTL0_CH1COMCEN BIT(15) /*!< channel 1 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL0_CH0CAPPSC BITS(2, 3) /*!< channel 0 input capture prescaler */ +#define TIMER_CHCTL0_CH0CAPFLT BITS(4, 7) /*!< channel 0 input capture filter control */ +#define TIMER_CHCTL0_CH1CAPPSC BITS(10, 11) /*!< channel 1 input capture prescaler */ +#define TIMER_CHCTL0_CH1CAPFLT BITS(12, 15) /*!< channel 1 input capture filter control */ + +/* TIMER_CHCTL1 */ +/* output compare mode */ +#define TIMER_CHCTL1_CH2MS BITS(0, 1) /*!< channel 2 mode selection */ +#define TIMER_CHCTL1_CH2COMFEN BIT(2) /*!< channel 2 output compare fast enable */ +#define TIMER_CHCTL1_CH2COMSEN BIT(3) /*!< channel 2 output compare shadow enable */ +#define TIMER_CHCTL1_CH2COMCTL BITS(4, 6) /*!< channel 2 output compare control */ +#define TIMER_CHCTL1_CH2COMCEN BIT(7) /*!< channel 2 output compare clear enable */ +#define TIMER_CHCTL1_CH3MS BITS(8, 9) /*!< channel 3 mode selection */ +#define TIMER_CHCTL1_CH3COMFEN BIT(10) /*!< channel 3 output compare fast enable */ +#define TIMER_CHCTL1_CH3COMSEN BIT(11) /*!< channel 3 output compare shadow enable */ +#define TIMER_CHCTL1_CH3COMCTL BITS(12, 14) /*!< channel 3 output compare control */ +#define TIMER_CHCTL1_CH3COMCEN BIT(15) /*!< channel 3 output compare clear enable */ +/* input capture mode */ +#define TIMER_CHCTL1_CH2CAPPSC BITS(2, 3) /*!< channel 2 input capture prescaler */ +#define TIMER_CHCTL1_CH2CAPFLT BITS(4, 7) /*!< channel 2 input capture filter control */ +#define TIMER_CHCTL1_CH3CAPPSC BITS(10, 11) /*!< channel 3 input capture prescaler */ +#define TIMER_CHCTL1_CH3CAPFLT BITS(12, 15) /*!< channel 3 input capture filter control */ + +/* TIMER_CHCTL2 */ +#define TIMER_CHCTL2_CH0EN BIT(0) /*!< channel 0 capture/compare function enable */ +#define TIMER_CHCTL2_CH0P BIT(1) /*!< channel 0 capture/compare function polarity */ +#define TIMER_CHCTL2_CH0NEN BIT(2) /*!< channel 0 complementary output enable */ +#define TIMER_CHCTL2_CH0NP BIT(3) /*!< channel 0 complementary output polarity */ +#define TIMER_CHCTL2_CH1EN BIT(4) /*!< channel 1 capture/compare function enable */ +#define TIMER_CHCTL2_CH1P BIT(5) /*!< channel 1 capture/compare function polarity */ +#define TIMER_CHCTL2_CH1NEN BIT(6) /*!< channel 1 complementary output enable */ +#define TIMER_CHCTL2_CH1NP BIT(7) /*!< channel 1 complementary output polarity */ +#define TIMER_CHCTL2_CH2EN BIT(8) /*!< channel 2 capture/compare function enable */ +#define TIMER_CHCTL2_CH2P BIT(9) /*!< channel 2 capture/compare function polarity */ +#define TIMER_CHCTL2_CH2NEN BIT(10) /*!< channel 2 complementary output enable */ +#define TIMER_CHCTL2_CH2NP BIT(11) /*!< channel 2 complementary output polarity */ +#define TIMER_CHCTL2_CH3EN BIT(12) /*!< channel 3 capture/compare function enable */ +#define TIMER_CHCTL2_CH3P BIT(13) /*!< channel 3 capture/compare function polarity */ + +/* TIMER_CNT */ +#define TIMER_CNT_CNT BITS(0, 15) /*!< 16 bit timer counter */ + +/* TIMER_PSC */ +#define TIMER_PSC_PSC BITS(0, 15) /*!< prescaler value of the counter clock */ + +/* TIMER_CAR */ +#define TIMER_CAR_CARL BITS(0, 15) /*!< 16 bit counter auto reload value */ + +/* TIMER_CREP */ +#define TIMER_CREP_CREP BITS(0, 7) /*!< counter repetition value */ + +/* TIMER_CH0CV */ +#define TIMER_CH0CV_CH0VAL BITS(0, 15) /*!< 16 bit capture/compare value of channel 0 */ + +/* TIMER_CH1CV */ +#define TIMER_CH1CV_CH1VAL BITS(0, 15) /*!< 16 bit capture/compare value of channel 1 */ + +/* TIMER_CH2CV */ +#define TIMER_CH2CV_CH2VAL BITS(0, 15) /*!< 16 bit capture/compare value of channel 2 */ + +/* TIMER_CH3CV */ +#define TIMER_CH3CV_CH3VAL BITS(0, 15) /*!< 16 bit capture/compare value of channel 3 */ + +/* TIMER_CCHP */ +#define TIMER_CCHP_DTCFG BITS(0, 7) /*!< dead time configure */ +#define TIMER_CCHP_PROT BITS(8, 9) /*!< complementary register protect control */ +#define TIMER_CCHP_IOS BIT(10) /*!< idle mode off-state configure */ +#define TIMER_CCHP_ROS BIT(11) /*!< run mode off-state configure */ +#define TIMER_CCHP_BRKEN BIT(12) /*!< break enable */ +#define TIMER_CCHP_BRKP BIT(13) /*!< break polarity */ +#define TIMER_CCHP_OAEN BIT(14) /*!< output automatic enable */ +#define TIMER_CCHP_POEN BIT(15) /*!< primary output enable */ + +/* TIMER_DMACFG */ +#define TIMER_DMACFG_DMATA BITS(0, 4) /*!< DMA transfer access start address */ +#define TIMER_DMACFG_DMATC BITS(8, 12) /*!< DMA transfer count */ + +/* TIMER_DMATB */ +#define TIMER_DMATB_DMATB BITS(0, 15) /*!< DMA transfer buffer address */ + +/* constants definitions */ +/* TIMER init parameter struct definitions */ +typedef struct +{ + uint16_t prescaler; /*!< prescaler value */ + uint16_t alignedmode; /*!< aligned mode */ + uint16_t counterdirection; /*!< counter direction */ + uint32_t period; /*!< period value */ + uint16_t clockdivision; /*!< clock division value */ + uint8_t repetitioncounter; /*!< the counter repetition value */ +} timer_parameter_struct; + +/* break parameter struct definitions */ +typedef struct +{ + uint16_t runoffstate; /*!< run mode off-state */ + uint16_t ideloffstate; /*!< idle mode off-state */ + uint16_t deadtime; /*!< dead time */ + uint16_t breakpolarity; /*!< break polarity */ + uint16_t outputautostate; /*!< output automatic enable */ + uint16_t protectmode; /*!< complementary register protect control */ + uint16_t breakstate; /*!< break enable */ +} timer_break_parameter_struct; + +/* channel output parameter struct definitions */ +typedef struct +{ + uint16_t outputstate; /*!< channel output state */ + uint16_t outputnstate; /*!< channel complementary output state */ + uint16_t ocpolarity; /*!< channel output polarity */ + uint16_t ocnpolarity; /*!< channel complementary output polarity */ + uint16_t ocidlestate; /*!< idle state of channel output */ + uint16_t ocnidlestate; /*!< idle state of channel complementary output */ +} timer_oc_parameter_struct; + +/* channel input parameter struct definitions */ +typedef struct +{ + uint16_t icpolarity; /*!< channel input polarity */ + uint16_t icselection; /*!< channel input mode selection */ + uint16_t icprescaler; /*!< channel input capture prescaler */ + uint16_t icfilter; /*!< channel input capture filter control */ +} timer_ic_parameter_struct; + +/* TIMER interrupt enable or disable */ +#define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ +#define TIMER_INT_CH0 TIMER_DMAINTEN_CH0IE /*!< channel 0 interrupt */ +#define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ +#define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ +#define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ +#define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ + +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ +#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ +#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ +#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ +#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ +#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ +#define TIMER_INT_FLAG_BRK TIMER_INT_BRK + +/* TIMER flag */ +#define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ +#define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ +#define TIMER_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 flag */ +#define TIMER_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 flag */ +#define TIMER_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 flag */ +#define TIMER_FLAG_CMT TIMER_INTF_CMTIF /*!< channel control update flag */ +#define TIMER_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger flag */ +#define TIMER_FLAG_BRK TIMER_INTF_BRKIF /*!< break flag */ +#define TIMER_FLAG_CH0O TIMER_INTF_CH0OF /*!< channel 0 overcapture flag */ +#define TIMER_FLAG_CH1O TIMER_INTF_CH1OF /*!< channel 1 overcapture flag */ +#define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ +#define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ + +/* TIMER DMA source enable */ +#define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ +#define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ +#define TIMER_DMA_CH1D ((uint16_t)TIMER_DMAINTEN_CH1DEN) /*!< channel 1 DMA enable */ +#define TIMER_DMA_CH2D ((uint16_t)TIMER_DMAINTEN_CH2DEN) /*!< channel 2 DMA enable */ +#define TIMER_DMA_CH3D ((uint16_t)TIMER_DMAINTEN_CH3DEN) /*!< channel 3 DMA enable */ +#define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ +#define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ + +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ + +/* DMA access base address */ +#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ +#define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ +#define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ +#define TIMER_DMACFG_DMATA_DMAINTEN DMACFG_DMATA(3) /*!< DMA transfer address is TIMER_DMAINTEN */ +#define TIMER_DMACFG_DMATA_INTF DMACFG_DMATA(4) /*!< DMA transfer address is TIMER_INTF */ +#define TIMER_DMACFG_DMATA_SWEVG DMACFG_DMATA(5) /*!< DMA transfer address is TIMER_SWEVG */ +#define TIMER_DMACFG_DMATA_CHCTL0 DMACFG_DMATA(6) /*!< DMA transfer address is TIMER_CHCTL0 */ +#define TIMER_DMACFG_DMATA_CHCTL1 DMACFG_DMATA(7) /*!< DMA transfer address is TIMER_CHCTL1 */ +#define TIMER_DMACFG_DMATA_CHCTL2 DMACFG_DMATA(8) /*!< DMA transfer address is TIMER_CHCTL2 */ +#define TIMER_DMACFG_DMATA_CNT DMACFG_DMATA(9) /*!< DMA transfer address is TIMER_CNT */ +#define TIMER_DMACFG_DMATA_PSC DMACFG_DMATA(10) /*!< DMA transfer address is TIMER_PSC */ +#define TIMER_DMACFG_DMATA_CAR DMACFG_DMATA(11) /*!< DMA transfer address is TIMER_CAR */ +#define TIMER_DMACFG_DMATA_CREP DMACFG_DMATA(12) /*!< DMA transfer address is TIMER_CREP */ +#define TIMER_DMACFG_DMATA_CH0CV DMACFG_DMATA(13) /*!< DMA transfer address is TIMER_CH0CV */ +#define TIMER_DMACFG_DMATA_CH1CV DMACFG_DMATA(14) /*!< DMA transfer address is TIMER_CH1CV */ +#define TIMER_DMACFG_DMATA_CH2CV DMACFG_DMATA(15) /*!< DMA transfer address is TIMER_CH2CV */ +#define TIMER_DMACFG_DMATA_CH3CV DMACFG_DMATA(16) /*!< DMA transfer address is TIMER_CH3CV */ +#define TIMER_DMACFG_DMATA_CCHP DMACFG_DMATA(17) /*!< DMA transfer address is TIMER_CCHP */ +#define TIMER_DMACFG_DMATA_DMACFG DMACFG_DMATA(18) /*!< DMA transfer address is TIMER_DMACFG */ + +/* DMA access burst length */ +#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ +#define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ +#define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ +#define TIMER_DMACFG_DMATC_4TRANSFER DMACFG_DMATC(3) /*!< DMA transfer 4 times */ +#define TIMER_DMACFG_DMATC_5TRANSFER DMACFG_DMATC(4) /*!< DMA transfer 5 times */ +#define TIMER_DMACFG_DMATC_6TRANSFER DMACFG_DMATC(5) /*!< DMA transfer 6 times */ +#define TIMER_DMACFG_DMATC_7TRANSFER DMACFG_DMATC(6) /*!< DMA transfer 7 times */ +#define TIMER_DMACFG_DMATC_8TRANSFER DMACFG_DMATC(7) /*!< DMA transfer 8 times */ +#define TIMER_DMACFG_DMATC_9TRANSFER DMACFG_DMATC(8) /*!< DMA transfer 9 times */ +#define TIMER_DMACFG_DMATC_10TRANSFER DMACFG_DMATC(9) /*!< DMA transfer 10 times */ +#define TIMER_DMACFG_DMATC_11TRANSFER DMACFG_DMATC(10) /*!< DMA transfer 11 times */ +#define TIMER_DMACFG_DMATC_12TRANSFER DMACFG_DMATC(11) /*!< DMA transfer 12 times */ +#define TIMER_DMACFG_DMATC_13TRANSFER DMACFG_DMATC(12) /*!< DMA transfer 13 times */ +#define TIMER_DMACFG_DMATC_14TRANSFER DMACFG_DMATC(13) /*!< DMA transfer 14 times */ +#define TIMER_DMACFG_DMATC_15TRANSFER DMACFG_DMATC(14) /*!< DMA transfer 15 times */ +#define TIMER_DMACFG_DMATC_16TRANSFER DMACFG_DMATC(15) /*!< DMA transfer 16 times */ +#define TIMER_DMACFG_DMATC_17TRANSFER DMACFG_DMATC(16) /*!< DMA transfer 17 times */ +#define TIMER_DMACFG_DMATC_18TRANSFER DMACFG_DMATC(17) /*!< DMA transfer 18 times */ + +/* TIMER software event generation source */ +#define TIMER_EVENT_SRC_UPG ((uint16_t)0x0001U) /*!< update event generation */ +#define TIMER_EVENT_SRC_CH0G ((uint16_t)0x0002U) /*!< channel 0 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH1G ((uint16_t)0x0004U) /*!< channel 1 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH2G ((uint16_t)0x0008U) /*!< channel 2 capture or compare event generation */ +#define TIMER_EVENT_SRC_CH3G ((uint16_t)0x0010U) /*!< channel 3 capture or compare event generation */ +#define TIMER_EVENT_SRC_CMTG ((uint16_t)0x0020U) /*!< channel commutation event generation */ +#define TIMER_EVENT_SRC_TRGG ((uint16_t)0x0040U) /*!< trigger event generation */ +#define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ + +/* center-aligned mode selection */ +#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ +#define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ +#define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ +#define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ + +/* TIMER prescaler reload mode */ +#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ + +/* count direction */ +#define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ +#define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ + +/* specify division ratio between TIMER clock and dead-time and sampling clock */ +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ +#define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ +#define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ + +/* single pulse mode */ +#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ + +/* update source */ +#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ + +/* run mode off-state configure */ +#define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* idle mode off-state configure */ +#define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ +#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ + +/* break input polarity */ +#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000U) /*!< break input polarity is low */ +#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)TIMER_CCHP_BRKP) /*!< break input polarity is high */ + +/* output automatic enable */ +#define TIMER_OUTAUTO_ENABLE ((uint16_t)TIMER_CCHP_OAEN) /*!< output automatic enable */ +#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ + +/* complementary register protect control */ +#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ +#define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ +#define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ +#define TIMER_CCHP_PROT_2 CCHP_PROT(3) /*!< PROT mode 2 */ + +/* break input enable */ +#define TIMER_BREAK_ENABLE ((uint16_t)TIMER_CCHP_BRKEN) /*!< break input enable */ +#define TIMER_BREAK_DISABLE ((uint16_t)0x0000U) /*!< break input disable */ + +/* TIMER channel n(n=0,1,2,3) */ +#define TIMER_CH_0 ((uint16_t)0x0000U) /*!< TIMER channel 0(TIMERx(x=0..4)) */ +#define TIMER_CH_1 ((uint16_t)0x0001U) /*!< TIMER channel 1(TIMERx(x=0..4)) */ +#define TIMER_CH_2 ((uint16_t)0x0002U) /*!< TIMER channel 2(TIMERx(x=0..4)) */ +#define TIMER_CH_3 ((uint16_t)0x0003U) /*!< TIMER channel 3(TIMERx(x=0..4)) */ + +/* channel enable state */ +#define TIMER_CCX_ENABLE ((uint16_t)0x0001U) /*!< channel enable */ +#define TIMER_CCX_DISABLE ((uint16_t)0x0000U) /*!< channel disable */ + +/* channel complementary output enable state */ +#define TIMER_CCXN_ENABLE ((uint16_t)0x0004U) /*!< channel complementary enable */ +#define TIMER_CCXN_DISABLE ((uint16_t)0x0000U) /*!< channel complementary disable */ + +/* channel output polarity */ +#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel output polarity is high */ +#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002U) /*!< channel output polarity is low */ + +/* channel complementary output polarity */ +#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ +#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ + +/* idle state of channel output */ +#define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ +#define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ + +/* idle state of channel complementary output */ +#define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ +#define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ + +/* channel output compare mode */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< timing mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< active mode */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< inactive mode */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle mode */ +#define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ +#define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ +#define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ +#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0070U) /*!< PWM1 mode */ + +/* channel output compare shadow enable */ +#define TIMER_OC_SHADOW_ENABLE ((uint16_t)0x0008U) /*!< channel output shadow state enable */ +#define TIMER_OC_SHADOW_DISABLE ((uint16_t)0x0000U) /*!< channel output shadow state disable */ + +/* channel output compare fast enable */ +#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) /*!< channel output fast function enable */ +#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) /*!< channel output fast function disable */ + +/* channel output compare clear enable */ +#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ +#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ + +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ + +/* channel input capture polarity */ +#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ +#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ +#define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ + +/* TIMER input capture selection */ +#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel n is configured as input and icy is mapped on CIy */ +#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel n is configured as input and icy is mapped on opposite input */ +#define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel n is configured as input and icy is mapped on ITS */ + +/* channel input capture prescaler */ +#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000U) /*!< no prescaler */ +#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004U) /*!< divided by 2 */ +#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008U) /*!< divided by 4 */ +#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ + +/* trigger selection */ +#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ +#define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ +#define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ +#define TIMER_SMCFG_TRGSEL_ITI3 SMCFG_TRGSEL(3) /*!< internal trigger 3 */ +#define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ +#define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ +#define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< filtered external trigger input */ + +/* master mode control */ +#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ +#define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ +#define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ +#define TIMER_TRI_OUT_SRC_CH0 CTL1_MMC(3) /*!< a capture or a compare match occurred in channel 0 as trigger output TRGO */ +#define TIMER_TRI_OUT_SRC_O0CPRE CTL1_MMC(4) /*!< O0CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O1CPRE CTL1_MMC(5) /*!< O1CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O2CPRE CTL1_MMC(6) /*!< O2CPRE as trigger output */ +#define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ + +/* slave mode control */ +#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ +#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ +#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ +#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ +#define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ +#define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ +#define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ + +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ + +/* external trigger prescaler */ +#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ +#define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ +#define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ +#define TIMER_EXT_TRI_PSC_DIV8 SMCFG_ETPSC(3) /*!< divided by 8 */ + +/* external trigger polarity */ +#define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ +#define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ + +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ + +/* TIMERx(x=0..4) write CHxVAL register selection */ +#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ +#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ + +/* function declarations */ +/* TIMER timebase */ +/* deinit a timer */ +void timer_deinit(uint32_t timer_periph); +/* initialize TIMER init parameter struct */ +void timer_struct_para_init(timer_parameter_struct *initpara); +/* initialize TIMER counter */ +void timer_init(uint32_t timer_periph, timer_parameter_struct *initpara); +/* enable a timer */ +void timer_enable(uint32_t timer_periph); +/* disable a timer */ +void timer_disable(uint32_t timer_periph); +/* enable the auto reload shadow function */ +void timer_auto_reload_shadow_enable(uint32_t timer_periph); +/* disable the auto reload shadow function */ +void timer_auto_reload_shadow_disable(uint32_t timer_periph); +/* enable the update event */ +void timer_update_event_enable(uint32_t timer_periph); +/* disable the update event */ +void timer_update_event_disable(uint32_t timer_periph); +/* set TIMER counter alignment mode */ +void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned); +/* set TIMER counter up direction */ +void timer_counter_up_direction(uint32_t timer_periph); +/* set TIMER counter down direction */ +void timer_counter_down_direction(uint32_t timer_periph); + +/* configure TIMER prescaler */ +void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); +/* configure TIMER repetition register value */ +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition); +/* configure TIMER autoreload register value */ +void timer_autoreload_value_config(uint32_t timer_periph, uint16_t autoreload); +/* configure TIMER counter register value */ +void timer_counter_value_config(uint32_t timer_periph, uint16_t counter); +/* read TIMER counter value */ +uint32_t timer_counter_read(uint32_t timer_periph); +/* read TIMER prescaler value */ +uint16_t timer_prescaler_read(uint32_t timer_periph); +/* configure TIMER single pulse mode */ +void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); +/* configure TIMER update source */ +void timer_update_source_config(uint32_t timer_periph, uint32_t update); + +/* TIMER DMA and event */ +/* enable the TIMER DMA */ +void timer_dma_enable(uint32_t timer_periph, uint16_t dma); +/* disable the TIMER DMA */ +void timer_dma_disable(uint32_t timer_periph, uint16_t dma); +/* channel DMA request source selection */ +void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request); +/* configure the TIMER DMA transfer */ +void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth); +/* software generate events */ +void timer_event_software_generate(uint32_t timer_periph, uint16_t event); + +/* TIMER channel complementary protection */ +/* initialize TIMER break parameter struct */ +void timer_break_struct_para_init(timer_break_parameter_struct *breakpara); +/* configure TIMER break function */ +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct *breakpara); +/* enable TIMER break function */ +void timer_break_enable(uint32_t timer_periph); +/* disable TIMER break function */ +void timer_break_disable(uint32_t timer_periph); +/* enable TIMER output automatic function */ +void timer_automatic_output_enable(uint32_t timer_periph); +/* disable TIMER output automatic function */ +void timer_automatic_output_disable(uint32_t timer_periph); +/* enable or disable TIMER primary output function */ +void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue); +/* enable or disable channel capture/compare control shadow register */ +void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue); +/* configure TIMER channel control shadow register update control */ +void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl); + +/* TIMER channel output */ +/* initialize TIMER channel output parameter struct */ +void timer_channel_output_struct_para_init(timer_oc_parameter_struct *ocpara); +/* configure TIMER channel output function */ +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct *ocpara); +/* configure TIMER channel output compare mode */ +void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); +/* configure TIMER channel output pulse value */ +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse); +/* configure TIMER channel output shadow function */ +void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); +/* configure TIMER channel output fast function */ +void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast); +/* configure TIMER channel output clear function */ +void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear); +/* configure TIMER channel output polarity */ +void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity); +/* configure TIMER channel complementary output polarity */ +void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity); +/* configure TIMER channel enable state */ +void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state); +/* configure TIMER channel complementary output enable state */ +void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate); + +/* TIMER channel input */ +/* initialize TIMER channel input parameter struct */ +void timer_channel_input_struct_para_init(timer_ic_parameter_struct *icpara); +/* configure TIMER input capture parameter */ +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpara); +/* configure TIMER channel input capture prescaler value */ +void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); +/* read TIMER channel capture compare register value */ +uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); +/* configure TIMER input pwm capture function */ +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpwm); +/* configure TIMER hall sensor mode */ +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); + +/* TIMER master and slave mode */ +/* select TIMER input trigger source */ +void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger); +/* select TIMER master mode output trigger source */ +void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t outrigger); +/* select TIMER slave mode */ +void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); +/* configure TIMER master slave mode */ +void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); +/* configure TIMER external trigger input */ +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER quadrature decoder mode */ +void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); +/* configure TIMER internal clock mode */ +void timer_internal_clock_config(uint32_t timer_periph); +/* configure TIMER the internal trigger as external clock input */ +void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); +/* configure TIMER the external trigger as external clock input */ +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter); +/* configure TIMER the external clock mode 0 */ +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* configure TIMER the external clock mode 1 */ +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); +/* disable TIMER the external clock mode 1 */ +void timer_external_clock_mode1_disable(uint32_t timer_periph); + +/* TIMER interrupt and flag */ +/* enable the TIMER interrupt */ +void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); +/* disable the TIMER interrupt */ +void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER interrupt flag */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); +/* clear TIMER interrupt flag */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); +/* get TIMER flag */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flag */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); + +#endif /* GD32VF103_TIMER_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.c new file mode 100644 index 00000000..cdd4f4d1 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.c @@ -0,0 +1,765 @@ +/*! + \file gd32vf103_usart.c + \brief USART driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_usart.h" + +/*! + \brief reset USART/UART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_deinit(uint32_t usart_periph) +{ + switch(usart_periph){ + case USART0: + /* reset USART0 */ + rcu_periph_reset_enable(RCU_USART0RST); + rcu_periph_reset_disable(RCU_USART0RST); + break; + case USART1: + /* reset USART1 */ + rcu_periph_reset_enable(RCU_USART1RST); + rcu_periph_reset_disable(RCU_USART1RST); + break; + case USART2: + /* reset USART2 */ + rcu_periph_reset_enable(RCU_USART2RST); + rcu_periph_reset_disable(RCU_USART2RST); + break; + case UART3: + /* reset UART3 */ + rcu_periph_reset_enable(RCU_UART3RST); + rcu_periph_reset_disable(RCU_UART3RST); + break; + case UART4: + /* reset UART4 */ + rcu_periph_reset_enable(RCU_UART4RST); + rcu_periph_reset_disable(RCU_UART4RST); + break; + default: + break; + } +} + +/*! + \brief configure USART baud rate value + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] baudval: baud rate value + \param[out] none + \retval none +*/ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) +{ + uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; + switch(usart_periph){ + /* get clock frequency */ + case USART0: + /* get USART0 clock */ + uclk=rcu_clock_freq_get(CK_APB2); + break; + case USART1: + /* get USART1 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case USART2: + /* get USART2 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART3: + /* get UART3 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + case UART4: + /* get UART4 clock */ + uclk=rcu_clock_freq_get(CK_APB1); + break; + default: + break; + } + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk+baudval/2U)/baudval; + intdiv = udiv & (0x0000fff0U); + fradiv = udiv & (0x0000000fU); + USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); +} + +/*! + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity + \param[out] none + \retval none +*/ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) +{ + /* clear USART_CTL0 PM,PCEN bits */ + USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); + /* configure USART parity mode */ + USART_CTL0(usart_periph) |= paritycfg ; +} + +/*! + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits + \param[out] none + \retval none +*/ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) +{ + /* clear USART_CTL0 WL bit */ + USART_CTL0(usart_periph) &= ~USART_CTL0_WL; + /* configure USART word length */ + USART_CTL0(usart_periph) |= wlen; +} + +/*! + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit + \arg USART_STB_0_5BIT: 0.5 bit, not available for UARTx(x=3,4) + \arg USART_STB_2BIT: 2 bits + \arg USART_STB_1_5BIT: 1.5 bits, not available for UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) +{ + /* clear USART_CTL1 STB bits */ + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + /* configure USART stop bits */ + USART_CTL1(usart_periph) |= stblen; +} + +/*! + \brief enable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_UEN; +} + +/*! + \brief disable USART + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_UEN); +} + +/*! + \brief configure USART transmitter + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] txconfig: enable or disable USART transmitter + only one parameter can be selected which is shown as below: + \arg USART_TRANSMIT_ENABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: disable USART transmission + \param[out] none + \retval none +*/ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_TEN; + ctl |= txconfig; + /* configure transfer mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief configure USART receiver + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] rxconfig: enable or disable USART receiver + only one parameter can be selected which is shown as below: + \arg USART_RECEIVE_ENABLE: enable USART reception + \arg USART_RECEIVE_DISABLE: disable USART reception + \param[out] none + \retval none +*/ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL0(usart_periph); + ctl &= ~USART_CTL0_REN; + ctl |= rxconfig; + /* configure receiver mode */ + USART_CTL0(usart_periph) = ctl; +} + +/*! + \brief USART transmit data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] data: data of transmission + \param[out] none + \retval none +*/ +void usart_data_transmit(uint32_t usart_periph, uint32_t data) +{ + USART_DATA(usart_periph) = USART_DATA_DATA & data; +} + +/*! + \brief USART receive data function + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval data of received +*/ +uint16_t usart_data_receive(uint32_t usart_periph) +{ + return (uint16_t)(GET_BITS(USART_DATA(usart_periph), 0U, 8U)); +} + +/*! + \brief configure the address of the USART in wake up by address match mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] addr: address of USART/UART + \param[out] none + \retval none +*/ +void usart_address_config(uint32_t usart_periph, uint8_t addr) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); +} + +/*! + \brief receiver in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_enable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_RWU; +} + +/*! + \brief receiver in active mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_mute_mode_disable(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_RWU); +} + +/*! + \brief configure wakeup method in mute mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] wmethod: two methods be used to enter or exit the mute mode + only one parameter can be selected which is shown as below: + \arg USART_WM_IDLE: idle line + \arg USART_WM_ADDR: address mask + \param[out] none + \retval none +*/ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) +{ + USART_CTL0(usart_periph) &= ~(USART_CTL0_WM); + USART_CTL0(usart_periph) |= wmethod; +} + +/*! + \brief enable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_LMEN; +} + +/*! + \brief disable LIN mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_lin_mode_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); +} + +/*! + \brief configure lin break frame length + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] lblen: lin break frame length + only one parameter can be selected which is shown as below: + \arg USART_LBLEN_10B: 10 bits + \arg USART_LBLEN_11B: 11 bits + \param[out] none + \retval none +*/ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_LBLEN); + USART_CTL1(usart_periph) |= (USART_CTL1_LBLEN & lblen); +} + +/*! + \brief send break frame + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_send_break(uint32_t usart_periph) +{ + USART_CTL0(usart_periph) |= USART_CTL0_SBKCMD; +} + +/*! + \brief enable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_HDEN; +} + +/*! + \brief disable half duplex mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_halfduplex_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_HDEN); +} + +/*! + \brief enable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_enable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) |= USART_CTL1_CKEN; +} + +/*! + \brief disable CK pin in synchronous mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_synchronous_clock_disable(uint32_t usart_periph) +{ + USART_CTL1(usart_periph) &= ~(USART_CTL1_CKEN); +} + +/*! + \brief configure USART synchronous mode parameters + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] clen: CK length + only one parameter can be selected which is shown as below: + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame + \param[in] cph: clock phase + only one parameter can be selected which is shown as below: + \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_2CK: second clock transition is the first data capture edge + \param[in] cpl: clock polarity + only one parameter can be selected which is shown as below: + \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_HIGH: steady high value on CK pin + \param[out] none + \retval none +*/ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) +{ + uint32_t ctl = 0U; + + /* read USART_CTL1 register */ + ctl = USART_CTL1(usart_periph); + ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + /* set CK length, CK phase, CK polarity */ + ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); + + USART_CTL1(usart_periph) = ctl; +} + +/*! + \brief configure guard time value in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] gaut: guard time value + \param[out] none + \retval none +*/ +void usart_guard_time_config(uint32_t usart_periph,uint32_t gaut) +{ + USART_GP(usart_periph) &= ~(USART_GP_GUAT); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((gaut)<<8)); +} + +/*! + \brief enable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_SCEN; +} + +/*! + \brief disable smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_SCEN); +} + +/*! + \brief enable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_NKEN; +} + +/*! + \brief disable NACK in smartcard mode + \param[in] usart_periph: USARTx(x=0,1,2) + \param[out] none + \retval none +*/ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_NKEN); +} + +/*! + \brief enable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_enable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) |= USART_CTL2_IREN; +} + +/*! + \brief disable IrDA mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[out] none + \retval none +*/ +void usart_irda_mode_disable(uint32_t usart_periph) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IREN); +} + +/*! + \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] psc: 0x00-0xFF + \param[out] none + \retval none +*/ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) +{ + USART_GP(usart_periph) &= ~(USART_GP_PSC); + USART_GP(usart_periph) |= psc; +} + +/*! + \brief configure IrDA low-power + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] irlp: IrDA low-power or normal + only one parameter can be selected which is shown as below: + \arg USART_IRLP_LOW: low-power + \arg USART_IRLP_NORMAL: normal + \param[out] none + \retval none +*/ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) +{ + USART_CTL2(usart_periph) &= ~(USART_CTL2_IRLP); + USART_CTL2(usart_periph) |= (USART_CTL2_IRLP & irlp); +} + +/*! + \brief configure hardware flow control RTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] rtsconfig: enable or disable RTS + only one parameter can be selected which is shown as below: + \arg USART_RTS_ENABLE: enable RTS + \arg USART_RTS_DISABLE: disable RTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_RTSEN; + ctl |= rtsconfig; + /* configure RTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure hardware flow control CTS + \param[in] usart_periph: USARTx(x=0,1,2) + \param[in] ctsconfig: enable or disable CTS + only one parameter can be selected which is shown as below: + \arg USART_CTS_ENABLE: enable CTS + \arg USART_CTS_DISABLE: disable CTS + \param[out] none + \retval none +*/ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_CTSEN; + ctl |= ctsconfig; + /* configure CTS */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA reception + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for reception + only one parameter can be selected which is shown as below: + \arg USART_DENR_ENABLE: DMA enable for reception + \arg USART_DENR_DISABLE: DMA disable for reception + \param[out] none + \retval none +*/ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENR; + ctl |= dmacmd; + /* configure DMA reception */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief configure USART DMA transmission + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3) + \param[in] dmacmd: enable or disable DMA for transmission + only one parameter can be selected which is shown as below: + \arg USART_DENT_ENABLE: DMA enable for transmission + \arg USART_DENT_DISABLE: DMA disable for transmission + \param[out] none + \retval none +*/ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +{ + uint32_t ctl = 0U; + + ctl = USART_CTL2(usart_periph); + ctl &= ~USART_CTL2_DENT; + ctl |= dmacmd; + /* configure DMA transmission */ + USART_CTL2(usart_periph) = ctl; +} + +/*! + \brief get flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TBE: transmit data buffer empty + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \arg USART_FLAG_IDLE: IDLE frame detected flag + \arg USART_FLAG_ORERR: overrun error + \arg USART_FLAG_NERR: noise error flag + \arg USART_FLAG_FERR: frame error flag + \arg USART_FLAG_PERR: parity error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) +{ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] flag: USART flags, refer to usart_flag_enum + only one parameter can be selected which is shown as below: + \arg USART_FLAG_CTS: CTS change flag + \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_TC: transmission complete + \arg USART_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) +{ + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +} + +/*! + \brief enable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] interrupt + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t interrupt) +{ + USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); +} + +/*! + \brief disable USART interrupt + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] interrupt + only one parameter can be selected which is shown as below: + \arg USART_INT_PERR: parity error interrupt + \arg USART_INT_TBE: transmitter buffer empty interrupt + \arg USART_INT_TC: transmission complete interrupt + \arg USART_INT_RBNE: read data buffer not empty interrupt and overrun error interrupt + \arg USART_INT_IDLE: IDLE line detected interrupt + \arg USART_INT_LBD: LIN break detected interrupt + \arg USART_INT_ERR: error interrupt + \arg USART_INT_CTS: CTS interrupt + \param[out] none + \retval none +*/ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t interrupt) +{ + USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); +} + +/*! + \brief get USART interrupt and flag status + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_PERR: parity error interrupt and flag + \arg USART_INT_FLAG_TBE: transmitter buffer empty interrupt and flag + \arg USART_INT_FLAG_TC: transmission complete interrupt and flag + \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag + \arg USART_INT_FLAG_RBNE_ORERR: read data buffer not empty interrupt and overrun error flag + \arg USART_INT_FLAG_IDLE: IDLE line detected interrupt and flag + \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag + \arg USART_INT_FLAG_CTS: CTS interrupt and flag + \arg USART_INT_FLAG_ERR_ORERR: error interrupt and overrun error + \arg USART_INT_FLAG_ERR_NERR: error interrupt and noise error flag + \arg USART_INT_FLAG_ERR_FERR: error interrupt and frame error flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +{ + uint32_t intenable = 0U, flagstatus = 0U; + /* get the interrupt enable bit status */ + intenable = (USART_REG_VAL(usart_periph, int_flag) & BIT(USART_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); + + if(flagstatus && intenable){ + return SET; + }else{ + return RESET; + } +} + +/*! + \brief clear USART interrupt flag in STAT register + \param[in] usart_periph: USARTx(x=0,1,2)/UARTx(x=3,4) + \param[in] int_flag: USART interrupt flag + only one parameter can be selected which is shown as below: + \arg USART_INT_FLAG_CTS: CTS change flag + \arg USART_INT_FLAG_LBD: LIN break detected flag + \arg USART_INT_FLAG_TC: transmission complete + \arg USART_INT_FLAG_RBNE: read data buffer not empty + \param[out] none + \retval none +*/ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t int_flag) +{ + USART_REG_VAL2(usart_periph, int_flag) &= ~BIT(USART_BIT_POS2(int_flag)); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.h new file mode 100644 index 00000000..fc5a8031 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_usart.h @@ -0,0 +1,376 @@ +/*! + \file gd32vf103_usart.h + \brief definitions for the USART + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2018, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef GD32VF103_USART_H +#define GD32VF103_USART_H + +#include "gd32vf103.h" + +/* USARTx(x=0,1,2)/UARTx(x=3,4) definitions */ +#define USART1 USART_BASE /*!< USART1 base address */ +#define USART2 (USART_BASE + (0x00000400U)) /*!< USART2 base address */ +#define UART3 (USART_BASE + (0x00000800U)) /*!< UART3 base address */ +#define UART4 (USART_BASE + (0x00000C00U)) /*!< UART4 base address */ +#define USART0 (USART_BASE + (0x0000F400U)) /*!< USART0 base address */ + +/* registers definitions */ +#define USART_STAT(usartx) REG32((usartx) + (0x00000000U)) /*!< USART status register */ +#define USART_DATA(usartx) REG32((usartx) + (0x00000004U)) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + (0x00000008U)) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + (0x0000000CU)) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + (0x00000010U)) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + (0x00000014U)) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + (0x00000018U)) /*!< USART guard time and prescaler register */ + +/* bits definitions */ +/* USARTx_STAT */ +#define USART_STAT_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT_TC BIT(6) /*!< transmission complete */ +#define USART_STAT_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT_CTSF BIT(9) /*!< CTS change flag */ + +/* USARTx_DATA */ +#define USART_DATA_DATA BITS(0, 8) /*!< transmit or read data value */ + +/* USARTx_BAUD */ +#define USART_BAUD_FRADIV BITS(0, 3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4, 15) /*!< integer part of baud-rate divider */ + +/* USARTx_CTL0 */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< receiver enable */ +#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ +#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ +#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ +#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ +#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ +#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< USART enable */ + +/* USARTx_CTL1 */ +#define USART_CTL1_ADDR BITS(0, 3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ +#define USART_CTL1_STB BITS(12, 13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ + +/* USARTx_CTL2 */ +#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ +#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ +#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ +#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ +#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ +#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ +#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ +#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ + +/* USARTx_GP */ +#define USART_GP_PSC BITS(0, 7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8, 15) /*!< guard time value in smartcard mode */ + +/* constants definitions */ +/* define the USART bit position and its register index offset */ +#define USART_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) +#define USART_REG_VAL(usartx, offset) (REG32((usartx) + (((uint32_t)(offset) & (0x0000FFFFU)) >> 6))) +#define USART_BIT_POS(val) ((uint32_t)(val) & (0x0000001FU)) +#define USART_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16) | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) +#define USART_REG_VAL2(usartx, offset) (REG32((usartx) + ((uint32_t)(offset) >> 22))) +#define USART_BIT_POS2(val) (((uint32_t)(val) & (0x001F0000U)) >> 16) + +/* register offset */ +#define USART_STAT_REG_OFFSET (0x00000000U) /*!< STAT register offset */ +#define USART_CTL0_REG_OFFSET (0x0000000CU) /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET (0x00000010U) /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET (0x00000014U) /*!< CTL2 register offset */ + +/* USART flags */ +typedef enum { + /* flags in STAT register */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT_REG_OFFSET, 0U), /*!< parity error flag */ +} usart_flag_enum; + +/* USART interrupt flags */ +typedef enum { + /* interrupt flags in CTL0 register */ + USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ + USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ + USART_INT_FLAG_TC = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 6U), /*!< transmission complete interrupt and flag */ + USART_INT_FLAG_RBNE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and flag */ + USART_INT_FLAG_RBNE_ORERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 5U, USART_STAT_REG_OFFSET, 3U), /*!< read data buffer not empty interrupt and overrun error flag */ + USART_INT_FLAG_IDLE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 4U, USART_STAT_REG_OFFSET, 4U), /*!< IDLE line detected interrupt and flag */ + /* interrupt flags in CTL1 register */ + USART_INT_FLAG_LBD = USART_REGIDX_BIT2(USART_CTL1_REG_OFFSET, 6U, USART_STAT_REG_OFFSET, 8U), /*!< LIN break detected interrupt and flag */ + /* interrupt flags in CTL2 register */ + USART_INT_FLAG_CTS = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 10U, USART_STAT_REG_OFFSET, 9U), /*!< CTS interrupt and flag */ + USART_INT_FLAG_ERR_ORERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 3U), /*!< error interrupt and overrun error */ + USART_INT_FLAG_ERR_NERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 2U), /*!< error interrupt and noise error flag */ + USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ +} usart_interrupt_flag_enum; + +/* USART interrupt enable or disable */ +typedef enum { + /* interrupt in CTL0 register */ + USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ + USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ + USART_INT_TC = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 6U), /*!< transmission complete interrupt */ + USART_INT_RBNE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 5U), /*!< read data buffer not empty interrupt and overrun error interrupt */ + USART_INT_IDLE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 4U), /*!< IDLE line detected interrupt */ + /* interrupt in CTL1 register */ + USART_INT_LBD = USART_REGIDX_BIT(USART_CTL1_REG_OFFSET, 6U), /*!< LIN break detected interrupt */ + /* interrupt in CTL2 register */ + USART_INT_CTS = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 10U), /*!< CTS interrupt */ + USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ +} usart_interrupt_enum; + +/* USART receiver configure */ +#define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ + +/* USART transmitter configure */ +#define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ + +/* USART parity bits definitions */ +#define CTL0_PM(regval) (BITS(9, 10) & ((uint32_t)(regval) << 9)) +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ + +/* USART wakeup method in mute mode */ +#define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ + +/* USART word length definitions */ +#define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ + +/* USART stop bits definitions */ +#define CTL1_STB(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12)) +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ + +/* USART LIN break frame length */ +#define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ + +/* USART CK length */ +#define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ + +/* USART clock phase */ +#define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ + +/* USART clock polarity */ +#define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* USART DMA request for receive configure */ +#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ +#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ + +/* USART DMA request for transmission configure */ +#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ +#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ + +/* USART RTS configure */ +#define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ + +/* USART CTS configure */ +#define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ + +/* USART IrDA low-power enable */ +#define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ + +/* function declarations */ +/* initialization functions */ +/* reset USART */ +void usart_deinit(uint32_t usart_periph); +/* configure USART baud rate value */ +void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); +/* configure USART parity function */ +void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); +/* configure USART word length */ +void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); +/* configure USART stop bit length */ +void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); + +/* USART normal mode communication */ +/* enable USART */ +void usart_enable(uint32_t usart_periph); +/* disable USART */ +void usart_disable(uint32_t usart_periph); +/* configure USART transmitter */ +void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); +/* configure USART receiver */ +void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); +/* USART transmit data function */ +void usart_data_transmit(uint32_t usart_periph, uint32_t data); +/* USART receive data function */ +uint16_t usart_data_receive(uint32_t usart_periph); + +/* multi-processor communication */ +/* configure address of the USART */ +void usart_address_config(uint32_t usart_periph, uint8_t addr); +/* enable mute mode */ +void usart_mute_mode_enable(uint32_t usart_periph); +/* disable mute mode */ +void usart_mute_mode_disable(uint32_t usart_periph); +/* configure wakeup method in mute mode */ +void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); + +/* LIN mode communication */ +/* LIN mode enable */ +void usart_lin_mode_enable(uint32_t usart_periph); +/* LIN mode disable */ +void usart_lin_mode_disable(uint32_t usart_periph); +/* LIN break detection length */ +void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); +/* send break frame */ +void usart_send_break(uint32_t usart_periph); + +/* half-duplex communication */ +/* half-duplex enable */ +void usart_halfduplex_enable(uint32_t usart_periph); +/* half-duplex disable */ +void usart_halfduplex_disable(uint32_t usart_periph); + +/* synchronous communication */ +/* clock enable */ +void usart_synchronous_clock_enable(uint32_t usart_periph); +/* clock disable */ +void usart_synchronous_clock_disable(uint32_t usart_periph); +/* configure usart synchronous mode parameters */ +void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); + +/* smartcard communication */ +/* guard time value configure in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph, uint32_t gaut); +/* smartcard mode enable */ +void usart_smartcard_mode_enable(uint32_t usart_periph); +/* smartcard mode disable */ +void usart_smartcard_mode_disable(uint32_t usart_periph); +/* NACK enable in smartcard mode */ +void usart_smartcard_mode_nack_enable(uint32_t usart_periph); +/* NACK disable in smartcard mode */ +void usart_smartcard_mode_nack_disable(uint32_t usart_periph); + +/* IrDA communication */ +/* enable IrDA mode */ +void usart_irda_mode_enable(uint32_t usart_periph); +/* disable IrDA mode */ +void usart_irda_mode_disable(uint32_t usart_periph); +/* configure the peripheral clock prescaler */ +void usart_prescaler_config(uint32_t usart_periph, uint8_t psc); +/* configure IrDA low-power */ +void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp); + +/* hardware flow communication */ +/* configure hardware flow control RTS */ +void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); +/* configure hardware flow control CTS */ +void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); + +/* configure USART DMA for reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); +/* configure USART DMA for transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); + +/* flag functions */ +/* get flag in STAT register */ +FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); +/* clear flag in STAT register */ +void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); + +/* interrupt functions */ +/* enable USART interrupt */ +void usart_interrupt_enable(uint32_t usart_periph, uint32_t interrupt); +/* disable USART interrupt */ +void usart_interrupt_disable(uint32_t usart_periph, uint32_t interrupt); +/* get USART interrupt and flag status */ +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); +/* clear interrupt flag in STAT register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t int_flag); +#endif /* GD32VF103_USART_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.c new file mode 100644 index 00000000..3703e65a --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.c @@ -0,0 +1,146 @@ +/*! + \file gd32vf103_wwdgt.c + \brief WWDGT driver + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103_wwdgt.h" + +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + +/*! + \brief reset the window watchdog timer configuration + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_deinit(void) +{ + rcu_periph_reset_enable(RCU_WWDGTRST); + rcu_periph_reset_disable(RCU_WWDGTRST); +} + +/*! + \brief start the window watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_enable(void) +{ + WWDGT_CTL |= WWDGT_CTL_WDGTEN; +} + +/*! + \brief configure the window watchdog timer counter value + \param[in] counter_value: 0x00 - 0x7F + \param[out] none + \retval none +*/ +void wwdgt_counter_update(uint16_t counter_value) +{ + uint32_t reg = 0U; + + reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); + reg |= CTL_CNT(counter_value); + + WWDGT_CTL = reg; +} + +/*! + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F + \param[in] window: 0x00 - 0x7F + \param[in] prescaler: wwdgt prescaler value + only one parameter can be selected which is shown as below: + \arg WWDGT_CFG_PSC_DIV1: the time base of window watchdog counter = (PCLK1/4096)/1 + \arg WWDGT_CFG_PSC_DIV2: the time base of window watchdog counter = (PCLK1/4096)/2 + \arg WWDGT_CFG_PSC_DIV4: the time base of window watchdog counter = (PCLK1/4096)/4 + \arg WWDGT_CFG_PSC_DIV8: the time base of window watchdog counter = (PCLK1/4096)/8 + \param[out] none + \retval none +*/ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) +{ + uint32_t reg_cfg = 0U, reg_ctl = 0U; + + /* clear WIN and PSC bits, clear CNT bit */ + reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); + reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); + + /* configure WIN and PSC bits, configure CNT bit */ + reg_cfg |= CFG_WIN(window); + reg_cfg |= prescaler; + reg_ctl |= CTL_CNT(counter); + + WWDGT_CTL = reg_ctl; + WWDGT_CFG = reg_cfg; +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; +} + +/*! + \brief check early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus wwdgt_flag_get(void) +{ + if(WWDGT_STAT & WWDGT_STAT_EWIF){ + return SET; + } + + return RESET; +} + +/*! + \brief clear early wakeup interrupt state of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_flag_clear(void) +{ + WWDGT_STAT &= (~WWDGT_STAT_EWIF); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.h new file mode 100644 index 00000000..0cf04a99 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_wwdgt.h @@ -0,0 +1,91 @@ +/*! + \file gd32vf103_wwdgt.h + \brief definitions for the WWDGT + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32VF103_WWDGT_H +#define GD32VF103_WWDGT_H +#ifdef __cplusplus +extern "C" { +#endif +#include "gd32vf103.h" + +/* WWDGT definitions */ +#define WWDGT WWDGT_BASE /*!< WWDGT base address */ + +/* registers definitions */ +#define WWDGT_CTL REG32((WWDGT) + 0x00000000U) /*!< WWDGT control register */ +#define WWDGT_CFG REG32((WWDGT) + 0x00000004U) /*!< WWDGT configuration register */ +#define WWDGT_STAT REG32((WWDGT) + 0x00000008U) /*!< WWDGT status register */ + +/* bits definitions */ +/* WWDGT_CTL */ +#define WWDGT_CTL_CNT BITS(0, 6) /*!< WWDGT counter value */ +#define WWDGT_CTL_WDGTEN BIT(7) /*!< WWDGT counter enable */ + +/* WWDGT_CFG */ +#define WWDGT_CFG_WIN BITS(0, 6) /*!< WWDGT counter window value */ +#define WWDGT_CFG_PSC BITS(7, 8) /*!< WWDGT prescaler divider value */ +#define WWDGT_CFG_EWIE BIT(9) /*!< early wakeup interrupt enable */ + +/* WWDGT_STAT */ +#define WWDGT_STAT_EWIF BIT(0) /*!< early wakeup interrupt flag */ + +/* constants definitions */ +#define CFG_PSC(regval) (BITS(7, 8) & ((uint32_t)(regval) << 7)) /*!< write value to WWDGT_CFG_PSC bit field */ +#define WWDGT_CFG_PSC_DIV1 CFG_PSC(0) /*!< the time base of WWDGT = (PCLK1/4096)/1 */ +#define WWDGT_CFG_PSC_DIV2 CFG_PSC(1) /*!< the time base of WWDGT = (PCLK1/4096)/2 */ +#define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ +#define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ + +/* function declarations */ +/* reset the window watchdog timer configuration */ +void wwdgt_deinit(void); +/* start the window watchdog timer counter */ +void wwdgt_enable(void); + +/* configure the window watchdog timer counter value */ +void wwdgt_counter_update(uint16_t counter_value); +/* configure counter value, window value, and prescaler divider value */ +void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); + +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); +/* check early wakeup interrupt state of WWDGT */ +FlagStatus wwdgt_flag_get(void); +/* clear early wakeup interrupt state of WWDGT */ +void wwdgt_flag_clear(void); + +#endif /* GD32VF103_WWDGT_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c new file mode 100644 index 00000000..ecc22d05 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c @@ -0,0 +1,25 @@ +//See LICENSE for license details. +#include +#include +#include +#include "riscv_encoding.h" +#include "n200_func.h" + +__attribute__((weak)) uintptr_t handle_nmi() { + write(1, "nmi\n", 5); + _exit(1); + return 0; +} + +__attribute__((weak)) uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp) { + if ((mcause & 0xFFF) == 0xFFF) { + handle_nmi(); + } + write(1, "trap\n", 5); + printf("In trap handler, the mcause is %d\n", mcause); + printf("In trap handler, the mepc is 0x%x\n", read_csr(mepc)); + printf("In trap handler, the mtval is 0x%x\n", read_csr(mbadaddr)); + _exit(mcause); + return 0; +} + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.h new file mode 100644 index 00000000..256226d0 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.h @@ -0,0 +1,15 @@ +#ifndef HANDLERS_H_ +#define HANDLERS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); +unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c new file mode 100644 index 00000000..39a72ab2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c @@ -0,0 +1,34 @@ +//See LICENSE for license details. +#include +#include +#include +#include +#include "riscv_encoding.h" +#include "n200_func.h" + +extern uint32_t disable_mcycle_minstret(); +void _init() +{ + SystemInit(); + + //ECLIC init + eclic_init(ECLIC_NUM_INTERRUPTS); + eclic_mode_enable(); + + //printf("After ECLIC mode enabled, the mtvec value is %x \n\n\r", read_csr(mtvec)); + + // // It must be NOTED: + // // * In the RISC-V arch, if user mode and PMP supported, then by default if PMP is not configured + // // with valid entries, then user mode cannot access any memory, and cannot execute any instructions. + // // * So if switch to user-mode and still want to continue, then you must configure PMP first + //pmp_open_all_space(); + //switch_m2u_mode(); + + /* Before enter into main, add the cycle/instret disable by default to save power, + only use them when needed to measure the cycle/instret */ + disable_mcycle_minstret(); +} + +void _fini() +{ +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/integer.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/integer.h new file mode 100644 index 00000000..bddb78de --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/integer.h @@ -0,0 +1,50 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef _INTEGER + +#if 0 +#include +#else + +#include "usb_conf.h" + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef signed char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +/* Boolean type */ +// typedef enum { FALSE = 0, TRUE } BOOL; +#include +//typedef bool BOOL; +#ifndef FALSE +#define FALSE false +#define TRUE true +#endif + +#endif + +#define _INTEGER +#endif +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S new file mode 100644 index 00000000..e90ebaa2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Nuclei Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/****************************************************************************** + * \file intexc_gd32vf103.S + * \brief NMSIS Interrupt and Exception Handling Template File + * for Device gd32vf103 + * \version V1.00 + * \date 7 Jan 2020 + * + ******************************************************************************/ + +#include "riscv_encoding.h" + +/* Default Handler for Exceptions / Interrupts */ +.global default_intexc_handler +.weak default_intexc_handler +Undef_Handler: +default_intexc_handler: +1: + j 1b diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c new file mode 100644 index 00000000..c874f678 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c @@ -0,0 +1,13 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include + +#include "stub.h" + +ssize_t _read(int fd, void* ptr, size_t len) +{ + return _stub(EBADF); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.c new file mode 100644 index 00000000..f2b28938 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.c @@ -0,0 +1,205 @@ +/*! + \file rtc.c + \brief RTC check and config,time_show and time_adjust function + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "rtc.h" + +/* enter the second interruption,set the second interrupt flag to 1 */ +__IO uint32_t timedisplay; + +/*! + \brief configure the RTC + \param[in] none + \param[out] none + \retval none +*/ +void rtc_configuration(void) +{ + /* enable PMU and BKPI clocks */ + rcu_periph_clock_enable(RCU_BKPI); + rcu_periph_clock_enable(RCU_PMU); + /* allow access to BKP domain */ + pmu_backup_write_enable(); + + /* reset backup domain */ + bkp_deinit(); + + /* enable LXTAL */ + rcu_osci_on(RCU_LXTAL); + /* wait till LXTAL is ready */ + rcu_osci_stab_wait(RCU_LXTAL); + + /* select RCU_LXTAL as RTC clock source */ + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); + + /* enable RTC Clock */ + rcu_periph_clock_enable(RCU_RTC); + + /* wait for RTC registers synchronization */ + rtc_register_sync_wait(); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + + /* enable the RTC second interrupt*/ + rtc_interrupt_enable(RTC_INT_SECOND); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + + /* set RTC prescaler: set RTC period to 1s */ + rtc_prescaler_set(32767); + + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); +} + +/*! + \brief return the time entered by user, using Hyperterminal + \param[in] none + \param[out] none + \retval current time of RTC counter value +*/ +uint32_t time_regulate(void) +{ + uint32_t tmp_hh = 0xFF, tmp_mm = 0xFF, tmp_ss = 0xFF; + + printf("\r\n==============Time Settings====================================="); + printf("\r\n Please Set Hours"); + + while (tmp_hh == 0xFF){ + tmp_hh = usart_scanf(23); + } + printf(": %d", tmp_hh); + printf("\r\n Please Set Minutes"); + while (tmp_mm == 0xFF){ + tmp_mm = usart_scanf(59); + } + printf(": %d", tmp_mm); + printf("\r\n Please Set Seconds"); + while (tmp_ss == 0xFF){ + tmp_ss = usart_scanf(59); + } + printf(": %d", tmp_ss); + + /* return the value store in RTC counter register */ + return((tmp_hh*3600 + tmp_mm*60 + tmp_ss)); +} + +/*! + \brief adjust time + \param[in] none + \param[out] none + \retval none +*/ +void time_adjust(void) +{ + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); + /* change the current time */ + rtc_counter_set(time_regulate()); + /* wait until last write operation on RTC registers has finished */ + rtc_lwoff_wait(); +} + +/*! + \brief display the current time + \param[in] timeVar: RTC counter value + \param[out] none + \retval none +*/ +void time_display(uint32_t timevar) +{ + uint32_t thh = 0, tmm = 0, tss = 0; + + /* compute hours */ + thh = timevar / 3600; + /* compute minutes */ + tmm = (timevar % 3600) / 60; + /* compute seconds */ + tss = (timevar % 3600) % 60; + + printf(" Time: %0.2d:%0.2d:%0.2d\r\n", thh, tmm, tss); +} + +/*! + \brief show the current time (HH:MM:SS) on the Hyperterminal + \param[in] none + \param[out] none + \retval none +*/ +void time_show(void) +{ + printf("\n\r"); + + /* infinite loop */ + while (1){ + /* if 1s has paased */ + if (timedisplay == 1){ + /* display current time */ + time_display(rtc_counter_get()); + timedisplay = 0; + } + } +} + +/*! + \brief get numeric values from the hyperterminal + \param[in] value: input value from the hyperterminal + \param[out] none + \retval input value in BCD mode +*/ +uint8_t usart_scanf(uint32_t value) +{ + uint32_t index = 0; + uint32_t tmp[2] = {0, 0}; + + while (index < 2){ + /* loop until RBNE = 1 */ + while (usart_flag_get(USART0, USART_FLAG_RBNE) == RESET); + tmp[index++] = (usart_data_receive(USART0)); + + if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)){ + printf("\n\rPlease enter valid number between 0 and 9\n"); + index--; + } + } + /* calculate the Corresponding value */ + index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10); + /* check */ + if (index > value){ + printf("\n\rPlease enter valid number between 0 and %d\n", value); + return 0xFF; + } + return index; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.h new file mode 100644 index 00000000..8258bd42 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/rtc.h @@ -0,0 +1,54 @@ +/*! + \file rtc.h + \brief headfile of RTC check and config,time_show and time_adjust function + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef __RTC_H +#define __RTC_H + +#include "gd32vf103.h" +#include + +void rtc_configuration(void); +uint32_t time_regulate(void); +void time_adjust(void); +void time_display(uint32_t timevar); +void time_show(void); +uint8_t usart_scanf(uint32_t value); + +#endif /* __RTC_H */ + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h new file mode 100644 index 00000000..791615c7 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h @@ -0,0 +1,22 @@ +#ifdef __cplusplus +extern "C" { +#endif +/* See LICENSE of license details. */ +#ifndef _NUCLEI_SYS_STUB_H +#define _NUCLEI_SYS_STUB_H + +#include +#include + +void write_hex(int fd, unsigned long int hex); + +static inline int _stub(int err) { + return -1; +} + +void _exit(int code); + +#endif /* _NUCLEI_SYS_STUB_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.c new file mode 100644 index 00000000..0c3bc4f8 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.c @@ -0,0 +1,999 @@ +/*! + \file system_gd32vf103.c + \brief RISC-V Device Peripheral Access Layer Source File for + GD32VF103 Device Series + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* This file refers the RISC-V standard, some adjustments are made according to + * GigaDevice chips */ + +#include "gd32vf103.h" + +/* system frequency define */ +#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */ +#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */ +#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */ + +/* select a system clock by uncommenting the following line */ +/* use IRC8M */ +//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000) +#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000) + +/********************************************************************/ +//#define __SYSTEM_CLOCK_HXTAL (HXTAL_VALUE) +//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000) +/********************************************************************/ + +//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000) +//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000) +//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000) +//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000) +//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000) +// #define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) + +#define SEL_IRC8M 0x00U +#define SEL_HXTAL 0x01U +#define SEL_PLL 0x02U + +/* set the system clock frequency and declare the system clock configuration + * function */ +#ifdef __SYSTEM_CLOCK_48M_PLL_IRC8M +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_IRC8M; +static void system_clock_48m_irc8m(void); +#elif defined(__SYSTEM_CLOCK_72M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_IRC8M; +static void system_clock_72m_irc8m(void); +#elif defined(__SYSTEM_CLOCK_108M_PLL_IRC8M) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_IRC8M; +static void system_clock_108m_irc8m(void); + +#elif defined(__SYSTEM_CLOCK_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_HXTAL; +static void system_clock_hxtal(void); +#elif defined(__SYSTEM_CLOCK_24M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_24M_PLL_HXTAL; +static void system_clock_24m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_36M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_36M_PLL_HXTAL; +static void system_clock_36m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_48M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_48M_PLL_HXTAL; +static void system_clock_48m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_56M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_56M_PLL_HXTAL; +static void system_clock_56m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_72M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_72M_PLL_HXTAL; +static void system_clock_72m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_96M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_96M_PLL_HXTAL; +static void system_clock_96m_hxtal(void); +#elif defined(__SYSTEM_CLOCK_108M_PLL_HXTAL) +uint32_t SystemCoreClock = __SYSTEM_CLOCK_108M_PLL_HXTAL; +static void system_clock_108m_hxtal(void); +#else +uint32_t SystemCoreClock = IRC8M_VALUE; +#endif /* __SYSTEM_CLOCK_48M_PLL_IRC8M */ + +/* configure the system clock */ +static void system_clock_config(void); + +/*! + \brief configure the system clock + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_config(void) { +#ifdef __SYSTEM_CLOCK_HXTAL + system_clock_hxtal(); +#elif defined(__SYSTEM_CLOCK_24M_PLL_HXTAL) + system_clock_24m_hxtal(); +#elif defined(__SYSTEM_CLOCK_36M_PLL_HXTAL) + system_clock_36m_hxtal(); +#elif defined(__SYSTEM_CLOCK_48M_PLL_HXTAL) + system_clock_48m_hxtal(); +#elif defined(__SYSTEM_CLOCK_56M_PLL_HXTAL) + system_clock_56m_hxtal(); +#elif defined(__SYSTEM_CLOCK_72M_PLL_HXTAL) + system_clock_72m_hxtal(); +#elif defined(__SYSTEM_CLOCK_96M_PLL_HXTAL) + system_clock_96m_hxtal(); +#elif defined(__SYSTEM_CLOCK_108M_PLL_HXTAL) + system_clock_108m_hxtal(); + +#elif defined(__SYSTEM_CLOCK_48M_PLL_IRC8M) + system_clock_48m_irc8m(); +#elif defined(__SYSTEM_CLOCK_72M_PLL_IRC8M) + system_clock_72m_irc8m(); +#elif defined(__SYSTEM_CLOCK_108M_PLL_IRC8M) + system_clock_108m_irc8m(); +#endif /* __SYSTEM_CLOCK_HXTAL */ +} + +/*! + \brief setup the microcontroller system, initialize the system + \param[in] none + \param[out] none + \retval none +*/ +void SystemInit(void) { + /* reset the RCC clock configuration to the default reset state */ + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ + RCU_CFG0 &= + ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | + RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); + + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + + /* Reset HXTALBPS bit */ + RCU_CTL &= ~(RCU_CTL_HXTALBPS); + + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ + + RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | + RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); + RCU_CFG1 = 0x00000000U; + + /* Reset HXTALEN, CKMEN, PLLEN, PLL1EN and PLL2EN bits */ + RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_PLL1EN | RCU_CTL_PLL2EN | RCU_CTL_CKMEN | + RCU_CTL_HXTALEN); + /* disable all interrupts */ + RCU_INT = 0x00FF0000U; + + /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and + * Flash settings */ + system_clock_config(); +} + +/*! + \brief update the SystemCoreClock with current core clock retrieved + from cpu registers \param[in] none \param[out] none \retval none +*/ +void SystemCoreClockUpdate(void) { + uint32_t scss; + uint32_t pllsel, predv0sel, pllmf, ck_src; + uint32_t predv0, predv1, pll1mf; + + scss = GET_BITS(RCU_CFG0, 2, 3); + + switch (scss) { + /* IRC8M is selected as CK_SYS */ + case SEL_IRC8M: + SystemCoreClock = IRC8M_VALUE; + break; + + /* HXTAL is selected as CK_SYS */ + case SEL_HXTAL: + SystemCoreClock = HXTAL_VALUE; + break; + + /* PLL is selected as CK_SYS */ + case SEL_PLL: + /* PLL clock source selection, HXTAL or IRC8M/2 */ + pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); + + if (RCU_PLLSRC_IRC8M_DIV2 == pllsel) { + /* PLL clock source is IRC8M/2 */ + ck_src = IRC8M_VALUE / 2U; + } else { + /* PLL clock source is HXTAL */ + ck_src = HXTAL_VALUE; + + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); + + /* source clock use PLL1 */ + if (RCU_PREDV0SRC_CKPLL1 == predv0sel) { + predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; + pll1mf = ((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; + if (17U == pll1mf) { + pll1mf = 20U; + } + ck_src = (ck_src / predv1) * pll1mf; + } + predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; + ck_src /= predv0; + } + + /* PLL multiplication factor */ + pllmf = GET_BITS(RCU_CFG0, 18, 21); + + if ((RCU_CFG0 & RCU_CFG0_PLLMF_4)) { + pllmf |= 0x10U; + } + + if (pllmf >= 15U) { + pllmf += 1U; + } else { + pllmf += 2U; + } + + SystemCoreClock = ck_src * pllmf; + + if (15U == pllmf) { + /* PLL source clock multiply by 6.5 */ + SystemCoreClock = ck_src * 6U + ck_src / 2U; + } + + break; + + /* IRC8M is selected as CK_SYS */ + default: + SystemCoreClock = IRC8M_VALUE; + break; + } +} + +#ifdef __SYSTEM_CLOCK_HXTAL +/*! + \brief configure the system clock to HXTAL + \param[in] none + \param[out] none + \retval none +*/ +static void system_clock_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* select HXTAL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; + + /* wait until HXTAL is selected as system clock */ + while (0 == (RCU_CFG0 & RCU_SCSS_HXTAL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_24M_PLL_HXTAL) +/*! + \brief configure the system clock to 24M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_24m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); + + if (HXTAL_VALUE == 25000000) { + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_36M_PLL_HXTAL) +/*! + \brief configure the system clock to 36M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_36m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); + + if (HXTAL_VALUE == 25000000) { + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_48M_PLL_HXTAL) +/*! + \brief configure the system clock to 48M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_48m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); + + if (HXTAL_VALUE == 25000000) { + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_56M_PLL_HXTAL) +/*! + \brief configure the system clock to 56M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_56m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 14 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL14); + + if (HXTAL_VALUE == 25000000) { + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_72M_PLL_HXTAL) +/*! + \brief configure the system clock to 72M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_72m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL18); + + if (HXTAL_VALUE == 25000000) { + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_96M_PLL_HXTAL) +/*! + \brief configure the system clock to 96M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ +static void system_clock_96m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + if (HXTAL_VALUE == 25000000) { + + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | + RCU_PREDV0_DIV10); + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while ((RCU_CTL & RCU_CTL_PLL1STB) == 0) { + } + + } else if (HXTAL_VALUE == 8000000) { + /* CK_PLL = (CK_PREDIV0) * 24 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL24); + + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2); + } + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_108M_PLL_HXTAL) +/*! + \brief configure the system clock to 108M by PLL which selects + HXTAL(MD/HD/XD:8M; CL:25M) as its clock source \param[in] none \param[out] + none \retval none +*/ + +static void system_clock_108m_hxtal(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable HXTAL */ + RCU_CTL |= RCU_CTL_HXTALEN; + + /* wait until HXTAL is stable or the startup time is longer than + * HXTAL_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); + } while ((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while (1) { + } + } + + /* HXTAL is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_PREDIV0) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL27); + + if (HXTAL_VALUE == 25000000) { + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PREDV1_DIV5 | RCU_PLL1_MUL8 | + RCU_PREDV0_DIV10); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) { + } + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL2EN; + /* wait till PLL1 is ready */ + while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) { + } + } else if (HXTAL_VALUE == 8000000) { + RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | + RCU_CFG1_PREDV0); + RCU_CFG1 |= (RCU_PREDV0SRC_HXTAL | RCU_PREDV0_DIV2 | RCU_PREDV1_DIV2 | + RCU_PLL1_MUL20 | RCU_PLL2_MUL20); + + /* enable PLL1 */ + RCU_CTL |= RCU_CTL_PLL1EN; + /* wait till PLL1 is ready */ + while (0U == (RCU_CTL & RCU_CTL_PLL1STB)) { + } + + /* enable PLL2 */ + RCU_CTL |= RCU_CTL_PLL2EN; + /* wait till PLL1 is ready */ + while (0U == (RCU_CTL & RCU_CTL_PLL2STB)) { + } + } + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_48M_PLL_IRC8M) +/*! + \brief configure the system clock to 48M by PLL which selects IRC8M as + its clock source \param[in] none \param[out] none \retval none +*/ +static void system_clock_48m_irc8m(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than + * IRC8M_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } while ((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while (1) { + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL12; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_72M_PLL_IRC8M) +/*! + \brief configure the system clock to 72M by PLL which selects IRC8M as + its clock source \param[in] none \param[out] none \retval none +*/ +static void system_clock_72m_irc8m(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than + * IRC8M_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } while ((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while (1) { + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL18; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#elif defined(__SYSTEM_CLOCK_108M_PLL_IRC8M) +/*! + \brief configure the system clock to 108M by PLL which selects IRC8M as + its clock source \param[in] none \param[out] none \retval none +*/ +static void system_clock_108m_irc8m(void) { + uint32_t timeout = 0U; + uint32_t stab_flag = 0U; + + /* enable IRC8M */ + RCU_CTL |= RCU_CTL_IRC8MEN; + + /* wait until IRC8M is stable or the startup time is longer than + * IRC8M_STARTUP_TIMEOUT */ + do { + timeout++; + stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); + } while ((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + + /* if fail */ + if (0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while (1) { + } + } + + /* IRC8M is stable */ + /* AHB = SYSCLK */ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; + /* APB2 = AHB/1 */ + RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; + /* APB1 = AHB/2 */ + RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; + + /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4); + RCU_CFG0 |= RCU_PLL_MUL27; + + /* enable PLL */ + RCU_CTL |= RCU_CTL_PLLEN; + + /* wait until PLL is stable */ + while (0U == (RCU_CTL & RCU_CTL_PLLSTB)) { + } + + /* select PLL as system clock */ + RCU_CFG0 &= ~RCU_CFG0_SCS; + RCU_CFG0 |= RCU_CKSYSSRC_PLL; + + /* wait until PLL is selected as system clock */ + while (0U == (RCU_CFG0 & RCU_SCSS_PLL)) { + } +} + +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.h new file mode 100644 index 00000000..14aefa92 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/system_gd32vf103.h @@ -0,0 +1,60 @@ +/*! + \file system_gd32vf103.h + \brief RISC-V Device Peripheral Access Layer Header File for + GD32VF103 Device Series + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/* This file refers the RISC-V standard, some adjustments are made according to GigaDevice chips */ + +#ifndef SYSTEM_GD32VF103_H +#define SYSTEM_GD32VF103_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* system clock frequency (core clock) */ +extern uint32_t SystemCoreClock; + +/* function declarations */ +/* initialize the system and update the SystemCoreClock variable */ +extern void SystemInit(void); +/* update the SystemCoreClock with current core clock retrieved from cpu registers */ +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_GD32VF103_H */ diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.c new file mode 100644 index 00000000..7d30da30 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.c @@ -0,0 +1,57 @@ +/*! + \file systick.c + \brief the systick configuration file + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "gd32vf103.h" +#include "systick.h" + +/*! + \brief delay a time in milliseconds + \param[in] count: count in milliseconds + \param[out] none + \retval none +*/ +void delay_1ms(uint32_t count) +{ + uint64_t start_mtime, delta_mtime; + + // Don't start measuruing until we see an mtime tick + uint64_t tmp = get_timer_value(); + do { + start_mtime = get_timer_value(); + } while (start_mtime == tmp); + + do { + delta_mtime = get_timer_value() - start_mtime; + }while(delta_mtime <(SystemCoreClock/4000.0 *count )); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.h new file mode 100644 index 00000000..ed36d482 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/systick.h @@ -0,0 +1,47 @@ +/*! + \file systick.h + \brief the header file of systick + + \version 2019-06-05, V1.0.0, firmware for GD32VF103 +*/ + +/* + Copyright (c) 2019, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ +#ifdef __cplusplus +extern "C" { +#endif +#ifndef SYS_TICK_H +#define SYS_TICK_H + +#include + +void delay_1ms(uint32_t count); + +#endif /* SYS_TICK_H */ +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c new file mode 100644 index 00000000..8836b701 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c @@ -0,0 +1,47 @@ +/* See LICENSE of license details. */ + +#include +#include +#include +#include +#include +#include + +#include "stub.h" +#include "gd32vf103.h" + +typedef unsigned int size_t; + +extern int _put_char(int ch) __attribute__((weak)); + +ssize_t _write(int fd, const void* ptr, size_t len) { + const uint8_t * current = (const uint8_t *) ptr; + +// if (isatty(fd)) + { + for (size_t jj = 0; jj < len; jj++) { + _put_char(current[jj]); + + if (current[jj] == '\n') { + _put_char('\r'); + } + } + return len; + } + + return _stub(EBADF); +} + +int puts(const char* string) { + return _write(0, (const void *) string, strlen(string)); +} + +int _put_char(int ch) +{ + usart_data_transmit(USART0, (uint8_t) ch ); + while (usart_flag_get(USART0, USART_FLAG_TBE)== RESET){ + } + + return ch; +} + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write_hex.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write_hex.c new file mode 100644 index 00000000..f7aa9a4b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write_hex.c @@ -0,0 +1,18 @@ +/* See LICENSE of license details. */ + +#include +#include + +void write_hex(int fd, unsigned long int hex) +{ + uint8_t ii; + uint8_t jj; + char towrite; + write(fd , "0x", 2); + for (ii = sizeof(unsigned long int) * 2 ; ii > 0; ii--) { + jj = ii - 1; + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + write(fd, &towrite, 1); + } +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/your_printf.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/your_printf.c new file mode 100644 index 00000000..41d4cd84 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/your_printf.c @@ -0,0 +1,4 @@ +int __wrap_printf(const char *fmt, ...) { + //:D + +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S new file mode 100644 index 00000000..67987d26 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S @@ -0,0 +1,291 @@ +#include "riscv_encoding.h" +#include "riscv_bits.h" +#include "n200_eclic.h" +#include "n200_timer.h" + +#define USE_MSP 1 //启用中断栈 + + +/** + * @brief 压栈通用寄存器 + * @param x 目标sp寄存器 + */ +.macro pushREGFILE x +#ifdef __riscv_flen + addi \x, \x, -REGBYTES * 68 //36+32 +#else + addi \x, \x, -REGBYTES * 36 +#endif + STORE x1, 1 * REGBYTES(\x) + STORE x2, 2 * REGBYTES(\x) + #STORE x3, 3 * REGBYTES(\x) + #STORE x4, 4 * REGBYTES(\x) + STORE x5, 5 * REGBYTES(\x) + STORE x6, 6 * REGBYTES(\x) + STORE x7, 7 * REGBYTES(\x) + STORE x8, 8 * REGBYTES(\x) + STORE x9, 9 * REGBYTES(\x) + STORE x10, 10 * REGBYTES(\x) + STORE x11, 11 * REGBYTES(\x) + STORE x12, 12 * REGBYTES(\x) + STORE x13, 13 * REGBYTES(\x) + STORE x14, 14 * REGBYTES(\x) + STORE x15, 15 * REGBYTES(\x) +#ifndef __riscv_32e + STORE x16, 16 * REGBYTES(\x) + STORE x17, 17 * REGBYTES(\x) + STORE x18, 18 * REGBYTES(\x) + STORE x19, 19 * REGBYTES(\x) + STORE x20, 20 * REGBYTES(\x) + STORE x21, 21 * REGBYTES(\x) + STORE x22, 22 * REGBYTES(\x) + STORE x23, 23 * REGBYTES(\x) + STORE x24, 24 * REGBYTES(\x) + STORE x25, 25 * REGBYTES(\x) + STORE x26, 26 * REGBYTES(\x) + STORE x27, 27 * REGBYTES(\x) + STORE x28, 28 * REGBYTES(\x) + STORE x29, 29 * REGBYTES(\x) + STORE x30, 30 * REGBYTES(\x) + STORE x31, 31 * REGBYTES(\x) +#endif +.endm + + +/** + * @brief 压栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) + * @param x 目标sp寄存器 + */ +.macro portSAVE_CONTEXT_EXCP x + csrr t0, CSR_MSTATUS + STORE t0, 32 * REGBYTES(\x) + csrr t0, CSR_MEPC + STORE t0, 33 * REGBYTES(\x) + csrr t0, CSR_MSUBM + STORE t0, 34 * REGBYTES(\x) + csrr t0, CSR_MCAUSE + STORE t0, 35 * REGBYTES(\x) +.endm + + +/** + * @brief 压栈浮点寄存器 + * @param x 目标sp寄存器 + */ +.macro popVFPREGFILE x + flw f0, 36 * REGBYTES(\x) + flw f1, 37 * REGBYTES(\x) + flw f2, 38 * REGBYTES(\x) + flw f3, 39 * REGBYTES(\x) + flw f4, 40 * REGBYTES(\x) + flw f5, 41 * REGBYTES(\x) + flw f6, 42 * REGBYTES(\x) + flw f7, 43 * REGBYTES(\x) + flw f8, 44 * REGBYTES(\x) + flw f9, 45 * REGBYTES(\x) + flw f10,46 * REGBYTES(\x) + flw f11, 47 * REGBYTES(\x) + flw f12, 48 * REGBYTES(\x) + flw f13, 49 * REGBYTES(\x) + flw f14, 50 * REGBYTES(\x) + flw f15, 51 * REGBYTES(\x) + flw f16, 52 * REGBYTES(\x) + flw f17, 53 * REGBYTES(\x) + flw f18, 54 * REGBYTES(\x) + flw f19, 55 * REGBYTES(\x) + flw f20, 56 * REGBYTES(\x) + flw f21, 57 * REGBYTES(\x) + flw f22, 58 * REGBYTES(\x) + flw f23, 59 * REGBYTES(\x) + flw f24, 60 * REGBYTES(\x) + flw f25, 61 * REGBYTES(\x) + flw f26, 62 * REGBYTES(\x) + flw f27, 63 * REGBYTES(\x) + flw f28, 64 * REGBYTES(\x) + flw f29, 65 * REGBYTES(\x) + flw f30, 66 * REGBYTES(\x) + flw f31, 67 * REGBYTES(\x) +.endm + + +/** + * @brief 出栈通用寄存器 + * @param x 目标sp寄存器 + */ +.macro popREGFILE x + LOAD x1, 1 * REGBYTES(\x) + #LOAD x2, 2 * REGBYTES(\x) + #LOAD x3, 3 * REGBYTES(\x) + #LOAD x4, 4 * REGBYTES(\x) + LOAD x5, 5 * REGBYTES(\x) + LOAD x6, 6 * REGBYTES(\x) + LOAD x7, 7 * REGBYTES(\x) + LOAD x8, 8 * REGBYTES(\x) + LOAD x9, 9 * REGBYTES(\x) + LOAD x10, 10 * REGBYTES(\x) + LOAD x11, 11 * REGBYTES(\x) + LOAD x12, 12 * REGBYTES(\x) + LOAD x13, 13 * REGBYTES(\x) + LOAD x14, 14 * REGBYTES(\x) + LOAD x15, 15 * REGBYTES(\x) +#ifndef __riscv_32e + LOAD x16, 16 * REGBYTES(\x) + LOAD x17, 17 * REGBYTES(\x) + LOAD x18, 18 * REGBYTES(\x) + LOAD x19, 19 * REGBYTES(\x) + LOAD x20, 20 * REGBYTES(\x) + LOAD x21, 21 * REGBYTES(\x) + LOAD x22, 22 * REGBYTES(\x) + LOAD x23, 23 * REGBYTES(\x) + LOAD x24, 24 * REGBYTES(\x) + LOAD x25, 25 * REGBYTES(\x) + LOAD x26, 26 * REGBYTES(\x) + LOAD x27, 27 * REGBYTES(\x) + LOAD x28, 28 * REGBYTES(\x) + LOAD x29, 29 * REGBYTES(\x) + LOAD x30, 30 * REGBYTES(\x) + LOAD x31, 31 * REGBYTES(\x) +#endif +#ifdef __riscv_flen + addi \x, \x, REGBYTES * 68 //36+32 +#else + addi \x, \x, REGBYTES * 36 +#endif +.endm + + +/** + * @brief 出栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) + * @param x 目标sp寄存器 + */ +.macro portRESTORE_CONTEXT_EXCP x + LOAD t0, 35*REGBYTES(\x) + csrw CSR_MCAUSE, t0 + LOAD t0, 34*REGBYTES(\x) + csrw CSR_MSUBM, t0 + LOAD t0, 33*REGBYTES(\x) + csrw CSR_MEPC, t0 + LOAD t0, 32*REGBYTES(\x) + csrw CSR_MSTATUS, t0 +.endm + + +/** + * @brief 出栈浮点寄存器 + * @param x 目标sp寄存器 + */ +.macro pushVFPREGFILE x + fsw f0, 36 * REGBYTES(\x) + fsw f1, 37 * REGBYTES(\x) + fsw f2, 38 * REGBYTES(\x) + fsw f3, 39 * REGBYTES(\x) + fsw f4, 40 * REGBYTES(\x) + fsw f5, 41 * REGBYTES(\x) + fsw f6, 42 * REGBYTES(\x) + fsw f7, 43 * REGBYTES(\x) + fsw f8, 44 * REGBYTES(\x) + fsw f9, 45 * REGBYTES(\x) + fsw f10, 46 * REGBYTES(\x) + fsw f11, 47 * REGBYTES(\x) + fsw f12, 48 * REGBYTES(\x) + fsw f13, 49 * REGBYTES(\x) + fsw f14, 50 * REGBYTES(\x) + fsw f15, 51 * REGBYTES(\x) + fsw f16, 52 * REGBYTES(\x) + fsw f17, 53 * REGBYTES(\x) + fsw f18, 54 * REGBYTES(\x) + fsw f19, 55 * REGBYTES(\x) + fsw f20, 56 * REGBYTES(\x) + fsw f21, 57 * REGBYTES(\x) + fsw f22, 58 * REGBYTES(\x) + fsw f23, 59 * REGBYTES(\x) + fsw f24, 60 * REGBYTES(\x) + fsw f25, 61 * REGBYTES(\x) + fsw f26, 62 * REGBYTES(\x) + fsw f27, 63 * REGBYTES(\x) + fsw f28, 64 * REGBYTES(\x) + fsw f29, 65 * REGBYTES(\x) + fsw f30, 66 * REGBYTES(\x) + fsw f31, 67 * REGBYTES(\x) +.endm + + +/** + * @brief 清理fpu状态寄存器 + */ +.macro CONFIG_FS_CLEAN + li t0, (0x1 << 13) //配置FS为clean状态 + csrc mstatus, t0 + li t0, (0x1 << 14) + csrs mstatus, t0 +.endm + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brief trap入口函数 + */ + .section .text.trap + .align 6// In CLIC mode, the trap entry must be 64bytes aligned + .global trap_entry + .weak trap_entry +trap_entry: + pushREGFILE sp //trap这里就直接使用当前栈,方便对当前位置进行异常分析, + //同时不担心(任务栈/中断栈/主栈)溢出,因为程序进入这里便不会返回了 + portSAVE_CONTEXT_EXCP sp + + csrr a0, mcause + mv a1, sp + jal ulSynchTrap + mv sp, a0 + + portRESTORE_CONTEXT_EXCP sp + popREGFILE sp + mret + + +/* -------------------------------------------------------------------------------------------------------- */ +/** + * @brief irq入口函数 + */ + .section .text.irq + .align 2 + .global irq_entry + .weak irq_entry +irq_entry: +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + pushREGFILE sp //保存通用寄存器 + portSAVE_CONTEXT_EXCP sp +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1, t2, t0 + bne t1, t0, 1f //浮点寄存器状态为Dirty状态,则保存浮点寄存器, 否则不用保存 + pushVFPREGFILE sp +1: + CONFIG_FS_CLEAN +#endif + + csrrw ra, CSR_JALMNXTI, ra //跳转到中断向量表入口地址,中断处理返回时继续回到此处 + + csrc CSR_MSTATUS, MSTATUS_MIE //此时中断处理完毕,中断关闭,注意mret退出中断时将恢复从mpie恢复mie, + //因此在中断内部修改mie仅会保持中断mret前,退出中断将恢复为进中断前状态 +#ifdef __riscv_flen + csrr t2, mstatus + li t0, (0x3 << 13) + and t1, t2, t0 + bne t1, t0, 2f //浮点寄存器状态为Dirty状态,则恢复浮点寄存器, 否则不用恢复 + popVFPREGFILE sp +2: +#endif + portRESTORE_CONTEXT_EXCP sp +#ifdef __riscv_flen + CONFIG_FS_CLEAN +#endif + popREGFILE sp +#if USE_MSP + csrrw sp, CSR_MSCRATCHCSWL, sp +#endif + mret diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_eclic.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_eclic.h new file mode 100644 index 00000000..a1557488 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_eclic.h @@ -0,0 +1,48 @@ +// See LICENSE file for licence details + +#ifndef N200_ECLIC_H +#define N200_ECLIC_H + +#include + +#define ECLICINTCTLBITS 4 + +//ECLIC memory map +// Offset +// 0x0000 1B RW ecliccfg +#define ECLIC_CFG_OFFSET 0x0 +// 0x0004 4B R eclicinfo +#define ECLIC_INFO_OFFSET 0x4 +// 0x000B 1B RW mintthresh +#define ECLIC_MTH_OFFSET 0xB +// +// 0x1000+4*i 1B/input RW eclicintip[i] +#define ECLIC_INT_IP_OFFSET _AC(0x1000,UL) +// 0x1001+4*i 1B/input RW eclicintie[i] +#define ECLIC_INT_IE_OFFSET _AC(0x1001,UL) +// 0x1002+4*i 1B/input RW eclicintattr[i] +#define ECLIC_INT_ATTR_OFFSET _AC(0x1002,UL) + +#define ECLIC_INT_ATTR_SHV 0x01 +#define ECLIC_INT_ATTR_TRIG_LEVEL 0x00 +#define ECLIC_INT_ATTR_TRIG_EDGE 0x02 +#define ECLIC_INT_ATTR_TRIG_POS 0x00 +#define ECLIC_INT_ATTR_TRIG_NEG 0x04 + +// 0x1003+4*i 1B/input RW eclicintctl[i] +#define ECLIC_INT_CTRL_OFFSET _AC(0x1003,UL) +// +// ... +// +#define ECLIC_ADDR_BASE 0xd2000000 + + +#define ECLIC_CFG_NLBITS_MASK _AC(0x1E,UL) +#define ECLIC_CFG_NLBITS_LSB (1u) + +#define MSIP_HANDLER eclic_msip_handler +#define MTIME_HANDLER eclic_mtip_handler +#define BWEI_HANDLER eclic_bwei_handler +#define PMOVI_HANDLER eclic_pmovi_handler + +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.c b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.c new file mode 100644 index 00000000..b5890206 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.c @@ -0,0 +1,398 @@ +// See LICENSE for license details. +#include +#include +#include +#include +#include + +#include "riscv_encoding.h" +#include "n200_func.h" + + // Configure PMP to make all the address space accesable and executable +void pmp_open_all_space(){ + // Config entry0 addr to all 1s to make the range cover all space + asm volatile ("li x6, 0xffffffff":::"x6"); + asm volatile ("csrw pmpaddr0, x6":::); + // Config entry0 cfg to make it NAPOT address mode, and R/W/X okay + asm volatile ("li x6, 0x7f":::"x6"); + asm volatile ("csrw pmpcfg0, x6":::); +} + +void switch_m2u_mode(){ + clear_csr (mstatus,MSTATUS_MPP); + //printf("\nIn the m2u function, the mstatus is 0x%x\n", read_csr(mstatus)); + //printf("\nIn the m2u function, the mepc is 0x%x\n", read_csr(mepc)); + asm volatile ("la x6, 1f ":::"x6"); + asm volatile ("csrw mepc, x6":::); + asm volatile ("mret":::); + asm volatile ("1:":::); +} + +uint32_t mtime_lo(void) +{ + return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); +} + + +uint32_t mtime_hi(void) +{ + return *(volatile uint32_t *)(TIMER_CTRL_ADDR + TIMER_MTIME + 4); +} + +uint64_t get_timer_value() +{ + while (1) { + uint32_t hi = mtime_hi(); + uint32_t lo = mtime_lo(); + if (hi == mtime_hi()) + return ((uint64_t)hi << 32) | lo; + } +} + +uint32_t get_timer_freq() +{ + return TIMER_FREQ; +} + +uint64_t get_instret_value() +{ + while (1) { + uint32_t hi = read_csr(minstreth); + uint32_t lo = read_csr(minstret); + if (hi == read_csr(minstreth)) + return ((uint64_t)hi << 32) | lo; + } +} + +uint64_t get_cycle_value() +{ + while (1) { + uint32_t hi = read_csr(mcycleh); + uint32_t lo = read_csr(mcycle); + if (hi == read_csr(mcycleh)) + return ((uint64_t)hi << 32) | lo; + } +} + +uint32_t __attribute__((noinline)) measure_cpu_freq(size_t n) +{ + uint32_t start_mtime, delta_mtime; + uint32_t mtime_freq = get_timer_freq(); + + // Don't start measuruing until we see an mtime tick + uint32_t tmp = mtime_lo(); + do { + start_mtime = mtime_lo(); + } while (start_mtime == tmp); + + uint32_t start_mcycle = read_csr(mcycle); + + do { + delta_mtime = mtime_lo() - start_mtime; + } while (delta_mtime < n); + + uint32_t delta_mcycle = read_csr(mcycle) - start_mcycle; + + return (delta_mcycle / delta_mtime) * mtime_freq + + ((delta_mcycle % delta_mtime) * mtime_freq) / delta_mtime; +} + +uint32_t get_cpu_freq() +{ + uint32_t cpu_freq; + + // warm up + measure_cpu_freq(1); + // measure for real + cpu_freq = measure_cpu_freq(100); + + return cpu_freq; +} + + + +// Note that there are no assertions or bounds checking on these +// parameter values. + + + + +void eclic_init ( uint32_t num_irq ) +{ + + typedef volatile uint32_t vuint32_t; + + //clear cfg register + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET)=0; + + //clear minthresh register + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET)=0; + + //clear all IP/IE/ATTR/CTRL bits for all interrupt sources + vuint32_t * ptr; + + vuint32_t * base = (vuint32_t*)(ECLIC_ADDR_BASE + ECLIC_INT_IP_OFFSET); + vuint32_t * upper = (vuint32_t*)(base + num_irq*4); + + for (ptr = base; ptr < upper; ptr=ptr+4){ + *ptr = 0; + } +} + + + +void eclic_enable_interrupt (uint32_t source) { + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 1; +} + +void eclic_disable_interrupt (uint32_t source){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IE_OFFSET+source*4) = 0; +} + +void eclic_set_pending(uint32_t source){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 1; +} + +void eclic_clear_pending(uint32_t source){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_IP_OFFSET+source*4) = 0; +} + +void eclic_set_intctrl (uint32_t source, uint8_t intctrl){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4) = intctrl; +} + +uint8_t eclic_get_intctrl (uint32_t source){ + return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_CTRL_OFFSET+source*4); +} + +void eclic_set_intattr (uint32_t source, uint8_t intattr){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4) = intattr; +} + +uint8_t eclic_get_intattr (uint32_t source){ + return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_INT_ATTR_OFFSET+source*4); +} + +void eclic_set_cliccfg (uint8_t cliccfg){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET) = cliccfg; +} + +uint8_t eclic_get_cliccfg (){ + return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_CFG_OFFSET); +} + +void eclic_set_mth (uint8_t mth){ + *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET) = mth; +} + +uint8_t eclic_get_mth (){ + return *(volatile uint8_t*)(ECLIC_ADDR_BASE+ECLIC_MTH_OFFSET); +} + +//sets nlbits +void eclic_set_nlbits(uint8_t nlbits) { + //shift nlbits to correct position + uint8_t nlbits_shifted = nlbits << ECLIC_CFG_NLBITS_LSB; + + //read the current cliccfg + uint8_t old_cliccfg = eclic_get_cliccfg(); + uint8_t new_cliccfg = (old_cliccfg & (~ECLIC_CFG_NLBITS_MASK)) | (ECLIC_CFG_NLBITS_MASK & nlbits_shifted); + + eclic_set_cliccfg(new_cliccfg); +} + +//get nlbits +uint8_t eclic_get_nlbits(void) { + //extract nlbits + uint8_t nlbits = eclic_get_cliccfg(); + nlbits = (nlbits & ECLIC_CFG_NLBITS_MASK) >> ECLIC_CFG_NLBITS_LSB; + return nlbits; +} + +//sets an interrupt level based encoding of nlbits and ECLICINTCTLBITS +void eclic_set_irq_lvl(uint32_t source, uint8_t lvl) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits > ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + } + + //shift lvl right to mask off unused bits + lvl = lvl >> (8-nlbits); + //shift lvl into correct bit position + lvl = lvl << (8-nlbits); + + //write to clicintctrl + uint8_t current_intctrl = eclic_get_intctrl(source); + //shift intctrl left to mask off unused bits + current_intctrl = current_intctrl << nlbits; + //shift intctrl into correct bit position + current_intctrl = current_intctrl >> nlbits; + + eclic_set_intctrl(source, (current_intctrl | lvl)); +} + +//gets an interrupt level based encoding of nlbits +uint8_t eclic_get_irq_lvl(uint32_t source) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits > ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + } + + uint8_t intctrl = eclic_get_intctrl(source); + + //shift intctrl + intctrl = intctrl >> (8-nlbits); + //shift intctrl + uint8_t lvl = intctrl << (8-nlbits); + + return lvl; +} + +void eclic_set_irq_lvl_abs(uint32_t source, uint8_t lvl_abs) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits > ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + } + + //shift lvl_abs into correct bit position + uint8_t lvl = lvl_abs << (8-nlbits); + + //write to clicintctrl + uint8_t current_intctrl = eclic_get_intctrl(source); + //shift intctrl left to mask off unused bits + current_intctrl = current_intctrl << nlbits; + //shift intctrl into correct bit position + current_intctrl = current_intctrl >> nlbits; + + eclic_set_intctrl(source, (current_intctrl | lvl)); +} + +uint8_t eclic_get_irq_lvl_abs(uint32_t source) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits > ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + } + + uint8_t intctrl = eclic_get_intctrl(source); + + //shift intctrl + intctrl = intctrl >> (8-nlbits); + //shift intctrl + uint8_t lvl_abs = intctrl; + + return lvl_abs; +} + +//sets an interrupt priority based encoding of nlbits and ECLICINTCTLBITS +uint8_t eclic_set_irq_priority(uint32_t source, uint8_t priority) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits >= ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + return 0; + } + + //shift priority into correct bit position + priority = priority << (8 - ECLICINTCTLBITS); + + //write to eclicintctrl + uint8_t current_intctrl = eclic_get_intctrl(source); + //shift intctrl right to mask off unused bits + current_intctrl = current_intctrl >> (8-nlbits); + //shift intctrl into correct bit position + current_intctrl = current_intctrl << (8-nlbits); + + eclic_set_intctrl(source, (current_intctrl | priority)); + + return priority; +} + +//gets an interrupt priority based encoding of nlbits +uint8_t eclic_get_irq_priority(uint32_t source) { + //extract nlbits + uint8_t nlbits = eclic_get_nlbits(); + if (nlbits > ECLICINTCTLBITS) { + nlbits = ECLICINTCTLBITS; + } + + uint8_t intctrl = eclic_get_intctrl(source); + + //shift intctrl + intctrl = intctrl << nlbits; + //shift intctrl + uint8_t priority = intctrl >> (nlbits+(8 - ECLICINTCTLBITS)); + + return priority; +} + +void eclic_mode_enable() { + uint32_t mtvec_value = read_csr(mtvec); + mtvec_value = mtvec_value & 0xFFFFFFC0; + mtvec_value = mtvec_value | 0x00000003; + write_csr(mtvec,mtvec_value); +} + +//sets vector-mode or non-vector mode +void eclic_set_vmode(uint32_t source) { + //read the current attr + uint8_t old_intattr = eclic_get_intattr(source); + // Keep other bits unchanged and only set the LSB bit + uint8_t new_intattr = (old_intattr | 0x1); + + eclic_set_intattr(source,new_intattr); +} + +void eclic_set_nonvmode(uint32_t source) { + //read the current attr + uint8_t old_intattr = eclic_get_intattr(source); + // Keep other bits unchanged and only clear the LSB bit + uint8_t new_intattr = (old_intattr & (~0x1)); + + eclic_set_intattr(source,new_intattr); +} + +//sets interrupt as level sensitive +//Bit 1, trig[0], is defined as "edge-triggered" (0: level-triggered, 1: edge-triggered); +//Bit 2, trig[1], is defined as "negative-edge" (0: positive-edge, 1: negative-edge). + +void eclic_set_level_trig(uint32_t source) { + //read the current attr + uint8_t old_intattr = eclic_get_intattr(source); + // Keep other bits unchanged and only clear the bit 1 + uint8_t new_intattr = (old_intattr & (~0x2)); + + eclic_set_intattr(source,new_intattr); +} + +void eclic_set_posedge_trig(uint32_t source) { + //read the current attr + uint8_t old_intattr = eclic_get_intattr(source); + // Keep other bits unchanged and only set the bit 1 + uint8_t new_intattr = (old_intattr | 0x2); + // Keep other bits unchanged and only clear the bit 2 + new_intattr = (old_intattr & (~0x4)); + + eclic_set_intattr(source,new_intattr); +} + +void eclic_set_negedge_trig(uint32_t source) { + //read the current attr + uint8_t old_intattr = eclic_get_intattr(source); + // Keep other bits unchanged and only set the bit 1 + uint8_t new_intattr = (old_intattr | 0x2); + // Keep other bits unchanged and only set the bit 2 + new_intattr = (old_intattr | 0x4); + + eclic_set_intattr(source,new_intattr); +} + +//void wfe() { +// core_wfe(); +//} + + + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h new file mode 100644 index 00000000..6531d0b9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h @@ -0,0 +1,109 @@ +// See LICENSE file for licence details + +#ifndef N200_FUNC_H +#define N200_FUNC_H + + +#include +#include "n200_timer.h" +#include "n200_eclic.h" + +#define ECLIC_GROUP_LEVEL0_PRIO4 0 +#define ECLIC_GROUP_LEVEL1_PRIO3 1 +#define ECLIC_GROUP_LEVEL2_PRIO2 2 +#define ECLIC_GROUP_LEVEL3_PRIO1 3 +#define ECLIC_GROUP_LEVEL4_PRIO0 4 + +void pmp_open_all_space(); + +void switch_m2u_mode(); + +uint32_t get_mtime_freq(); + +uint32_t mtime_lo(void); + +uint32_t mtime_hi(void); + +uint64_t get_mtime_value(); + +uint64_t get_instret_value(); + +uint64_t get_cycle_value(); + +uint32_t get_cpu_freq(); + +uint32_t __attribute__((noinline)) measure_cpu_freq(size_t n); + + +/////////////////////////////////////////////////////////////////// +/////// ECLIC relevant functions +/////// +void eclic_init ( uint32_t num_irq ); +uint64_t get_timer_value(); +void eclic_enable_interrupt (uint32_t source); +void eclic_disable_interrupt (uint32_t source); + +void eclic_set_pending(uint32_t source); +void eclic_clear_pending(uint32_t source); + +void eclic_set_intctrl (uint32_t source, uint8_t intctrl); +uint8_t eclic_get_intctrl (uint32_t source); + +void eclic_set_intattr (uint32_t source, uint8_t intattr); +uint8_t eclic_get_intattr (uint32_t source); + +void eclic_set_cliccfg (uint8_t cliccfg); +uint8_t eclic_get_cliccfg (); + +void eclic_set_mth (uint8_t mth); +uint8_t eclic_get_mth(); + +//sets nlbits +void eclic_set_nlbits(uint8_t nlbits); + + +//get nlbits +uint8_t eclic_get_nlbits(); + +void eclic_set_irq_lvl(uint32_t source, uint8_t lvl); +uint8_t eclic_get_irq_lvl(uint32_t source); + +void eclic_set_irq_lvl_abs(uint32_t source, uint8_t lvl_abs); +uint8_t eclic_get_irq_lvl_abs(uint32_t source); + +uint8_t eclic_set_irq_priority(uint32_t source, uint8_t priority); +uint8_t eclic_get_irq_priority(uint32_t source); + +void eclic_mode_enable(); + +void eclic_set_vmode(uint32_t source); +void eclic_set_nonvmode(uint32_t source); + +void eclic_set_level_trig(uint32_t source); +void eclic_set_posedge_trig(uint32_t source); +void eclic_set_negedge_trig(uint32_t source); + + +///** \brief Wait For Interrupt +// +// Wait For Interrupt is a hint instruction that suspends execution +// until one of a number of events occurs. +// */ +__attribute__( ( always_inline ) ) static inline void __WFI(void) { + __asm volatile ("wfi"); +} +// +// +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) static inline void __WFE(void) { + __asm volatile ("csrs 0x810, 0x1"); + __asm volatile ("wfi"); + __asm volatile ("csrc 0x810, 0x1"); +} + + +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_timer.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_timer.h new file mode 100644 index 00000000..75ef7ca1 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_timer.h @@ -0,0 +1,18 @@ +// See LICENSE file for licence details + +#ifndef N200_TIMER_H +#define N200_TIMER_H + +#define TIMER_MSIP 0xFFC +#define TIMER_MSIP_size 0x4 +#define TIMER_MTIMECMP 0x8 +#define TIMER_MTIMECMP_size 0x8 +#define TIMER_MTIME 0x0 +#define TIMER_MTIME_size 0x8 + +#define TIMER_CTRL_ADDR 0xd1000000 +#define TIMER_REG(offset) _REG32(TIMER_CTRL_ADDR, offset) +#define TIMER_FREQ ((uint32_t)SystemCoreClock/4) //units HZ + +#endif + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_bits.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_bits.h new file mode 100644 index 00000000..bfe656fe --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_bits.h @@ -0,0 +1,36 @@ +// See LICENSE for license details. +#ifndef _RISCV_BITS_H +#define _RISCV_BITS_H + +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) + +#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) +#define ROUNDDOWN(a, b) ((a)/(b)*(b)) + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) + +#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) +#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) + +#define STR(x) XSTR(x) +#define XSTR(x) #x + +#if __riscv_xlen == 64 +# define SLL32 sllw +# define STORE sd +# define LOAD ld +# define LWU lwu +# define LOG_REGBYTES 3 +#else +# define SLL32 sll +# define STORE sw +# define LOAD lw +# define LWU lw +# define LOG_REGBYTES 2 +#endif +#define REGBYTES (1 << LOG_REGBYTES) + +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_const.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_const.h new file mode 100644 index 00000000..d5dec8ac --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_const.h @@ -0,0 +1,18 @@ +// See LICENSE for license details. +/* Derived from */ + +#ifndef _RISCV_CONST_H +#define _RISCV_CONST_H + +#ifdef __ASSEMBLER__ +#define _AC(X,Y) X +#define _AT(T,X) X +#else +#define _AC(X,Y) (X##Y) +#define _AT(T,X) ((T)(X)) +#endif /* !__ASSEMBLER__*/ + +#define _BITUL(x) (_AC(1,UL) << (x)) +#define _BITULL(x) (_AC(1,ULL) << (x)) + +#endif /* _NUCLEI_CONST_H */ diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_encoding.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_encoding.h new file mode 100644 index 00000000..2d995836 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/riscv_encoding.h @@ -0,0 +1,1369 @@ +// See LICENSE for license details. + +#ifndef RISCV_CSR_ENCODING_H +#define RISCV_CSR_ENCODING_H + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_PUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_VM 0x1F000000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS64_SD 0x8000000000000000 + + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_PUM 0x00040000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define MIE_SSIE MIP_SSIP +#define MIE_HSIE MIP_HSIP +#define MIE_MSIE MIP_MSIP +#define MIE_STIE MIP_STIP +#define MIE_HTIE MIP_HTIP +#define MIE_MTIE MIP_MTIP +#define MIE_SEIE MIP_SEIP +#define MIE_HEIE MIP_HEIP +#define MIE_MEIE MIP_MEIP + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define VM_MBARE 0 +#define VM_MBB 1 +#define VM_MBBID 2 +#define VM_SV32 8 +#define VM_SV39 9 +#define VM_SV48 10 + +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +#define DEFAULT_RSTVEC 0x00001000 +#define DEFAULT_NMIVEC 0x00001004 +#define DEFAULT_MTVEC 0x00001010 +#define CONFIG_STRING_ADDR 0x0000100C +#define EXT_IO_BASE 0x40000000 +#define DRAM_BASE 0x80000000 + +// page table entry (PTE) fields +#define PTE_V 0x001 // Valid +#define PTE_R 0x002 // Read +#define PTE_W 0x004 // Write +#define PTE_X 0x008 // Execute +#define PTE_U 0x010 // User +#define PTE_G 0x020 // Global +#define PTE_A 0x040 // Accessed +#define PTE_D 0x080 // Dirty +#define PTE_SOFT 0x300 // Reserved for Software + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#ifdef __riscv + +#ifdef __riscv64 +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD +# define RISCV_PGLEVEL_BITS 9 +#else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD +# define RISCV_PGLEVEL_BITS 10 +#endif +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#ifndef __ASSEMBLER__ + +#ifdef __GNUC__ + +#define read_fpu(reg) ({ unsigned long __tmp; \ + asm volatile ("fmv.x.w %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_fpu(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("fmv.w.x " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("fmv.w.x " #reg ", %0" :: "r"(val)); }) + + +#define read_csr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define write_csr(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define swap_csr(reg, val) ({ unsigned long __tmp; \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ + else \ + asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ + __tmp; }) + +#define set_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define clear_csr(reg, bit) ({ unsigned long __tmp; \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ + else \ + asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ + __tmp; }) + +#define rdtime() read_csr(time) +#define rdcycle() read_csr(cycle) +#define rdinstret() read_csr(instret) + + + + + + +#endif + +#endif + +#endif + +#endif +/* Automatically generated by parse-opcodes */ +#ifndef RISCV_ENCODING_H +#define RISCV_ENCODING_H +#define MATCH_BEQ 0x63 +#define MASK_BEQ 0x707f +#define MATCH_BNE 0x1063 +#define MASK_BNE 0x707f +#define MATCH_BLT 0x4063 +#define MASK_BLT 0x707f +#define MATCH_BGE 0x5063 +#define MASK_BGE 0x707f +#define MATCH_BLTU 0x6063 +#define MASK_BLTU 0x707f +#define MATCH_BGEU 0x7063 +#define MASK_BGEU 0x707f +#define MATCH_JALR 0x67 +#define MASK_JALR 0x707f +#define MATCH_JAL 0x6f +#define MASK_JAL 0x7f +#define MATCH_LUI 0x37 +#define MASK_LUI 0x7f +#define MATCH_AUIPC 0x17 +#define MASK_AUIPC 0x7f +#define MATCH_ADDI 0x13 +#define MASK_ADDI 0x707f +#define MATCH_SLLI 0x1013 +#define MASK_SLLI 0xfc00707f +#define MATCH_SLTI 0x2013 +#define MASK_SLTI 0x707f +#define MATCH_SLTIU 0x3013 +#define MASK_SLTIU 0x707f +#define MATCH_XORI 0x4013 +#define MASK_XORI 0x707f +#define MATCH_SRLI 0x5013 +#define MASK_SRLI 0xfc00707f +#define MATCH_SRAI 0x40005013 +#define MASK_SRAI 0xfc00707f +#define MATCH_ORI 0x6013 +#define MASK_ORI 0x707f +#define MATCH_ANDI 0x7013 +#define MASK_ANDI 0x707f +#define MATCH_ADD 0x33 +#define MASK_ADD 0xfe00707f +#define MATCH_SUB 0x40000033 +#define MASK_SUB 0xfe00707f +#define MATCH_SLL 0x1033 +#define MASK_SLL 0xfe00707f +#define MATCH_SLT 0x2033 +#define MASK_SLT 0xfe00707f +#define MATCH_SLTU 0x3033 +#define MASK_SLTU 0xfe00707f +#define MATCH_XOR 0x4033 +#define MASK_XOR 0xfe00707f +#define MATCH_SRL 0x5033 +#define MASK_SRL 0xfe00707f +#define MATCH_SRA 0x40005033 +#define MASK_SRA 0xfe00707f +#define MATCH_OR 0x6033 +#define MASK_OR 0xfe00707f +#define MATCH_AND 0x7033 +#define MASK_AND 0xfe00707f +#define MATCH_ADDIW 0x1b +#define MASK_ADDIW 0x707f +#define MATCH_SLLIW 0x101b +#define MASK_SLLIW 0xfe00707f +#define MATCH_SRLIW 0x501b +#define MASK_SRLIW 0xfe00707f +#define MATCH_SRAIW 0x4000501b +#define MASK_SRAIW 0xfe00707f +#define MATCH_ADDW 0x3b +#define MASK_ADDW 0xfe00707f +#define MATCH_SUBW 0x4000003b +#define MASK_SUBW 0xfe00707f +#define MATCH_SLLW 0x103b +#define MASK_SLLW 0xfe00707f +#define MATCH_SRLW 0x503b +#define MASK_SRLW 0xfe00707f +#define MATCH_SRAW 0x4000503b +#define MASK_SRAW 0xfe00707f +#define MATCH_LB 0x3 +#define MASK_LB 0x707f +#define MATCH_LH 0x1003 +#define MASK_LH 0x707f +#define MATCH_LW 0x2003 +#define MASK_LW 0x707f +#define MATCH_LD 0x3003 +#define MASK_LD 0x707f +#define MATCH_LBU 0x4003 +#define MASK_LBU 0x707f +#define MATCH_LHU 0x5003 +#define MASK_LHU 0x707f +#define MATCH_LWU 0x6003 +#define MASK_LWU 0x707f +#define MATCH_SB 0x23 +#define MASK_SB 0x707f +#define MATCH_SH 0x1023 +#define MASK_SH 0x707f +#define MATCH_SW 0x2023 +#define MASK_SW 0x707f +#define MATCH_SD 0x3023 +#define MASK_SD 0x707f +#define MATCH_FENCE 0xf +#define MASK_FENCE 0x707f +#define MATCH_FENCE_I 0x100f +#define MASK_FENCE_I 0x707f +#define MATCH_MUL 0x2000033 +#define MASK_MUL 0xfe00707f +#define MATCH_MULH 0x2001033 +#define MASK_MULH 0xfe00707f +#define MATCH_MULHSU 0x2002033 +#define MASK_MULHSU 0xfe00707f +#define MATCH_MULHU 0x2003033 +#define MASK_MULHU 0xfe00707f +#define MATCH_DIV 0x2004033 +#define MASK_DIV 0xfe00707f +#define MATCH_DIVU 0x2005033 +#define MASK_DIVU 0xfe00707f +#define MATCH_REM 0x2006033 +#define MASK_REM 0xfe00707f +#define MATCH_REMU 0x2007033 +#define MASK_REMU 0xfe00707f +#define MATCH_MULW 0x200003b +#define MASK_MULW 0xfe00707f +#define MATCH_DIVW 0x200403b +#define MASK_DIVW 0xfe00707f +#define MATCH_DIVUW 0x200503b +#define MASK_DIVUW 0xfe00707f +#define MATCH_REMW 0x200603b +#define MASK_REMW 0xfe00707f +#define MATCH_REMUW 0x200703b +#define MASK_REMUW 0xfe00707f +#define MATCH_AMOADD_W 0x202f +#define MASK_AMOADD_W 0xf800707f +#define MATCH_AMOXOR_W 0x2000202f +#define MASK_AMOXOR_W 0xf800707f +#define MATCH_AMOOR_W 0x4000202f +#define MASK_AMOOR_W 0xf800707f +#define MATCH_AMOAND_W 0x6000202f +#define MASK_AMOAND_W 0xf800707f +#define MATCH_AMOMIN_W 0x8000202f +#define MASK_AMOMIN_W 0xf800707f +#define MATCH_AMOMAX_W 0xa000202f +#define MASK_AMOMAX_W 0xf800707f +#define MATCH_AMOMINU_W 0xc000202f +#define MASK_AMOMINU_W 0xf800707f +#define MATCH_AMOMAXU_W 0xe000202f +#define MASK_AMOMAXU_W 0xf800707f +#define MATCH_AMOSWAP_W 0x800202f +#define MASK_AMOSWAP_W 0xf800707f +#define MATCH_LR_W 0x1000202f +#define MASK_LR_W 0xf9f0707f +#define MATCH_SC_W 0x1800202f +#define MASK_SC_W 0xf800707f +#define MATCH_AMOADD_D 0x302f +#define MASK_AMOADD_D 0xf800707f +#define MATCH_AMOXOR_D 0x2000302f +#define MASK_AMOXOR_D 0xf800707f +#define MATCH_AMOOR_D 0x4000302f +#define MASK_AMOOR_D 0xf800707f +#define MATCH_AMOAND_D 0x6000302f +#define MASK_AMOAND_D 0xf800707f +#define MATCH_AMOMIN_D 0x8000302f +#define MASK_AMOMIN_D 0xf800707f +#define MATCH_AMOMAX_D 0xa000302f +#define MASK_AMOMAX_D 0xf800707f +#define MATCH_AMOMINU_D 0xc000302f +#define MASK_AMOMINU_D 0xf800707f +#define MATCH_AMOMAXU_D 0xe000302f +#define MASK_AMOMAXU_D 0xf800707f +#define MATCH_AMOSWAP_D 0x800302f +#define MASK_AMOSWAP_D 0xf800707f +#define MATCH_LR_D 0x1000302f +#define MASK_LR_D 0xf9f0707f +#define MATCH_SC_D 0x1800302f +#define MASK_SC_D 0xf800707f +#define MATCH_ECALL 0x73 +#define MASK_ECALL 0xffffffff +#define MATCH_EBREAK 0x100073 +#define MASK_EBREAK 0xffffffff +#define MATCH_URET 0x200073 +#define MASK_URET 0xffffffff +#define MATCH_SRET 0x10200073 +#define MASK_SRET 0xffffffff +#define MATCH_HRET 0x20200073 +#define MASK_HRET 0xffffffff +#define MATCH_MRET 0x30200073 +#define MASK_MRET 0xffffffff +#define MATCH_DRET 0x7b200073 +#define MASK_DRET 0xffffffff +#define MATCH_SFENCE_VM 0x10400073 +#define MASK_SFENCE_VM 0xfff07fff +#define MATCH_WFI 0x10500073 +#define MASK_WFI 0xffffffff +#define MATCH_CSRRW 0x1073 +#define MASK_CSRRW 0x707f +#define MATCH_CSRRS 0x2073 +#define MASK_CSRRS 0x707f +#define MATCH_CSRRC 0x3073 +#define MASK_CSRRC 0x707f +#define MATCH_CSRRWI 0x5073 +#define MASK_CSRRWI 0x707f +#define MATCH_CSRRSI 0x6073 +#define MASK_CSRRSI 0x707f +#define MATCH_CSRRCI 0x7073 +#define MASK_CSRRCI 0x707f +#define MATCH_FADD_S 0x53 +#define MASK_FADD_S 0xfe00007f +#define MATCH_FSUB_S 0x8000053 +#define MASK_FSUB_S 0xfe00007f +#define MATCH_FMUL_S 0x10000053 +#define MASK_FMUL_S 0xfe00007f +#define MATCH_FDIV_S 0x18000053 +#define MASK_FDIV_S 0xfe00007f +#define MATCH_FSGNJ_S 0x20000053 +#define MASK_FSGNJ_S 0xfe00707f +#define MATCH_FSGNJN_S 0x20001053 +#define MASK_FSGNJN_S 0xfe00707f +#define MATCH_FSGNJX_S 0x20002053 +#define MASK_FSGNJX_S 0xfe00707f +#define MATCH_FMIN_S 0x28000053 +#define MASK_FMIN_S 0xfe00707f +#define MATCH_FMAX_S 0x28001053 +#define MASK_FMAX_S 0xfe00707f +#define MATCH_FSQRT_S 0x58000053 +#define MASK_FSQRT_S 0xfff0007f +#define MATCH_FADD_D 0x2000053 +#define MASK_FADD_D 0xfe00007f +#define MATCH_FSUB_D 0xa000053 +#define MASK_FSUB_D 0xfe00007f +#define MATCH_FMUL_D 0x12000053 +#define MASK_FMUL_D 0xfe00007f +#define MATCH_FDIV_D 0x1a000053 +#define MASK_FDIV_D 0xfe00007f +#define MATCH_FSGNJ_D 0x22000053 +#define MASK_FSGNJ_D 0xfe00707f +#define MATCH_FSGNJN_D 0x22001053 +#define MASK_FSGNJN_D 0xfe00707f +#define MATCH_FSGNJX_D 0x22002053 +#define MASK_FSGNJX_D 0xfe00707f +#define MATCH_FMIN_D 0x2a000053 +#define MASK_FMIN_D 0xfe00707f +#define MATCH_FMAX_D 0x2a001053 +#define MASK_FMAX_D 0xfe00707f +#define MATCH_FCVT_S_D 0x40100053 +#define MASK_FCVT_S_D 0xfff0007f +#define MATCH_FCVT_D_S 0x42000053 +#define MASK_FCVT_D_S 0xfff0007f +#define MATCH_FSQRT_D 0x5a000053 +#define MASK_FSQRT_D 0xfff0007f +#define MATCH_FLE_S 0xa0000053 +#define MASK_FLE_S 0xfe00707f +#define MATCH_FLT_S 0xa0001053 +#define MASK_FLT_S 0xfe00707f +#define MATCH_FEQ_S 0xa0002053 +#define MASK_FEQ_S 0xfe00707f +#define MATCH_FLE_D 0xa2000053 +#define MASK_FLE_D 0xfe00707f +#define MATCH_FLT_D 0xa2001053 +#define MASK_FLT_D 0xfe00707f +#define MATCH_FEQ_D 0xa2002053 +#define MASK_FEQ_D 0xfe00707f +#define MATCH_FCVT_W_S 0xc0000053 +#define MASK_FCVT_W_S 0xfff0007f +#define MATCH_FCVT_WU_S 0xc0100053 +#define MASK_FCVT_WU_S 0xfff0007f +#define MATCH_FCVT_L_S 0xc0200053 +#define MASK_FCVT_L_S 0xfff0007f +#define MATCH_FCVT_LU_S 0xc0300053 +#define MASK_FCVT_LU_S 0xfff0007f +#define MATCH_FMV_X_S 0xe0000053 +#define MASK_FMV_X_S 0xfff0707f +#define MATCH_FCLASS_S 0xe0001053 +#define MASK_FCLASS_S 0xfff0707f +#define MATCH_FCVT_W_D 0xc2000053 +#define MASK_FCVT_W_D 0xfff0007f +#define MATCH_FCVT_WU_D 0xc2100053 +#define MASK_FCVT_WU_D 0xfff0007f +#define MATCH_FCVT_L_D 0xc2200053 +#define MASK_FCVT_L_D 0xfff0007f +#define MATCH_FCVT_LU_D 0xc2300053 +#define MASK_FCVT_LU_D 0xfff0007f +#define MATCH_FMV_X_D 0xe2000053 +#define MASK_FMV_X_D 0xfff0707f +#define MATCH_FCLASS_D 0xe2001053 +#define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCVT_S_W 0xd0000053 +#define MASK_FCVT_S_W 0xfff0007f +#define MATCH_FCVT_S_WU 0xd0100053 +#define MASK_FCVT_S_WU 0xfff0007f +#define MATCH_FCVT_S_L 0xd0200053 +#define MASK_FCVT_S_L 0xfff0007f +#define MATCH_FCVT_S_LU 0xd0300053 +#define MASK_FCVT_S_LU 0xfff0007f +#define MATCH_FMV_S_X 0xf0000053 +#define MASK_FMV_S_X 0xfff0707f +#define MATCH_FCVT_D_W 0xd2000053 +#define MASK_FCVT_D_W 0xfff0007f +#define MATCH_FCVT_D_WU 0xd2100053 +#define MASK_FCVT_D_WU 0xfff0007f +#define MATCH_FCVT_D_L 0xd2200053 +#define MASK_FCVT_D_L 0xfff0007f +#define MATCH_FCVT_D_LU 0xd2300053 +#define MASK_FCVT_D_LU 0xfff0007f +#define MATCH_FMV_D_X 0xf2000053 +#define MASK_FMV_D_X 0xfff0707f +#define MATCH_FLW 0x2007 +#define MASK_FLW 0x707f +#define MATCH_FLD 0x3007 +#define MASK_FLD 0x707f +#define MATCH_FSW 0x2027 +#define MASK_FSW 0x707f +#define MATCH_FSD 0x3027 +#define MASK_FSD 0x707f +#define MATCH_FMADD_S 0x43 +#define MASK_FMADD_S 0x600007f +#define MATCH_FMSUB_S 0x47 +#define MASK_FMSUB_S 0x600007f +#define MATCH_FNMSUB_S 0x4b +#define MASK_FNMSUB_S 0x600007f +#define MATCH_FNMADD_S 0x4f +#define MASK_FNMADD_S 0x600007f +#define MATCH_FMADD_D 0x2000043 +#define MASK_FMADD_D 0x600007f +#define MATCH_FMSUB_D 0x2000047 +#define MASK_FMSUB_D 0x600007f +#define MATCH_FNMSUB_D 0x200004b +#define MASK_FNMSUB_D 0x600007f +#define MATCH_FNMADD_D 0x200004f +#define MASK_FNMADD_D 0x600007f +#define MATCH_C_NOP 0x1 +#define MASK_C_NOP 0xffff +#define MATCH_C_ADDI16SP 0x6101 +#define MASK_C_ADDI16SP 0xef83 +#define MATCH_C_JR 0x8002 +#define MASK_C_JR 0xf07f +#define MATCH_C_JALR 0x9002 +#define MASK_C_JALR 0xf07f +#define MATCH_C_EBREAK 0x9002 +#define MASK_C_EBREAK 0xffff +#define MATCH_C_LD 0x6000 +#define MASK_C_LD 0xe003 +#define MATCH_C_SD 0xe000 +#define MASK_C_SD 0xe003 +#define MATCH_C_ADDIW 0x2001 +#define MASK_C_ADDIW 0xe003 +#define MATCH_C_LDSP 0x6002 +#define MASK_C_LDSP 0xe003 +#define MATCH_C_SDSP 0xe002 +#define MASK_C_SDSP 0xe003 +#define MATCH_C_ADDI4SPN 0x0 +#define MASK_C_ADDI4SPN 0xe003 +#define MATCH_C_FLD 0x2000 +#define MASK_C_FLD 0xe003 +#define MATCH_C_LW 0x4000 +#define MASK_C_LW 0xe003 +#define MATCH_C_FLW 0x6000 +#define MASK_C_FLW 0xe003 +#define MATCH_C_FSD 0xa000 +#define MASK_C_FSD 0xe003 +#define MATCH_C_SW 0xc000 +#define MASK_C_SW 0xe003 +#define MATCH_C_FSW 0xe000 +#define MASK_C_FSW 0xe003 +#define MATCH_C_ADDI 0x1 +#define MASK_C_ADDI 0xe003 +#define MATCH_C_JAL 0x2001 +#define MASK_C_JAL 0xe003 +#define MATCH_C_LI 0x4001 +#define MASK_C_LI 0xe003 +#define MATCH_C_LUI 0x6001 +#define MASK_C_LUI 0xe003 +#define MATCH_C_SRLI 0x8001 +#define MASK_C_SRLI 0xec03 +#define MATCH_C_SRAI 0x8401 +#define MASK_C_SRAI 0xec03 +#define MATCH_C_ANDI 0x8801 +#define MASK_C_ANDI 0xec03 +#define MATCH_C_SUB 0x8c01 +#define MASK_C_SUB 0xfc63 +#define MATCH_C_XOR 0x8c21 +#define MASK_C_XOR 0xfc63 +#define MATCH_C_OR 0x8c41 +#define MASK_C_OR 0xfc63 +#define MATCH_C_AND 0x8c61 +#define MASK_C_AND 0xfc63 +#define MATCH_C_SUBW 0x9c01 +#define MASK_C_SUBW 0xfc63 +#define MATCH_C_ADDW 0x9c21 +#define MASK_C_ADDW 0xfc63 +#define MATCH_C_J 0xa001 +#define MASK_C_J 0xe003 +#define MATCH_C_BEQZ 0xc001 +#define MASK_C_BEQZ 0xe003 +#define MATCH_C_BNEZ 0xe001 +#define MASK_C_BNEZ 0xe003 +#define MATCH_C_SLLI 0x2 +#define MASK_C_SLLI 0xe003 +#define MATCH_C_FLDSP 0x2002 +#define MASK_C_FLDSP 0xe003 +#define MATCH_C_LWSP 0x4002 +#define MASK_C_LWSP 0xe003 +#define MATCH_C_FLWSP 0x6002 +#define MASK_C_FLWSP 0xe003 +#define MATCH_C_MV 0x8002 +#define MASK_C_MV 0xf003 +#define MATCH_C_ADD 0x9002 +#define MASK_C_ADD 0xf003 +#define MATCH_C_FSDSP 0xa002 +#define MASK_C_FSDSP 0xe003 +#define MATCH_C_SWSP 0xc002 +#define MASK_C_SWSP 0xe003 +#define MATCH_C_FSWSP 0xe002 +#define MASK_C_FSWSP 0xe003 +#define MATCH_CUSTOM0 0xb +#define MASK_CUSTOM0 0x707f +#define MATCH_CUSTOM0_RS1 0x200b +#define MASK_CUSTOM0_RS1 0x707f +#define MATCH_CUSTOM0_RS1_RS2 0x300b +#define MASK_CUSTOM0_RS1_RS2 0x707f +#define MATCH_CUSTOM0_RD 0x400b +#define MASK_CUSTOM0_RD 0x707f +#define MATCH_CUSTOM0_RD_RS1 0x600b +#define MASK_CUSTOM0_RD_RS1 0x707f +#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b +#define MASK_CUSTOM0_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM1 0x2b +#define MASK_CUSTOM1 0x707f +#define MATCH_CUSTOM1_RS1 0x202b +#define MASK_CUSTOM1_RS1 0x707f +#define MATCH_CUSTOM1_RS1_RS2 0x302b +#define MASK_CUSTOM1_RS1_RS2 0x707f +#define MATCH_CUSTOM1_RD 0x402b +#define MASK_CUSTOM1_RD 0x707f +#define MATCH_CUSTOM1_RD_RS1 0x602b +#define MASK_CUSTOM1_RD_RS1 0x707f +#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b +#define MASK_CUSTOM1_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM2 0x5b +#define MASK_CUSTOM2 0x707f +#define MATCH_CUSTOM2_RS1 0x205b +#define MASK_CUSTOM2_RS1 0x707f +#define MATCH_CUSTOM2_RS1_RS2 0x305b +#define MASK_CUSTOM2_RS1_RS2 0x707f +#define MATCH_CUSTOM2_RD 0x405b +#define MASK_CUSTOM2_RD 0x707f +#define MATCH_CUSTOM2_RD_RS1 0x605b +#define MASK_CUSTOM2_RD_RS1 0x707f +#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b +#define MASK_CUSTOM2_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM3 0x7b +#define MASK_CUSTOM3 0x707f +#define MATCH_CUSTOM3_RS1 0x207b +#define MASK_CUSTOM3_RS1 0x707f +#define MATCH_CUSTOM3_RS1_RS2 0x307b +#define MASK_CUSTOM3_RS1_RS2 0x707f +#define MATCH_CUSTOM3_RD 0x407b +#define MASK_CUSTOM3_RD 0x707f +#define MATCH_CUSTOM3_RD_RS1 0x607b +#define MASK_CUSTOM3_RD_RS1 0x707f +#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b +#define MASK_CUSTOM3_RD_RS1_RS2 0x707f +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_SBADADDR 0x143 +#define CSR_SIP 0x144 +#define CSR_SPTBR 0x180 +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MBADADDR 0x343 +#define CSR_MIP 0x344 +#define CSR_MSCRATCHCSWL 0x349 +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH 0x7b2 +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MUCOUNTEREN 0x320 +#define CSR_MSCOUNTEREN 0x321 +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f + + +#define CSR_MTVT 0x307 +#define CSR_MNXTI 0x345 + +#define CSR_MCOUNTINHIBIT 0x320 + +#define CSR_MNVEC 0x7C3 + +#define CSR_MTVT2 0x7EC +#define CSR_JALMNXTI 0x7ED +#define CSR_PUSHMCAUSE 0x7EE +#define CSR_PUSHMEPC 0x7EF +#define CSR_PUSHMSUBM 0x7EB + +#define CSR_WFE 0x810 +#define CSR_SLEEPVALUE 0x811 +#define CSR_TXEVT 0x812 + +#define CSR_MMISC_CTL 0x7d0 +#define CSR_MSUBM 0x7c4 + + +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FAULT_FETCH 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_FAULT_LOAD 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_FAULT_STORE 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_HYPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#endif +#ifdef DECLARE_INSN +DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) +DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) +DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) +DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) +DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) +DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) +DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) +DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) +DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) +DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) +DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) +DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) +DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) +DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) +DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) +DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) +DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) +DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) +DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) +DECLARE_INSN(add, MATCH_ADD, MASK_ADD) +DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) +DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) +DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) +DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) +DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) +DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) +DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) +DECLARE_INSN(or, MATCH_OR, MASK_OR) +DECLARE_INSN(and, MATCH_AND, MASK_AND) +DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) +DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) +DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) +DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) +DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) +DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) +DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) +DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) +DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) +DECLARE_INSN(lb, MATCH_LB, MASK_LB) +DECLARE_INSN(lh, MATCH_LH, MASK_LH) +DECLARE_INSN(lw, MATCH_LW, MASK_LW) +DECLARE_INSN(ld, MATCH_LD, MASK_LD) +DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) +DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) +DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) +DECLARE_INSN(sb, MATCH_SB, MASK_SB) +DECLARE_INSN(sh, MATCH_SH, MASK_SH) +DECLARE_INSN(sw, MATCH_SW, MASK_SW) +DECLARE_INSN(sd, MATCH_SD, MASK_SD) +DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) +DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) +DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) +DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) +DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) +DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) +DECLARE_INSN(div, MATCH_DIV, MASK_DIV) +DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) +DECLARE_INSN(rem, MATCH_REM, MASK_REM) +DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) +DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) +DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) +DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) +DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) +DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) +DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) +DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) +DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) +DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) +DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) +DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) +DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) +DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) +DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) +DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) +DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) +DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) +DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) +DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) +DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) +DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) +DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) +DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) +DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) +DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) +DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) +DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) +DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) +DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) +DECLARE_INSN(uret, MATCH_URET, MASK_URET) +DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) +DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) +DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) +DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) +DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) +DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) +DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) +DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) +DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) +DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) +DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) +DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) +DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) +DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) +DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) +DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) +DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) +DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) +DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) +DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) +DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) +DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) +DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) +DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) +DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) +DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) +DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) +DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) +DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) +DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) +DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) +DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) +DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) +DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) +DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) +DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) +DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) +DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) +DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) +DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) +DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) +DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) +DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) +DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) +DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) +DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) +DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) +DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) +DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) +DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) +DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) +DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) +DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) +DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) +DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) +DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) +DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) +DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) +DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) +DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) +DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) +DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) +DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) +DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) +DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) +DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) +DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) +DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) +DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) +DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) +DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) +DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) +DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) +DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) +DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) +DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) +DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) +DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) +DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) +DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) +DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) +DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) +DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) +DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) +DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) +DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) +DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) +DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) +DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) +DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) +DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) +DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) +DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) +DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) +DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) +DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) +DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) +DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) +DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) +DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) +DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) +DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) +DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) +DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) +DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) +DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) +DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) +DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) +DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) +DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) +DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) +DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) +DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) +DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) +DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, +MASK_CUSTOM0_RD_RS1_RS2) +DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) +DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) +DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) +DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) +DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) +DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, +MASK_CUSTOM1_RD_RS1_RS2) +DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) +DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) +DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) +DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) +DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) +DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, +MASK_CUSTOM2_RD_RS1_RS2) +DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) +DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) +DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) +DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) +DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) +DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, +MASK_CUSTOM3_RD_RS1_RS2) +#endif +#ifdef DECLARE_CSR +DECLARE_CSR(fflags, CSR_FFLAGS) +DECLARE_CSR(frm, CSR_FRM) +DECLARE_CSR(fcsr, CSR_FCSR) +DECLARE_CSR(cycle, CSR_CYCLE) +DECLARE_CSR(time, CSR_TIME) +DECLARE_CSR(instret, CSR_INSTRET) +DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) +DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) +DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) +DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) +DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) +DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) +DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) +DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) +DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) +DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) +DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) +DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) +DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) +DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) +DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) +DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) +DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) +DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) +DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) +DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) +DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) +DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) +DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) +DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) +DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) +DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) +DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) +DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) +DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) +DECLARE_CSR(sstatus, CSR_SSTATUS) +DECLARE_CSR(sie, CSR_SIE) +DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(sscratch, CSR_SSCRATCH) +DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(sbadaddr, CSR_SBADADDR) +DECLARE_CSR(sip, CSR_SIP) +DECLARE_CSR(sptbr, CSR_SPTBR) +DECLARE_CSR(mstatus, CSR_MSTATUS) +DECLARE_CSR(misa, CSR_MISA) +DECLARE_CSR(medeleg, CSR_MEDELEG) +DECLARE_CSR(mideleg, CSR_MIDELEG) +DECLARE_CSR(mie, CSR_MIE) +DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mscratch, CSR_MSCRATCH) +DECLARE_CSR(mepc, CSR_MEPC) +DECLARE_CSR(mcause, CSR_MCAUSE) +DECLARE_CSR(mbadaddr, CSR_MBADADDR) +DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(tselect, CSR_TSELECT) +DECLARE_CSR(tdata1, CSR_TDATA1) +DECLARE_CSR(tdata2, CSR_TDATA2) +DECLARE_CSR(tdata3, CSR_TDATA3) +DECLARE_CSR(dcsr, CSR_DCSR) +DECLARE_CSR(dpc, CSR_DPC) +DECLARE_CSR(dscratch, CSR_DSCRATCH) +DECLARE_CSR(mcycle, CSR_MCYCLE) +DECLARE_CSR(minstret, CSR_MINSTRET) +DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) +DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) +DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) +DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) +DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) +DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) +DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) +DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) +DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) +DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) +DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) +DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) +DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) +DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) +DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) +DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) +DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) +DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) +DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) +DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) +DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) +DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) +DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) +DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) +DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) +DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) +DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) +DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) +DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) +DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) +DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) +DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) +DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) +DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) +DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) +DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) +DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) +DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) +DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) +DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) +DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) +DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) +DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) +DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) +DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) +DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) +DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) +DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) +DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) +DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) +DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) +DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) +DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) +DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) +DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) +DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) +DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) +DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) +DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) +DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) +DECLARE_CSR(mvendorid, CSR_MVENDORID) +DECLARE_CSR(marchid, CSR_MARCHID) +DECLARE_CSR(mimpid, CSR_MIMPID) +DECLARE_CSR(mhartid, CSR_MHARTID) +DECLARE_CSR(cycleh, CSR_CYCLEH) +DECLARE_CSR(timeh, CSR_TIMEH) +DECLARE_CSR(instreth, CSR_INSTRETH) +DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) +DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) +DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) +DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) +DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) +DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) +DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) +DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) +DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) +DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) +DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) +DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) +DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) +DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) +DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) +DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) +DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) +DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) +DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) +DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) +DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) +DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) +DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) +DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) +DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) +DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) +DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) +DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) +DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) +DECLARE_CSR(mcycleh, CSR_MCYCLEH) +DECLARE_CSR(minstreth, CSR_MINSTRETH) +DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) +DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) +DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) +DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) +DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) +DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) +DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) +DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) +DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) +DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) +DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) +DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) +DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) +DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) +DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) +DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) +DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) +DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) +DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) +DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) +DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) +DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) +DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) +DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) +DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) +DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) +DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) +DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) +DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) +#endif +#ifdef DECLARE_CAUSE +DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) +DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) +DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) +DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) +DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) +DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) +DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) +DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) +DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) +DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) +DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) +DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +#endif + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S new file mode 100644 index 00000000..0efa55b1 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S @@ -0,0 +1,289 @@ +// See LICENSE for license details. + +#include "riscv_encoding.h" + + .section .init + + .weak eclic_msip_handler //弱定义函数,这些在编译为bin后可以看到将全部为0 + .weak eclic_mtip_handler + .weak eclic_bwei_handler + .weak eclic_pmovi_handler + .weak WWDGT_IRQHandler + .weak LVD_IRQHandler + .weak TAMPER_IRQHandler + .weak RTC_IRQHandler + .weak FMC_IRQHandler + .weak RCU_IRQHandler + .weak EXTI0_IRQHandler + .weak EXTI1_IRQHandler + .weak EXTI2_IRQHandler + .weak EXTI3_IRQHandler + .weak EXTI4_IRQHandler + .weak DMA0_Channel0_IRQHandler + .weak DMA0_Channel1_IRQHandler + .weak DMA0_Channel2_IRQHandler + .weak DMA0_Channel3_IRQHandler + .weak DMA0_Channel4_IRQHandler + .weak DMA0_Channel5_IRQHandler + .weak DMA0_Channel6_IRQHandler + .weak ADC0_1_IRQHandler + .weak CAN0_TX_IRQHandler + .weak CAN0_RX0_IRQHandler + .weak CAN0_RX1_IRQHandler + .weak CAN0_EWMC_IRQHandler + .weak EXTI5_9_IRQHandler + .weak TIMER0_BRK_IRQHandler + .weak TIMER0_UP_IRQHandler + .weak TIMER0_TRG_CMT_IRQHandler + .weak TIMER0_Channel_IRQHandler + .weak TIMER1_IRQHandler + .weak TIMER2_IRQHandler + .weak TIMER3_IRQHandler + .weak I2C0_EV_IRQHandler + .weak I2C0_ER_IRQHandler + .weak I2C1_EV_IRQHandler + .weak I2C1_ER_IRQHandler + .weak SPI0_IRQHandler + .weak SPI1_IRQHandler + .weak USART0_IRQHandler + .weak USART1_IRQHandler + .weak USART2_IRQHandler + .weak EXTI10_15_IRQHandler + .weak RTC_Alarm_IRQHandler + .weak USBFS_WKUP_IRQHandler + .weak EXMC_IRQHandler + .weak TIMER4_IRQHandler + .weak SPI2_IRQHandler + .weak UART3_IRQHandler + .weak UART4_IRQHandler + .weak TIMER5_IRQHandler + .weak TIMER6_IRQHandler + .weak DMA1_Channel0_IRQHandler + .weak DMA1_Channel1_IRQHandler + .weak DMA1_Channel2_IRQHandler + .weak DMA1_Channel3_IRQHandler + .weak DMA1_Channel4_IRQHandler + .weak CAN1_TX_IRQHandler + .weak CAN1_RX0_IRQHandler + .weak CAN1_RX1_IRQHandler + .weak CAN1_EWMC_IRQHandler + .weak USBFS_IRQHandler + +vector_base: //中断向量表 + j _start //第一条指令即跳转到_start处开始执行 + .align 2 + .word 0 + .word 0 + .word eclic_msip_handler + .word 0 + .word 0 + .word 0 + .word eclic_mtip_handler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word eclic_bwei_handler + .word eclic_pmovi_handler + .word WWDGT_IRQHandler + .word LVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FMC_IRQHandler + .word RCU_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA0_Channel0_IRQHandler + .word DMA0_Channel1_IRQHandler + .word DMA0_Channel2_IRQHandler + .word DMA0_Channel3_IRQHandler + .word DMA0_Channel4_IRQHandler + .word DMA0_Channel5_IRQHandler + .word DMA0_Channel6_IRQHandler + .word ADC0_1_IRQHandler + .word CAN0_TX_IRQHandler + .word CAN0_RX0_IRQHandler + .word CAN0_RX1_IRQHandler + .word CAN0_EWMC_IRQHandler + .word EXTI5_9_IRQHandler + .word TIMER0_BRK_IRQHandler + .word TIMER0_UP_IRQHandler + .word TIMER0_TRG_CMT_IRQHandler + .word TIMER0_Channel_IRQHandler + .word TIMER1_IRQHandler + .word TIMER2_IRQHandler + .word TIMER3_IRQHandler + .word I2C0_EV_IRQHandler + .word I2C0_ER_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word SPI0_IRQHandler + .word SPI1_IRQHandler + .word USART0_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word EXTI10_15_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBFS_WKUP_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word EXMC_IRQHandler + .word 0 + .word TIMER4_IRQHandler + .word SPI2_IRQHandler + .word UART3_IRQHandler + .word UART4_IRQHandler + .word TIMER5_IRQHandler + .word TIMER6_IRQHandler + .word DMA1_Channel0_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word 0 + .word 0 + .word CAN1_TX_IRQHandler + .word CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_EWMC_IRQHandler + .word USBFS_IRQHandler + + .globl _start + .type _start,@function + +_start: + + csrc CSR_MSTATUS, MSTATUS_MIE //CSR_MSTATUS &= ~0x8 mstatus[3]:0屏蔽全部中断 1不屏蔽全部中断 (当然这里全部中断是除过不可屏蔽中断) + /* Jump to logical address first to ensure correct operation of RAM region */ + la a0, _start //a0 = _start + li a1, 1 //a1 = 1 + slli a1, a1, 29 //a1 = 0x20000000 raw起始地址 + bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 + srli a1, a1, 2 //a1 = 0x08000000 flash起始地址 + bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 + la a0, _start0800 //a0 = _start0800 + add a0, a0, a1 //a0 = a0+a1 + jr a0 //JUMP a0 + +_start0800: + + /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */ + li t0, 0x200 //t0 = 0x200 + csrs CSR_MMISC_CTL, t0 //mmisc_ctl |= 0x200 CSR_MMISC_CTL[9]:设置NMI的地址与mtvec相同且,mcause.EXCCODE = 0xfff + //cs开头的指令是特有的用来操作内核寄存器的的指令,内核寄存器是一组特有的12位地址 + + /* Intial the mtvt*/ + la t0, vector_base //t0 = vector_base 向量表地址 + csrw CSR_MTVT, t0 //mtvt = vector_base 中断向量表基地址 + + /* Intial the mtvt2 and enable it*/ + la t0, irq_entry //t0 = irq_entry irq_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S + csrw CSR_MTVT2, t0 //mtvt2 = irq_entry mtvt2[31:2]: 中断入口函数地址 + csrs CSR_MTVT2, 0x1 //mtvt2 |= 0x1 mtvt2[0]: 1配置mtvt2的配置有效,配0则为mtvec内地址 + + /* Intial the CSR MTVEC for the Trap ane NMI base addr*/ + la t0, trap_entry //t0 = trap_entry trap_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S + csrw CSR_MTVEC, t0 //mtvec = trap_entry mtvec[31:6]:异常入口地址 + // mtvec[5:0]:0B00011 -- ECLIC中断模式 其他:默认模式 + // 这里配置为默认模式 + // trap_entry基本上可以理解为arm里的hard/mem/use/svc等fault了, + // 这里在移植freertos时就使用了 ecall 进入trap_entry里 相当于arm里的PendSVC + + /* OS启动前配置中断栈为FHEAP的end地址 */ + la t0, ucHeap + csrw CSR_MSCRATCH, t0 + +#ifdef __riscv_flen //浮点宏 + /* Enable FPU */ + li t0, MSTATUS_FS //t0 = 0x6000 + csrs mstatus, t0 //mstatus |= 0x6000 mstatus[14:13]:非零值启用浮点单元,配置为1或2会在第一次使用浮点单元时变为3,这里直接配置为3 + csrw fcsr, x0 //fcsr = x0 = 0 ??这里x0是否指的是zero通用寄存器值? 这个寄存器0-4位是浮点异常状态标志,5-7位是浮点舍入模式配置 +#endif + +.option push +.option norelax + la gp, __global_pointer$ //__global_pointer$定义在link连接脚本内,指向所有.data段后偏移0x800的地址,0x800为2K,其值源于下文解释 + //gp 意为global pointer (全局指针)寄存器是一个解决方案, + //为了以进一步优化存储器访问单个4KB区域内。 + //链接器使用__global_pointer$符号定义来比较内存地址,如果在范围内, + //则它将绝对/相对pc寻址替换为gp相对寻址,从而使代码更有效。这个过程通过-Wl,--no-relax选项使用。 + //这里.option norelax起到-Wl,--no-relax作用,就不需要在编译选项添加了 + //上文参考自:https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register + //要让 relaxing 优化起作用,编译时要加入 -msmall-data-limit=n 参数,有了这个参数, + //编译器会把内存空间小于 n 字节的静态变量放入 .sdata 或者 .sdata.* 节, + //然后链接器将这部分静态变量集中在 __global_pointer$ +/- 2K 的范围内。 + //上文参考自:https://blog.csdn.net/zoomdy/article/details/100703451 +.option pop + la sp, _sp //sp = 主栈栈顶地址 _sp定义在link连接脚本内 + + /* Load data section */ + la a0, _data_lma //a0 = data的Load Memory Address _data_lma定义在link连接脚本内 + la a1, _data //a1 = data的Run Memory Address _data定义在link连接脚本内 + la a2, _edata //a2 = data的Run Memory Address结束地址 _edata定义在link连接脚本内 + bgeu a1, a2, 2f //if( a1 >= a2 ) JUMP 2f 原则上不会出现_data地址大于_edata地址 + //如果出现了则直接跳转到 2f 即下一个2标签 +1: + lw t0, (a0) //t0 = _data_lma + sw t0, (a1) //*_data = t0 即 *_data_lma,按word写入 + addi a0, a0, 4 //a0 = a0 + 4 下一个ward + addi a1, a1, 4 //a1 = a1 + 4 + bltu a1, a2, 1b //if( a1 < a2 ) JUMP 1b 如果未到达_edata则跳转到 1b 即上一个1标签,这里会完成一个循环 +2: + /* Clear bss section */ + la a0, __bss_start //a0 = __bss_start 初值为0的全局变量段起始地址 __bss_start定义在link连接脚本内 + la a1, _end //a1 = _end 初值为0的全局变量段结束地址 _end定义在link连接脚本内 + bgeu a0, a1, 2f //if( a0 >= a1 ) JUMP 2f 原则上不会出现__bss_start地址大于_end地址 + //如果出现了则直接跳转到 2f 即下一个2标签 +1: + sw zero, (a0) //*__bss_start = zero = 0 bss段清除为0 + addi a0, a0, 4 //a0 = a0 + 4 下一个ward + bltu a0, a1, 1b //if( a0 < a1 ) JUMP 1b 如果未到达_end则跳转到 1b 即上一个1标签,这里会完成一个循环 + + //程序执行到这里全局变量就以及处理完毕了 +2: + /*enable mcycle_minstret*/ + csrci CSR_MCOUNTINHIBIT, 0x5 //CSR_MCOUNTINHIBIT &= ~0x5 这里清零了第0bit和第1bit,使能了mcycle计数和minstret计数 + //csrci这条指令处理立即数5bit,列如0x5只是0B00101,高位不处理 + /* + * Call vendor defined SystemInit to + * initialize the micro-controller system + */ + call SystemInit + /* Call global constructors */ + la a0, __libc_fini_array //a0 = __libc_fini_array newlib中atexit函数的参数 + call atexit //调用newlib中的 void atexit(void (*func)(void)) 函数 + //功能为注册main函数结束后调用的函数,这里是__libc_fini_array + call __libc_init_array //调用newlib中的 void __libc_init_array (void) 函数 + //这里要注意__libc_init_array函数会调用_init的钩子函数,用来做c环境初始化前的一些硬件初始化 + //列如时钟的配置等,这里_init定义在init.c + + //程序执行到这里C/C++环境就初始化完成了,可以进入main函数入口了 + /* argc = argv = 0 */ + li a0, 0 //a0 = 0 main函数参数argc = 0 + li a1, 0 //a1 = 0 main函数参数argv = 0 + call main //调用 int main(int argc,char **argv) 函数 + tail exit //main返回后调用newlib的exit函数, tail指令应该是不会返回的调用函数了 + +1: + j 1b //1b 即上一次1标签,即跳转到自己,程序到这里就死循环了,原则不会运行到这里 + + .global disable_mcycle_minstret +disable_mcycle_minstret: + csrsi CSR_MCOUNTINHIBIT, 0x5 //关闭了mcycle计数和minstret计数 + ret + + .global enable_mcycle_minstret +enable_mcycle_minstret: + csrci CSR_MCOUNTINHIBIT, 0x5 //使能了mcycle计数和minstret计数 + ret diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/heap_4.c b/workspace/TS100/Core/BSP/Pine64/Vendor/heap_4.c new file mode 100644 index 00000000..6bb3ffbd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/heap_4.c @@ -0,0 +1,478 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that combines + * (coalescences) adjacent memory blocks as they are freed, and in so doing + * limits memory fragmentation. + * + * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) + #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 +#endif + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( size_t ) 8 ) + +/* Allocate the memory for the heap. */ +#if( configAPPLICATION_ALLOCATED_HEAP == 1 ) + /* The application writer has already defined the array used for the RTOS + heap - probably so it can be placed in a special segment or address. */ + extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#else + uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; +#endif /* configAPPLICATION_ALLOCATED_HEAP */ + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit( void ); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static size_t xFreeBytesRemaining = 0U; +static size_t xMinimumEverFreeBytesRemaining = 0U; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static size_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( pxEnd == NULL ) + { + prvHeapInit(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) + { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); + configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) + { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if( pxBlock != pxEnd ) + { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize ); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); + configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( pxNewBlockLink ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceMALLOC( pvReturn, xWantedSize ); + } + ( void ) xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +uint8_t *puc = ( uint8_t * ) pv; +BlockLink_t *pxLink; + + if( pv != NULL ) + { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + /* Check the block is actually allocated. */ + configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); + configASSERT( pxLink->pxNextFreeBlock == NULL ); + + if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) + { + if( pxLink->pxNextFreeBlock == NULL ) + { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + traceFREE( pv, pxLink->xBlockSize ); + prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); + } + ( void ) xTaskResumeAll(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +size_t xPortGetFreeHeapSize( void ) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit( void ) +{ +BlockLink_t *pxFirstFreeBlock; +uint8_t *pucAlignedHeap; +size_t uxAddress; +size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + uxAddress = ( size_t ) ucHeap; + + if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + uxAddress += ( portBYTE_ALIGNMENT - 1 ); + uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); + xTotalHeapSize -= uxAddress - ( size_t ) ucHeap; + } + + pucAlignedHeap = ( uint8_t * ) uxAddress; + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + at the end of the heap space. */ + uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize; + uxAddress -= xHeapStructSize; + uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); + pxEnd = ( void * ) uxAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = ( void * ) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock; + pxFirstFreeBlock->pxNextFreeBlock = pxEnd; + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) +{ +BlockLink_t *pxIterator; +uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) + { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; + if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = ( uint8_t * ) pxBlockToInsert; + if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) + { + if( pxIterator->pxNextFreeBlock != pxEnd ) + { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } + else + { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if( pxIterator != pxBlockToInsert ) + { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +} + diff --git a/workspace/TS100/Core/BSP/Pine64/flash.c b/workspace/TS100/Core/BSP/Pine64/flash.c new file mode 100644 index 00000000..f00e132b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/flash.c @@ -0,0 +1,23 @@ +/* + * flash.c + * + * Created on: 29 May 2020 + * Author: Ralim + */ + +#include "BSP.h" +#include "BSP_Flash.h" +#include "gd32vf103_libopt.h" +#include "string.h" +/*Flash start OR'ed with the maximum amount of flash - 1024 bytes*/ +/*We use the last 1024 byte page*/ +#define FLASH_ADDR (0x8000000 | 0xFC00) +uint8_t flash_save_buffer(const uint8_t *buffer, const uint16_t length) { + //TODO + return 1; +} + +void flash_read_buffer(uint8_t *buffer, const uint16_t length) { + + //TODO +} diff --git a/workspace/TS100/Core/BSP/Pine64/logo.cpp b/workspace/TS100/Core/BSP/Pine64/logo.cpp new file mode 100644 index 00000000..f71df93d --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/logo.cpp @@ -0,0 +1,27 @@ +/* + * logo.c + * + * Created on: 29 May 2020 + * Author: Ralim + */ + +#include "BSP.h" +#include "OLED.hpp" +// Second last page of flash set aside for logo image. +#define FLASH_LOGOADDR (0x8000000 | 0xF800) + +// Logo header signature. +#define LOGO_HEADER_VALUE 0xF00DAA55 + +uint8_t showBootLogoIfavailable() { +// Do not show logo data if signature is not found. + if (LOGO_HEADER_VALUE + != *(reinterpret_cast(FLASH_LOGOADDR))) { + return 0; + } + + OLED::drawAreaSwapped(0, 0, 96, 16, (uint8_t*) (FLASH_LOGOADDR + 4)); + OLED::refresh(); + return 1; +} + diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp new file mode 100644 index 00000000..deb78e5d --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -0,0 +1,14 @@ +#include "BSP.h" +#include "FreeRTOS.h" +#include "QC3.h" +#include "Settings.h" +#include "cmsis_os.h" +#include "main.hpp" +#include "power.hpp" +#include "stdlib.h" +#include "task.h" +#include "I2C_Wrapper.hpp" +void postRToSInit() { + // Any after RTos setup + FRToSI2C::FRToSInit(); +} diff --git a/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp new file mode 100644 index 00000000..f31610d5 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp @@ -0,0 +1,21 @@ +/* + * preRTOS.c + * + * Created on: 29 May 2020 + * Author: Ralim + */ + +#include "BSP.h" +#include "Pins.h" +#include "Setup.h" +#include +void preRToSInit() { + //Normal system bringup -- GPIO etc + eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); + eclic_global_interrupt_enable(); + hardware_init(); + FRToSI2C::init(); + gpio_bit_reset(OLED_RESET_GPIO_Port, OLED_RESET_Pin); + delay_ms(50); + gpio_bit_set(OLED_RESET_GPIO_Port, OLED_RESET_Pin); +} From a351d60ca0ff095e398d3828c501ba29e803660b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 16 Aug 2020 13:57:57 +1000 Subject: [PATCH 02/72] WiP makefile --- workspace/TS100/Makefile | 183 +++-- .../startup_stm32f103t8ux.S} | 688 +++++++++--------- .../TS100/{LinkerScript.ld => stm32f103.ld} | 0 3 files changed, 464 insertions(+), 407 deletions(-) rename workspace/TS100/{Startup/startup_stm32f103t8ux.s => Startup2/startup_stm32f103t8ux.S} (96%) rename workspace/TS100/{LinkerScript.ld => stm32f103.ld} (100%) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index ba6ba490..e80b1947 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -7,39 +7,84 @@ ifndef lang lang:= EN endif -# Discover the source files to build -SOURCE := $(shell find . -type f -name '*.c') -SOURCE_CPP := $(shell find . -type f -name '*.cpp') -SOURCES := $(shell find . -type f -name '*.c*') -S_SRCS := $(shell find . -type f -name '*.s') + +# Discover the source files to build + + +# Enumerate all of the include directories APP_INC_DIR = ./Core/Inc -CMSIS_DEVICE_INC_DIR = ./Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include +INC_CMSIS_DEVICE = ./Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include CMSIS_CORE_INC_DIR = ./Core/BSP/Miniware/Vendor/CMSIS/Include HAL_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc HAL_LEGACY_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/Legacy FRTOS_CMIS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include -FRTOS_GCC_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 DRIVER_INC_DIR =./Core/Drivers -FUSB_DRIVERS_INC_DIR = ./Core/Drivers/FUSB302 BSP_INC_DIR = ./Core/BSP -MINIWARE_INC_DIR = ./Core/BSP/Miniware THREADS_INC_DIR = ./Core/Threads +MINIWARE_INC_DIR = ./Core/BSP/Miniware +PINE_INC_DIR = ./Core/BSP/Pine64 +PINE_VENDOR_INC_DIR = ./Core/BSP/Pine64/Vendor/Lib +PINE_RISCV_INC_DIR = ./Core/BSP/Pine64/Vendor/RISCV +SOURCE_THREADS_DIR = ./Core/Threads +SOURCE_CORE_DIR = ./Core/Src +SOURCE_DRIVERS_DIR = ./Core/Drivers +INC_PD_DRIVERS_DIR = ./Core/Drivers/FUSB302 +SOURCE_MIDDLEWARES_DIR = ./Middlewares -INCLUDES = -I$(APP_INC_DIR) \ - -I$(CMSIS_DEVICE_INC_DIR)\ +# Device dependent settings +ifeq ($(model),$(filter $(model),TS100 TS80)) +$(info Building for Miniware ) +DEVICE_INCLUDES = -I$(MINIWARE_INC_DIR) \ + -I$(INC_CMSIS_DEVICE)\ -I$(CMSIS_CORE_INC_DIR) \ -I$(HAL_INC_DIR) \ -I$(HAL_LEGACY_INC_DIR) \ + -I$(INC_PD_DRIVERS_DIR) +DEVICE_BSP_DIR = ./Core/BSP/Miniware +S_SRCS := ./Startup/startup_stm32f103t8ux.S +LDSCRIPT=stm32f103.ld +DEV_LDFLAGS= +DEV_AFLAGS= +DEV_CFLAGS= +DEV_CXXFLAGS= +endif + +ifeq ($(model),Pinecil) +DEVICE_INCLUDES = -I$(PINE_INC_DIR) \ +-I$(PINE_INC_DIR)/N200 \ + -I$(PINE_VENDOR_INC_DIR) \ + -I$(PINE_RISCV_INC_DIR) + +DEVICE_BSP_DIR = ./Core/BSP/Pine64 +S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.s') +ASM_INC = -I$(PINE_RISCV_INC_DIR) +LDSCRIPT=GD32VF103x8.ld +DEV_LDFLAGS=-nostartfiles +DEV_AFLAGS = -msmall-data-limit=8 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections +DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" +DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" +endif + +INCLUDES = -I$(APP_INC_DIR) \ -I$(FRTOS_CMIS_INC_DIR) \ -I$(FRTOS_INC_DIR) \ - -I$(FRTOS_GCC_INC_DIR) \ -I$(DRIVER_INC_DIR) \ -I$(BSP_INC_DIR) \ - -I$(MINIWARE_INC_DIR) \ -I$(THREADS_INC_DIR) \ - -I$(FUSB_DRIVERS_INC_DIR) + $(DEVICE_INCLUDES) + +SOURCE := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.c') \ +$(shell find $(SOURCE_CORE_DIR) -type f -name '*.c') \ +$(shell find $(SOURCE_DRIVERS_DIR) -type f -name '*.c') \ +$(shell find $(DEVICE_BSP_DIR) -type f -name '*.c') \ +$(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.c') +SOURCE_CPP := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.cpp') \ +$(shell find $(SOURCE_CORE_DIR) -type f -name '*.cpp') \ +$(shell find $(SOURCE_DRIVERS_DIR) -type f -name '*.cpp') \ +$(shell find $(DEVICE_BSP_DIR) -type f -name '*.cpp') \ +$(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.cpp') # output folder HEXFILE_DIR=Hexfile @@ -47,61 +92,75 @@ HEXFILE_DIR=Hexfile OUTPUT_DIR=Objects # code optimisation ------------------------------------------------------------ +OPTIM_AS= -Wall OPTIM=-Os -flto -ffat-lto-objects -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections # global defines --------------------------------------------------------------- -GLOBAL_DEFINES += -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D LANG_$(lang) -D LANG -D MODEL_$(model) +GLOBAL_DEFINES += -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D LANG_$(lang) -D LANG -D MODEL_$(model) -D GCC_ARMCM3 \ + -D ARM_MATH_CM3 \ + -D STM32F10X_MD \ # Enable debug code generation DEBUG=-g3 -# Without debug code -#DEBUG= - # libs ------------------------------------------------------------------------- LIBS= -# linker script ---------------------------------------------------------------- -LDSCRIPT=LinkerScript.ld # ------------------------------------------------------------------------------ COMPILER=gcc -# arm-none is the general ARM compiler, -COMPILER_PREFIX=arm-none +# arm-none-eabi is the general ARM compiler, +#riscv-none-embed- is the riscv compiler +ifeq ($(model),$(filter $(model),TS100 TS80)) +COMPILER_PREFIX=arm-none-eabi +endif +ifeq ($(model),Pinecil) +COMPILER_PREFIX=riscv-nuclei-elf +endif # programs --------------------------------------------------------------------- -CC=$(COMPILER_PREFIX)-eabi-gcc -CPP=$(COMPILER_PREFIX)-eabi-g++ -AS=$(COMPILER_PREFIX)-eabi-as -GCOV=$(COMPILER_PREFIX)-eabi-gcov -OBJCOPY=$(COMPILER_PREFIX)-eabi-objcopy -OBJDUMP=$(COMPILER_PREFIX)-eabi-objdump -SIZE=$(COMPILER_PREFIX)-eabi-size +CC=$(COMPILER_PREFIX)-gcc +CPP=$(COMPILER_PREFIX)-g++ +AS=$(COMPILER_PREFIX)-as +GCOV=$(COMPILER_PREFIX)-gcov +OBJCOPY=$(COMPILER_PREFIX)-objcopy +OBJDUMP=$(COMPILER_PREFIX)-objdump +SIZE=$(COMPILER_PREFIX)-size +GDB=./tools/riscv-none-embed-gcc/8.3.0-1.1/bin/riscv-none-embed-gdb SREC=srec_cat SREC_INFO=srec_info +ifeq ($(model),Pinecil) +AS=$(COMPILER_PREFIX)-gcc -x assembler-with-cpp +endif +# compiler flags --------------------------------------------------------------- +ifeq ($(model),$(filter $(model),TS100 TS80)) +CPUFLAGS= -mthumb \ + -mcpu=cortex-m3 \ + -mfloat-abi=soft +endif +ifeq ($(model),Pinecil) +CPUFLAGS= -march=rv32imac \ + -mabi=ilp32 \ + -mcmodel=medany \ + -DGD32VF103C_START \ + -DUSE_STDPERIPH_DRIVER +endif # linker flags ----------------------------------------------------------------- +LD_FILE = $(PINE_VENDOR_INC_DIR)/GD32VF103xB.lds LINKER_FLAGS=-Wl,--gc-sections \ -Wl,--wrap=malloc \ -Wl,--wrap=free \ -o$(OUT_HEXFILE).elf \ -Wl,-Map=$(OUT_HEXFILE).map \ - -mcpu=cortex-m3 \ - -mthumb \ - -mfloat-abi=soft \ - -lm -Os -flto -Wl,--undefined=vTaskSwitchContext \ - --specs=nano.specs - -# compiler flags --------------------------------------------------------------- -CPUFLAGS=-D GCC_ARMCM3 \ - -D ARM_MATH_CM3 \ - -D STM32F10X_MD \ - -mthumb \ - -mcpu=cortex-m3 \ - -mfloat-abi=soft + $(CPUFLAGS) \ + -lm -Og -flto -Wl,--undefined=vTaskSwitchContext \ + -T$(LDSCRIPT) \ + --specs=nano.specs \ + $(DEV_LDFLAGS) @@ -157,39 +216,37 @@ CXXFLAGS=$(CPUFLAGS) \ -fno-rtti \ -fno-exceptions \ -fno-threadsafe-statics \ - -T$(LDSCRIPT) + $(DEV_CXXFLAGS) -CFLAGS=$(CPUFLAGS) \ +CFLAGS=$(CPUFLAGS) \ $(DEBUG) \ - $(INCLUDES) \ - $(CHECKOPTIONS_C) \ - $(GLOBAL_DEFINES) \ - -D${COMPILER} \ + $(INCLUDES) \ + $(CHECKOPTIONS_C) \ + $(GLOBAL_DEFINES) \ + -D${COMPILER} \ -MMD \ -std=gnu99 \ $(OPTIM) \ + $(DEV_CFLAGS) \ -fno-common \ - -ffreestanding \ - -T$(LDSCRIPT) \ - -c + -ffreestanding \ + -c AFLAGS=$(CPUFLAGS) \ - $(DEBUG) \ - $(INCLUDES) + $(OPTIM_AS) \ + $(DEBUG) \ + $(ASM_INC) \ + $(DEV_AFLAGS) -ifeq (${COMPILER}, gcc) -AFLAGS += -ffunction-sections -fdata-sections -CFLAGS += -ffunction-sections -fdata-sections -endif OBJS = $(SOURCE:.c=.o) OBJS_CPP = $(SOURCE_CPP:.cpp=.o) -OBJS_S = $(S_SRCS:.s=.o) +OBJS_S = $(S_SRCS:.S=.o) @@ -213,15 +270,14 @@ all: $(OUT_HEXFILE).hex $(OUT_HEXFILE).bin $(SIZE) $^ $(OBJCOPY) $^ -O binary $@ -$(OUT_HEXFILE).elf : $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) Makefile $(LDSCRIPT) +$(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) @test -d $(@D) || mkdir -p $(@D) @echo Linking $(OUTPUT_EXE).elf - @$(CPP) $(CXXFLAGS) $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) $(LIBS) $(LINKER_FLAGS) + @$(CPP) $(CXXFLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) $(LINKER_FLAGS) $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) @echo Compiling ${<} -# @echo $(CFLAGS) @$(CC) -c $(CFLAGS) $< -o $@ @$(OBJDUMP) -d -S $@ > $@.lst @@ -231,11 +287,11 @@ $(OUT_OBJS_CPP): $(OUTPUT_DIR)/%.o : %.cpp Makefile @$(CPP) -c $(CXXFLAGS) $< -o $@ @$(OBJDUMP) -d -S $@ > $@.lst -$(OUT_OBJS_S): $(OUTPUT_DIR)/%.o: %.s Makefile +$(OUT_OBJS_S): $(OUTPUT_DIR)/%.o: %.S Makefile @test -d $(@D) || mkdir -p $(@D) @echo 'Building file: $<' @echo 'Invoking: MCU GCC Assembler' - @$(AS) -mcpu=cortex-m3 -mthumb -mfloat-abi=soft $(INCLUDES) -g $< -o $@ + @$(AS) -c $(AFLAGS) $< -o $@ @echo 'Finished building: $<' @echo ' ' @@ -244,6 +300,7 @@ clean : rm -Rf $(OUTPUT_DIR) rm -Rf $(HEXFILE_DIR) + # pull in dependency info for *existing* .o files -include $(OUT_OBJS:.o=.d) -include $(OUT_OBJS_CPP:.o=.d) diff --git a/workspace/TS100/Startup/startup_stm32f103t8ux.s b/workspace/TS100/Startup2/startup_stm32f103t8ux.S similarity index 96% rename from workspace/TS100/Startup/startup_stm32f103t8ux.s rename to workspace/TS100/Startup2/startup_stm32f103t8ux.S index 8916ae55..f8d1c8ed 100644 --- a/workspace/TS100/Startup/startup_stm32f103t8ux.s +++ b/workspace/TS100/Startup2/startup_stm32f103t8ux.S @@ -1,344 +1,344 @@ -/** - ****************************************************************************** - * @file startup_stm32.s - * @author Ac6 - * @version V1.0.0 - * @date 12-June-2014 - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m3 - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss - -.equ BootRAM, 0xF1E0F85F -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval : None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2] - adds r2, r2, #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system intitialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - -LoopForever: - b LoopForever - -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * - * @param None - * @retval : None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex-M. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - .word WWDG_IRQHandler - .word PVD_IRQHandler - .word TAMPER_IRQHandler - .word RTC_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_2_IRQHandler - .word USB_HP_CAN1_TX_IRQHandler - .word USB_LP_CAN1_RX0_IRQHandler - .word CAN1_RX1_IRQHandler - .word CAN1_SCE_IRQHandler - .word EXTI9_5_IRQHandler - .word TIM1_BRK_IRQHandler - .word TIM1_UP_IRQHandler - .word TIM1_TRG_COM_IRQHandler - .word TIM1_CC_IRQHandler - .word TIM2_IRQHandler - .word TIM3_IRQHandler - .word TIM4_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C2_EV_IRQHandler - .word I2C2_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word USART2_IRQHandler - .word USART3_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word USBWakeUp_IRQHandler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word BootRAM /* @0x108. This is for boot in RAM mode for - STM32F10x Medium Density devices. */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDG_IRQHandler - .thumb_set WWDG_IRQHandler,Default_Handler - - .weak PVD_IRQHandler - .thumb_set PVD_IRQHandler,Default_Handler - - .weak TAMPER_IRQHandler - .thumb_set TAMPER_IRQHandler,Default_Handler - - .weak RTC_IRQHandler - .thumb_set RTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak RCC_IRQHandler - .thumb_set RCC_IRQHandler,Default_Handler - - .weak EXTI0_IRQHandler - .thumb_set EXTI0_IRQHandler,Default_Handler - - .weak EXTI1_IRQHandler - .thumb_set EXTI1_IRQHandler,Default_Handler - - .weak EXTI2_IRQHandler - .thumb_set EXTI2_IRQHandler,Default_Handler - - .weak EXTI3_IRQHandler - .thumb_set EXTI3_IRQHandler,Default_Handler - - .weak EXTI4_IRQHandler - .thumb_set EXTI4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak USB_HP_CAN1_TX_IRQHandler - .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler - - .weak USB_LP_CAN1_RX0_IRQHandler - .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SCE_IRQHandler - .thumb_set CAN1_SCE_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak TIM1_BRK_IRQHandler - .thumb_set TIM1_BRK_IRQHandler,Default_Handler - - .weak TIM1_UP_IRQHandler - .thumb_set TIM1_UP_IRQHandler,Default_Handler - - .weak TIM1_TRG_COM_IRQHandler - .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler - - .weak TIM1_CC_IRQHandler - .thumb_set TIM1_CC_IRQHandler,Default_Handler - - .weak TIM2_IRQHandler - .thumb_set TIM2_IRQHandler,Default_Handler - - .weak TIM3_IRQHandler - .thumb_set TIM3_IRQHandler,Default_Handler - - .weak TIM4_IRQHandler - .thumb_set TIM4_IRQHandler,Default_Handler - - .weak I2C1_EV_IRQHandler - .thumb_set I2C1_EV_IRQHandler,Default_Handler - - .weak I2C1_ER_IRQHandler - .thumb_set I2C1_ER_IRQHandler,Default_Handler - - .weak I2C2_EV_IRQHandler - .thumb_set I2C2_EV_IRQHandler,Default_Handler - - .weak I2C2_ER_IRQHandler - .thumb_set I2C2_ER_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXTI15_10_IRQHandler - .thumb_set EXTI15_10_IRQHandler,Default_Handler - - .weak RTC_Alarm_IRQHandler - .thumb_set RTC_Alarm_IRQHandler,Default_Handler - - .weak USBWakeUp_IRQHandler - .thumb_set USBWakeUp_IRQHandler,Default_Handler - - -/************************ (C) COPYRIGHT Ac6 *****END OF FILE****/ +/** + ****************************************************************************** + * @file startup_stm32.s + * @author Ac6 + * @version V1.0.0 + * @date 12-June-2014 + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF1E0F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex-M. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBWakeUp_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word BootRAM /* @0x108. This is for boot in RAM mode for + STM32F10x Medium Density devices. */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMPER_IRQHandler + .thumb_set TAMPER_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak USB_HP_CAN1_TX_IRQHandler + .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler + + .weak USB_LP_CAN1_RX0_IRQHandler + .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBWakeUp_IRQHandler + .thumb_set USBWakeUp_IRQHandler,Default_Handler + + +/************************ (C) COPYRIGHT Ac6 *****END OF FILE****/ diff --git a/workspace/TS100/LinkerScript.ld b/workspace/TS100/stm32f103.ld similarity index 100% rename from workspace/TS100/LinkerScript.ld rename to workspace/TS100/stm32f103.ld From 7d9feadc164c6d50959a39930941450297e3ede5 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 16 Aug 2020 13:58:04 +1000 Subject: [PATCH 03/72] . --- workspace/TS100/{Startup2 => Startup}/startup_stm32f103t8ux.S | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename workspace/TS100/{Startup2 => Startup}/startup_stm32f103t8ux.S (100%) diff --git a/workspace/TS100/Startup2/startup_stm32f103t8ux.S b/workspace/TS100/Startup/startup_stm32f103t8ux.S similarity index 100% rename from workspace/TS100/Startup2/startup_stm32f103t8ux.S rename to workspace/TS100/Startup/startup_stm32f103t8ux.S From 3560f6c5c181d45539bb3680d10255aa9b36bb1e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 16 Aug 2020 18:27:45 +1000 Subject: [PATCH 04/72] Add riscv compiler to docker image --- Dockerfile | 2 ++ workspace/TS100/Makefile | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7b9e0762..bcef5988 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,10 @@ RUN apt-get update && \ wget && \ apt-get clean RUN wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | tar -xj +RUN wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj # Add compiler to the path ENV PATH "/build/gcc-arm-none-eabi-9-2020-q2-update/bin:$PATH" +ENV PATH "/build/rv_linux_bare_1908291308/bin:$PATH" COPY . /build/source COPY ./ci /build/ci diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index e80b1947..94c29c24 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -126,7 +126,6 @@ GCOV=$(COMPILER_PREFIX)-gcov OBJCOPY=$(COMPILER_PREFIX)-objcopy OBJDUMP=$(COMPILER_PREFIX)-objdump SIZE=$(COMPILER_PREFIX)-size -GDB=./tools/riscv-none-embed-gcc/8.3.0-1.1/bin/riscv-none-embed-gdb SREC=srec_cat SREC_INFO=srec_info From 2becaa5eab9e54ca36b389e8bc4000fe95864173 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Aug 2020 18:58:00 +1000 Subject: [PATCH 05/72] Further work on Pinecil compile --- Dockerfile | 2 +- .../{Inc => BSP/Miniware}/FreeRTOSConfig.h | 0 .../GCC/ARM_CM3 => Core/BSP/Miniware}/port.c | 0 .../ARM_CM3 => Core/BSP/Miniware}/portmacro.h | 0 .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 247 ++-- .../TS100/Core/BSP/Pine64/Model_Config.h | 27 + workspace/TS100/Core/BSP/Pine64/N200/port.c | 192 ++- .../TS100/Core/BSP/Pine64/N200/portmacro.h | 152 +-- workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 18 +- workspace/TS100/Core/Drivers/LIS2DH12.cpp | 50 +- workspace/TS100/Core/Drivers/LIS2DH12.hpp | 17 +- workspace/TS100/Core/Inc/FreeRTOSHooks.h | 13 +- workspace/TS100/Core/Inc/Settings.h | 60 +- workspace/TS100/Core/Inc/main.hpp | 21 +- workspace/TS100/Core/Src/FreeRTOSHooks.c | 20 +- workspace/TS100/Core/Threads/PIDThread.cpp | 55 +- .../Lib/GD32VF103xB.lds => GD32VF103xB.ld} | 0 workspace/TS100/Makefile | 17 +- .../FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c | 1072 +++++++++-------- .../Source/include/deprecated_definitions.h | 279 ----- .../FreeRTOS/Source/include/portable.h | 115 +- workspace/TS100/configuration.h | 117 +- 22 files changed, 1214 insertions(+), 1260 deletions(-) rename workspace/TS100/Core/{Inc => BSP/Miniware}/FreeRTOSConfig.h (100%) rename workspace/TS100/{Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 => Core/BSP/Miniware}/port.c (100%) rename workspace/TS100/{Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3 => Core/BSP/Miniware}/portmacro.h (100%) create mode 100644 workspace/TS100/Core/BSP/Pine64/Model_Config.h rename workspace/TS100/{Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds => GD32VF103xB.ld} (100%) delete mode 100644 workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h diff --git a/Dockerfile b/Dockerfile index bcef5988..345acdc2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,6 @@ RUN wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download # Add compiler to the path ENV PATH "/build/gcc-arm-none-eabi-9-2020-q2-update/bin:$PATH" -ENV PATH "/build/rv_linux_bare_1908291308/bin:$PATH" +ENV PATH "/build/rv_linux_bare_1908312208/bin/:$PATH" COPY . /build/source COPY ./ci /build/ci diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/BSP/Miniware/FreeRTOSConfig.h similarity index 100% rename from workspace/TS100/Core/Inc/FreeRTOSConfig.h rename to workspace/TS100/Core/BSP/Miniware/FreeRTOSConfig.h diff --git a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/workspace/TS100/Core/BSP/Miniware/port.c similarity index 100% rename from workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c rename to workspace/TS100/Core/BSP/Miniware/port.c diff --git a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h b/workspace/TS100/Core/BSP/Miniware/portmacro.h similarity index 100% rename from workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h rename to workspace/TS100/Core/BSP/Miniware/portmacro.h diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index e73b9891..73f94629 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -12,7 +12,8 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; #define FLAG_TIMEOUT 1000 -void FRToSI2C::CpltCallback() { +void FRToSI2C::CpltCallback() +{ //TODO } @@ -20,28 +21,31 @@ void FRToSI2C::CpltCallback() { * * @param obj The I2C object */ -int i2c_start() { +int i2c_start() +{ int timeout; /* clear I2C_FLAG_AERR Flag */ i2c_flag_clear(I2C0, I2C_FLAG_AERR); /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) + { + if ((timeout--) == 0) + { - return (int) -1; + return (int)-1; } } /* ensure the i2c has been stopped */ - timeout = FLAG_TIMEOUT - ; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { - if ((timeout--) == 0) { - return (int) -1; + timeout = FLAG_TIMEOUT; + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) + { + if ((timeout--) == 0) + { + return (int)-1; } } @@ -49,30 +53,34 @@ int i2c_start() { i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - return (int) -1; + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) + { + if ((timeout--) == 0) + { + return (int)-1; } } - return (int) 0; + return (int)0; } /** Send STOP command * * @param obj The I2C object */ -int i2c_stop() { +int i2c_stop() +{ /* generate a STOP condition */ i2c_stop_on_bus(I2C0); /* wait for STOP bit reset */ int timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) { - if ((timeout--) == 0) { + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) + { + if ((timeout--) == 0) + { return -1; } } @@ -86,26 +94,32 @@ int i2c_stop() { * @param last Acknoledge * @return The read byte */ -int i2c_byte_read(int last) { +int i2c_byte_read(int last) +{ int timeout; - if (last) { + if (last) + { /* disable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } else { + } + else + { /* enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); } /* wait until the byte is received */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) { - if ((timeout--) == 0) { + while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) + { + if ((timeout--) == 0) + { return -1; } } - return (int) i2c_data_receive(I2C0); + return (int)i2c_data_receive(I2C0); } /** Write one byte @@ -114,15 +128,17 @@ int i2c_byte_read(int last) { * @param data Byte to be written * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. */ -int i2c_byte_write(int data) { +int i2c_byte_write(int data) +{ int timeout; i2c_data_transmit(I2C0, data); /* wait until the byte is transmitted */ timeout = FLAG_TIMEOUT; - while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) - || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { - if ((timeout--) == 0) { + while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) + { + if ((timeout--) == 0) + { return 2; } } @@ -131,7 +147,8 @@ int i2c_byte_write(int data) { } bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { + uint8_t *pData, uint16_t Size) +{ if (!lock()) return false; @@ -140,13 +157,18 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, /* wait until I2C_FLAG_I2CBSY flag is reset */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return false; - } else { - if (timeout % 5 == 0) { + } + else + { + if (timeout % 5 == 0) + { i2c_stop(); } } @@ -155,10 +177,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return false; @@ -170,9 +193,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) + { timeout++; - if (timeout > 100000) { + if (timeout > 100000) + { i2c_stop(); unlock(); return false; @@ -180,7 +205,8 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, } bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - if (no_ack) { + if (no_ack) + { i2c_stop(); unlock(); return false; @@ -190,21 +216,23 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, int status = i2c_byte_write(MemAddress); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB); - if (status == 2 || no_ack) { + if (status == 2 || no_ack) + { i2c_stop(); unlock(); return false; } -//////////////////////////// //Restart into read + //////////////////////////// //Restart into read /* generate a START condition */ i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return false; @@ -216,9 +244,11 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) + { timeout++; - if (timeout > 100000) { + if (timeout > 100000) + { i2c_stop(); unlock(); return false; @@ -228,13 +258,15 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - if (no_ack) { + if (no_ack) + { i2c_stop(); unlock(); return false; } - for (count = 0; count < Size; count++) { - pData[count] = i2c_byte_read(count == (Size - 1)); + for (count = 0; count < Size; count++) + { + pData[count] = i2c_byte_read(count == (uint32_t)(Size - 1)); } /* if not sequential write, then send stop */ @@ -243,17 +275,20 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, unlock(); return true; } -void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { +void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) +{ Mem_Write(address, reg, &data, 1); } -uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { +uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) +{ uint8_t temp = 0; Mem_Read(add, reg, &temp, 1); return temp; } void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { + uint8_t *pData, uint16_t Size) +{ if (!lock()) return; @@ -261,15 +296,19 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, int timeout = 0; /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return; - } else { - if (timeout % 5 == 0) { + } + else + { + if (timeout % 5 == 0) + { i2c_stop(); } } @@ -278,10 +317,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return; @@ -293,9 +333,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) + { timeout++; - if (timeout > 100000) { + if (timeout > 100000) + { i2c_stop(); unlock(); return; @@ -305,9 +347,11 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); int status = i2c_byte_write(MemAddress); - for (count = 0; count < Size; count++) { + for (count = 0; count < Size; count++) + { status = i2c_byte_write(pData[count]); - if (status != 1) { + if (status != 1) + { i2c_stop(); unlock(); return; @@ -320,7 +364,8 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, unlock(); } -void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { +void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ if (!lock()) return; uint32_t count = 0; @@ -328,13 +373,18 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { /* wait until I2C_FLAG_I2CBSY flag is reset */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return; - } else { - if (timeout % 5 == 0) { + } + else + { + if (timeout % 5 == 0) + { i2c_stop(); } } @@ -343,10 +393,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { + timeout = FLAG_TIMEOUT; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) + { + if ((timeout--) == 0) + { i2c_stop(); unlock(); return; @@ -358,9 +409,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) + { timeout++; - if (timeout > 100000) { + if (timeout > 100000) + { i2c_stop(); unlock(); return; @@ -370,9 +423,11 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - for (count = 0; count < Size; count++) { + for (count = 0; count < Size; count++) + { int status = i2c_byte_write(pData[count]); - if (status != 1) { + if (status != 1) + { i2c_stop(); unlock(); return; @@ -385,7 +440,8 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { unlock(); } -bool FRToSI2C::probe(uint16_t DevAddress) { +bool FRToSI2C::probe(uint16_t DevAddress) +{ if (!lock()) return false; i2c_start(); @@ -393,14 +449,16 @@ bool FRToSI2C::probe(uint16_t DevAddress) { i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); /* wait until ADDSEND bit is set */ int timeout = FLAG_TIMEOUT; - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - if (i2c_flag_get(I2C0, I2C_FLAG_AERR) - || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) + { + if (i2c_flag_get(I2C0, I2C_FLAG_AERR) || i2c_flag_get(I2C0, I2C_FLAG_BERR)) + { i2c_stop(); unlock(); return false; } - if (timeout-- == 0) { + if (timeout-- == 0) + { i2c_stop(); unlock(); return false; @@ -422,17 +480,20 @@ bool FRToSI2C::probe(uint16_t DevAddress) { return !no_ack; } -void FRToSI2C::I2C_Unstick() { +void FRToSI2C::I2C_Unstick() +{ unstick_I2C(); } -bool FRToSI2C::lock() { +bool FRToSI2C::lock() +{ if (I2CSemaphore == nullptr) return true; - return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; + return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; } -void FRToSI2C::unlock() { +void FRToSI2C::unlock() +{ if (I2CSemaphore == nullptr) return; xSemaphoreGive(I2CSemaphore); diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h new file mode 100644 index 00000000..6d274997 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -0,0 +1,27 @@ +/* + * Model_Config.h + * + * Created on: 25 Jul 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_MODEL_CONFIG_H_ +#define BSP_MINIWARE_MODEL_CONFIG_H_ +/* + * Lookup for mapping features <-> Models + */ + +#if defined(MODEL_Pinecil) > 1 +#error "Multiple models defined!" +#elif defined(MODEL_Pinecil) == 0 +#error "No model defined!" +#endif + +#ifdef MODEL_Pinecil +#define ACCEL_LIS +#define TEMP_TMP36 +#define POW_QC +#define POW_PD +#endif + +#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/N200/port.c b/workspace/TS100/Core/BSP/Pine64/N200/port.c index ac7c84fd..13b06f47 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/port.c +++ b/workspace/TS100/Core/BSP/Pine64/N200/port.c @@ -1,3 +1,4 @@ +#include "FreeRTOSConfig.h" #include "FreeRTOS.h" #include "task.h" #include "portmacro.h" @@ -6,36 +7,32 @@ #include "riscv_encoding.h" #include "n200_timer.h" #include "n200_eclic.h" - /* Standard Includes */ #include #include #include - /* Each task maintains its own interrupt status in the critical nesting variable. */ UBaseType_t uxCriticalNesting = 0xaaaaaaaa; #if USER_MODE_TASKS #ifdef __riscv_flen - unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); +unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); #else - unsigned long MSTATUS_INIT = (MSTATUS_MPIE); +unsigned long MSTATUS_INIT = (MSTATUS_MPIE); #endif #else #ifdef __riscv_flen - unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); +unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); #else - unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); +unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); #endif #endif - /* * Used to catch tasks that attempt to return from their implementing function. */ -static void prvTaskExitError( void ); - +static void prvTaskExitError(void); /** * @brief System Call Trap @@ -47,52 +44,51 @@ static void prvTaskExitError( void ); */ unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) { - switch(mcause&0X00000fff) + switch (mcause & 0X00000fff) { - //on User and Machine ECALL, handler the request - case 8: - case 11: + //on User and Machine ECALL, handler the request + case 8: + case 11: + { + if (arg1 == IRQ_DISABLE) { - if(arg1==IRQ_DISABLE) - { - //zero out mstatus.mpie - clear_csr(mstatus,MSTATUS_MPIE); - } - else if(arg1==IRQ_ENABLE) - { - //set mstatus.mpie - set_csr(mstatus,MSTATUS_MPIE); - } - else if(arg1==PORT_YIELD) - { - //always yield from machine mode - //fix up mepc on sync trap - unsigned long epc = read_csr(mepc); - vPortYield_from_ulSynchTrap(sp,epc+4); - } - else if(arg1==PORT_YIELD_TO_RA) - { - vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp)))); - } - break; + //zero out mstatus.mpie + clear_csr(mstatus, MSTATUS_MPIE); } - default: + else if (arg1 == IRQ_ENABLE) { - /* 异常处理 */ - extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); - handle_trap(mcause,sp); + //set mstatus.mpie + set_csr(mstatus, MSTATUS_MPIE); } + else if (arg1 == PORT_YIELD) + { + //always yield from machine mode + //fix up mepc on sync trap + unsigned long epc = read_csr(mepc); + vPortYield_from_ulSynchTrap(sp, epc + 4); + } + else if (arg1 == PORT_YIELD_TO_RA) + { + vPortYield_from_ulSynchTrap(sp, (*(unsigned long *)(sp + 1 * sizeof(sp)))); + } + break; + } + default: + { + /* 异常处理 */ + extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); + handle_trap(mcause, sp); + } } //fix mepc and return unsigned long epc = read_csr(mepc); - write_csr(mepc,epc+4); + write_csr(mepc, epc + 4); return sp; } /*-----------------------------------------------------------*/ - /** * @brief 设置触发软中断 * @note 目的是在软中断内进行任务上下文切换 @@ -100,24 +96,22 @@ unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long */ void vPortSetMSIPInt(void) { - *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01; + *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) |= 0x01; __asm volatile("fence"); __asm volatile("fence.i"); } /*-----------------------------------------------------------*/ - /** * @brief 清除软中断 * */ void vPortClearMSIPInt(void) { - *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; + *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; } /*-----------------------------------------------------------*/ - /** * @brief 执行任务上下文切换,在portasm.S中被调用 * @@ -125,23 +119,22 @@ void vPortClearMSIPInt(void) * @param arg1 * @return unsigned long sp地址 */ -unsigned long taskswitch( unsigned long sp, unsigned long arg1) +unsigned long taskswitch(unsigned long sp, unsigned long arg1) { //always yield from machine mode //fix up mepc on unsigned long epc = read_csr(mepc); - vPortYield(sp,epc); //never returns + vPortYield(sp, epc); //never returns return sp; } /*-----------------------------------------------------------*/ - /** * @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用 * */ -void vDoTaskSwitchContext( void ) +void vDoTaskSwitchContext(void) { portDISABLE_INTERRUPTS(); vTaskSwitchContext(); @@ -149,45 +142,42 @@ void vDoTaskSwitchContext( void ) } /*-----------------------------------------------------------*/ - /** * @brief 进入临界段 * */ -void vPortEnterCritical( void ) +void vPortEnterCritical(void) { - #if USER_MODE_TASKS - ECALL(IRQ_DISABLE); - #else - portDISABLE_INTERRUPTS(); - #endif +#if USER_MODE_TASKS + ECALL(IRQ_DISABLE); +#else + portDISABLE_INTERRUPTS(); +#endif uxCriticalNesting++; } /*-----------------------------------------------------------*/ - /** * @brief 退出临界段 * */ -void vPortExitCritical( void ) +void vPortExitCritical(void) { - configASSERT( uxCriticalNesting ); + configASSERT(uxCriticalNesting); uxCriticalNesting--; - if( uxCriticalNesting == 0 ) + if (uxCriticalNesting == 0) { - #if USER_MODE_TASKS - ECALL(IRQ_ENABLE); - #else - portENABLE_INTERRUPTS(); - #endif +#if USER_MODE_TASKS + ECALL(IRQ_ENABLE); +#else + portENABLE_INTERRUPTS(); +#endif } return; } /*-----------------------------------------------------------*/ - /** * @brief Clear current interrupt mask and set given mask * @@ -195,11 +185,10 @@ void vPortExitCritical( void ) */ void vPortClearInterruptMask(int int_mask) { - eclic_set_mth (int_mask); + eclic_set_mth(int_mask); } /*-----------------------------------------------------------*/ - /** * @brief Set interrupt mask and return current interrupt enable register * @@ -207,15 +196,14 @@ void vPortClearInterruptMask(int int_mask) */ int xPortSetInterruptMask(void) { - int int_mask=0; - int_mask=eclic_get_mth(); + int int_mask = 0; + int_mask = eclic_get_mth(); portDISABLE_INTERRUPTS(); return int_mask; } /*-----------------------------------------------------------*/ - /** * @brief 初始化任务栈帧 * @@ -224,30 +212,30 @@ int xPortSetInterruptMask(void) * @param pvParameters 任务参数 * @return StackType_t* 完成初始化后的栈顶 */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) { /* Simulate the stack frame as it would be created by a context switch interrupt. */ #ifdef __riscv_flen - pxTopOfStack -= 32; /* 浮点寄存器 */ + pxTopOfStack -= 32; /* 浮点寄存器 */ #endif pxTopOfStack--; - *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ + *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ pxTopOfStack--; - *pxTopOfStack = 0x40; /* CSR_SUBM */ + *pxTopOfStack = 0x40; /* CSR_SUBM */ pxTopOfStack--; - *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ + *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ pxTopOfStack--; - *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ + *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ pxTopOfStack -= 22; - *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ + *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ - pxTopOfStack -=9; + pxTopOfStack -= 9; *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */ pxTopOfStack--; @@ -255,25 +243,24 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px } /*-----------------------------------------------------------*/ - /** * @brief 任务退出函数 * */ -void prvTaskExitError( void ) +void prvTaskExitError(void) { /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it should instead call vTaskDelete( NULL ). Artificially force an assert() to be triggered if configASSERT() is defined, then stop here so application writers can catch the error. */ - configASSERT( uxCriticalNesting == ~0UL ); + configASSERT(uxCriticalNesting == ~0UL); portDISABLE_INTERRUPTS(); - for( ;; ); + for (;;) + ; } /*-----------------------------------------------------------*/ - /** * @brief tick中断 * @note 由于该中断配置为向量模式,则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler @@ -281,39 +268,38 @@ void prvTaskExitError( void ) */ void vPortSysTickHandler(void) { - volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); + volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - #if CONFIG_SYSTEMVIEW_EN +#if CONFIG_SYSTEMVIEW_EN traceISR_ENTER(); - #endif +#endif uint64_t now = *mtime; now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); *mtimecmp = now; /* 调用freertos的tick增加接口 */ - if( xTaskIncrementTick() != pdFALSE ) + if (xTaskIncrementTick() != pdFALSE) { - #if CONFIG_SYSTEMVIEW_EN +#if CONFIG_SYSTEMVIEW_EN traceISR_EXIT_TO_SCHEDULER(); - #endif +#endif portYIELD(); } - #if CONFIG_SYSTEMVIEW_EN +#if CONFIG_SYSTEMVIEW_EN else { traceISR_EXIT(); } - #endif +#endif - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } /*-----------------------------------------------------------*/ - /** * @brief 初始化tick * @@ -321,21 +307,20 @@ void vPortSysTickHandler(void) void vPortSetupTimer(void) { /* 内核timer定时器使用64位的计数器来实现 */ - volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); + volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); portENTER_CRITICAL(); - uint64_t now = *mtime; - now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); - *mtimecmp = now; + uint64_t now = *mtime; + now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); + *mtimecmp = now; portEXIT_CRITICAL(); eclic_set_vmode(CLIC_INT_TMR); - eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); + eclic_irq_enable(CLIC_INT_TMR, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); } /*-----------------------------------------------------------*/ - /** * @brief 初始化软中断 * @@ -343,11 +328,10 @@ void vPortSetupTimer(void) void vPortSetupMSIP(void) { eclic_set_vmode(CLIC_INT_SFT); - eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); + eclic_irq_enable(CLIC_INT_SFT, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); } /*-----------------------------------------------------------*/ - /** * @brief 调度启动前的初始化准备 * diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h index 50383ac5..29ccc744 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h +++ b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h @@ -1,14 +1,13 @@ -#ifndef PORTMACRO_H -#define PORTMACRO_H +#ifndef PINE_PORTMACRO_H +#define PINE_PORTMACRO_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif - #include "riscv_encoding.h" - /*----------------------------------------------------------- * Port specific definitions. * @@ -20,123 +19,128 @@ extern "C" { */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; + typedef portSTACK_TYPE StackType_t; + typedef long BaseType_t; + typedef unsigned long UBaseType_t; -#if( configUSE_16_BIT_TICKS == 1 ) +#if (configUSE_16_BIT_TICKS == 1) typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +#define portMAX_DELAY (TickType_t)0xffff #else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +typedef uint32_t TickType_t; +#define portMAX_DELAY (TickType_t)0xffffffffUL #endif /*-----------------------------------------------------------*/ /* Architecture specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 8 -/*-----------------------------------------------------------*/ - -/* Architecture specifics. */ -extern void vPortYield(unsigned long,unsigned long); -extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long); -extern int xPortSetInterruptMask(void); -extern void vPortClearInterruptMask( int uxSavedStatusValue ); +#define portSTACK_GROWTH (-1) +#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ) +#define portBYTE_ALIGNMENT 8 + /*-----------------------------------------------------------*/ + /* Architecture specifics. */ + extern void vPortYield(unsigned long, unsigned long); + extern void vPortYield_from_ulSynchTrap(unsigned long, unsigned long); + extern int xPortSetInterruptMask(void); + extern void vPortClearInterruptMask(int uxSavedStatusValue); /*-----------------------------------------------------------*/ /*System Calls */ /*-----------------------------------------------------------*/ //ecall macro used to store argument in a3 -#define ECALL(arg) ({ \ - register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \ - asm volatile ("ecall" \ - : "+r" (a2) \ - : \ - : "memory"); \ - a2; \ +#define ECALL(arg) ({ \ + register uintptr_t a2 asm("a2") = (uintptr_t)(arg); \ + asm volatile("ecall" \ + : "+r"(a2) \ + : \ + : "memory"); \ + a2; \ }) - -extern void vPortSetMSIPInt(void); + extern void vPortSetMSIPInt(void); #define port_MSIPSET_BIT vPortSetMSIPInt() -#define IRQ_DISABLE 20 -#define IRQ_ENABLE 30 -#define PORT_YIELD 40 -#define PORT_YIELD_TO_RA 50 +#define IRQ_DISABLE 20 +#define IRQ_ENABLE 30 +#define PORT_YIELD 40 +#define PORT_YIELD_TO_RA 50 /*-----------------------------------------------------------*/ - /* Scheduler utilities. */ /* the return after the ECALL is VERY important */ //#define portYIELD() ECALL(PORT_YIELD); #define portYIELD() port_MSIPSET_BIT; -#if CONFIG_SYSTEMVIEW_EN -#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } } +#ifdef CONFIG_SYSTEMVIEW_EN +#define portEND_SWITCHING_ISR(xSwitchRequired) \ + { \ + if (xSwitchRequired != pdFALSE) \ + { \ + traceISR_EXIT_TO_SCHEDULER(); \ + portYIELD(); \ + } \ + else \ + { \ + traceISR_EXIT(); \ + } \ + } #else -#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD() +#define portEND_SWITCHING_ISR(xSwitchRequired) \ + if (xSwitchRequired != pdFALSE) \ + portYIELD() #endif -#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) +#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) -/* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -extern void eclic_set_mth (uint8_t mth); -#define portDISABLE_INTERRUPTS() \ -{ \ - eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \ - __asm volatile("fence"); \ - __asm volatile("fence.i"); \ -} -#define portENABLE_INTERRUPTS() eclic_set_mth(0) -#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue ) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + /* Critical section management. */ + extern void vPortEnterCritical(void); + extern void vPortExitCritical(void); + extern void eclic_set_mth(uint8_t mth); +#define portDISABLE_INTERRUPTS() \ + { \ + eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY) | 0x1f); \ + __asm volatile("fence"); \ + __asm volatile("fence.i"); \ + } +#define portENABLE_INTERRUPTS() eclic_set_mth(0) +#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. These are not necessary for to use this port. They are defined so the common demo files (which build with all the ports) will build. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) +#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters) /*-----------------------------------------------------------*/ /* Tickless idle/low power functionality. */ #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime) #endif -/*-----------------------------------------------------------*/ + /*-----------------------------------------------------------*/ - -#define portINLINE __inline +#define portINLINE __inline #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) +#define portFORCE_INLINE inline __attribute__((always_inline)) #endif - - - #ifdef __cplusplus } #endif #endif /* PORTMACRO_H */ - diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 779ddc20..224b7d41 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -18,14 +18,16 @@ * * */ -class FRToSI2C { +class FRToSI2C +{ public: - - static void init() { + static void init() + { I2CSemaphore = nullptr; } - static void FRToSInit() { + static void FRToSInit() + { I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); xSemaphoreGive(I2CSemaphore); } @@ -33,20 +35,22 @@ public: static void CpltCallback(); //Normal Tx Callback static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); + uint8_t *pData, uint16_t Size); static void Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); + uint8_t *pData, uint16_t Size); //Returns true if device ACK's being addressed static bool probe(uint16_t DevAddress); static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, - uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); + uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); private: + static bool lock(); + static void unlock(); static void I2C_Unstick(); static SemaphoreHandle_t I2CSemaphore; static StaticSemaphore_t xSemaphoreBuffer; diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.cpp b/workspace/TS100/Core/Drivers/LIS2DH12.cpp index 888e1231..dfd2de43 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.cpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.cpp @@ -10,43 +10,55 @@ #include "LIS2DH12.hpp" #include "cmsis_os.h" -typedef struct { +typedef struct +{ const uint8_t reg; const uint8_t value; } LIS_REG; -static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz - { LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off - { LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins - { LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on - { LIS_CTRL_REG5, 0b00000010 }, { LIS_CTRL_REG6, 0b01100010 }, - //Basically setup the unit to run, and enable 4D orientation detection - { LIS_INT2_CFG, 0b01111110 }, //setup for movement detection - { LIS_INT2_THS, 0x28 }, { LIS_INT2_DURATION, 64 }, { - LIS_INT1_CFG, 0b01111110 }, { LIS_INT1_THS, 0x28 }, { - LIS_INT1_DURATION, 64 } }; +static const LIS_REG i2c_registers[] = {{LIS_CTRL_REG1, 0x17}, // 25Hz + {LIS_CTRL_REG2, 0b00001000}, // Highpass filter off + {LIS_CTRL_REG3, 0b01100000}, // Setup interrupt pins + {LIS_CTRL_REG4, 0b00001000}, // Block update mode off, HR on + {LIS_CTRL_REG5, 0b00000010}, + {LIS_CTRL_REG6, 0b01100010}, + //Basically setup the unit to run, and enable 4D orientation detection + {LIS_INT2_CFG, 0b01111110}, //setup for movement detection + {LIS_INT2_THS, 0x28}, + {LIS_INT2_DURATION, 64}, + {LIS_INT1_CFG, 0b01111110}, + {LIS_INT1_THS, 0x28}, + {LIS_INT1_DURATION, 64}}; -void LIS2DH12::initalize() { +void LIS2DH12::initalize() +{ +#ifdef ACCEL_LIS for (size_t index = 0; - index < (sizeof(i2c_registers) / sizeof(i2c_registers[0])); - index++) { + index < (sizeof(i2c_registers) / sizeof(i2c_registers[0])); + index++) + { FRToSI2C::I2C_RegisterWrite(LIS2DH_I2C_ADDRESS, - i2c_registers[index].reg, i2c_registers[index].value); + i2c_registers[index].reg, i2c_registers[index].value); } +#endif } -void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { +void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) +{ +#ifdef ACCEL_LIS std::array sensorData; FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8, - reinterpret_cast(sensorData.begin()), - sensorData.size() * sizeof(int16_t)); + reinterpret_cast(sensorData.begin()), + sensorData.size() * sizeof(int16_t)); x = sensorData[0]; y = sensorData[1]; z = sensorData[2]; +#endif } -bool LIS2DH12::detect() { +bool LIS2DH12::detect() +{ return FRToSI2C::probe(LIS2DH_I2C_ADDRESS); } diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.hpp b/workspace/TS100/Core/Drivers/LIS2DH12.hpp index 79346e98..e4bef50f 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.hpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.hpp @@ -11,15 +11,18 @@ #include "LIS2DH12_defines.hpp" #include "BSP.h" -class LIS2DH12 { +class LIS2DH12 +{ public: static bool detect(); static void initalize(); //1 = rh, 2,=lh, 8=flat - static Orientation getOrientation() { + static Orientation getOrientation() + { #ifdef LIS_ORI_FLIP uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, - LIS_INT2_SRC) >> 2); + LIS_INT2_SRC) >> + 2); if (val == 8) val = 3; else if (val == 1) @@ -30,11 +33,13 @@ public: val = 3; return static_cast(val); #endif -#ifdef MODEL_TS100 - return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1); +#ifdef ACCEL_LIS + return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, LIS_INT2_SRC) >> 2) - 1); +#else + return Orientation::ORIENTATION_FLAT; #endif } - static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z); + static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z); private: }; diff --git a/workspace/TS100/Core/Inc/FreeRTOSHooks.h b/workspace/TS100/Core/Inc/FreeRTOSHooks.h index 8dca47e6..c7653775 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSHooks.h +++ b/workspace/TS100/Core/Inc/FreeRTOSHooks.h @@ -9,20 +9,19 @@ #define INC_FREERTOSHOOKS_H_ #include "FreeRTOS.h" -#include "cmsis_os.h" #include "unit.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -// RToS -void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, - StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize); -void vApplicationIdleHook(void); + // RToS + void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, + StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize); + void vApplicationIdleHook(void); #ifdef __cplusplus } #endif - #endif /* INC_FREERTOSHOOKS_H_ */ diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index 21d4b35d..8ddd11d5 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -10,9 +10,8 @@ #ifndef SETTINGS_H_ #define SETTINGS_H_ #include -#include "stm32f1xx_hal.h" #include "unit.h" -#define SETTINGSVERSION ( 0x20 ) +#define SETTINGSVERSION (0x20) /*Change this if you change the struct below to prevent people getting \ out of sync*/ @@ -20,47 +19,48 @@ * This struct must be a multiple of 2 bytes as it is saved / restored from * flash in uint16_t chunks */ -typedef struct { - uint8_t version; // Used to track if a reset is needed on firmware upgrade +typedef struct +{ + uint8_t version; // Used to track if a reset is needed on firmware upgrade - uint16_t SolderingTemp; // current set point for the iron - uint16_t SleepTemp; // temp to drop to in sleep - uint8_t SleepTime; // minutes timeout to sleep - uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80 - uint8_t OrientationMode :2; // If true we want to invert the display for lefties - uint8_t sensitivity :4; // Sensitivity of accelerometer (5 bits) - uint8_t autoStartMode :2; // Should the unit automatically jump straight - // into soldering mode when power is applied - uint8_t ShutdownTime; // Time until unit shuts down if left alone - uint8_t boostModeEnabled :1; // Boost mode swaps BUT_A in soldering mode to - // temporary soldering temp over-ride - uint8_t coolingTempBlink :1; // Should the temperature blink on the cool - // down screen until its <50C - uint8_t detailedIDLE :1; // Detailed idle screen - uint8_t detailedSoldering :1; // Detailed soldering screens + uint16_t SolderingTemp; // current set point for the iron + uint16_t SleepTemp; // temp to drop to in sleep + uint8_t SleepTime; // minutes timeout to sleep + uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80 + uint8_t OrientationMode : 2; // If true we want to invert the display for lefties + uint8_t sensitivity : 4; // Sensitivity of accelerometer (5 bits) + uint8_t autoStartMode : 2; // Should the unit automatically jump straight + // into soldering mode when power is applied + uint8_t ShutdownTime; // Time until unit shuts down if left alone + uint8_t boostModeEnabled : 1; // Boost mode swaps BUT_A in soldering mode to + // temporary soldering temp over-ride + uint8_t coolingTempBlink : 1; // Should the temperature blink on the cool + // down screen until its <50C + uint8_t detailedIDLE : 1; // Detailed idle screen + uint8_t detailedSoldering : 1; // Detailed soldering screens #ifdef ENABLED_FAHRENHEIT_SUPPORT - uint8_t temperatureInF :1; // Should the temp be in F or C (true is F) + uint8_t temperatureInF : 1; // Should the temp be in F or C (true is F) #endif - uint8_t descriptionScrollSpeed :1; // Description scroll speed - uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) + uint8_t descriptionScrollSpeed : 1; // Description scroll speed + uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) - uint16_t voltageDiv; // Voltage divisor factor - uint16_t BoostTemp; // Boost mode set point for the iron + uint16_t voltageDiv; // Voltage divisor factor + uint16_t BoostTemp; // Boost mode set point for the iron uint16_t CalibrationOffset; // This stores the temperature offset for this tip // in the iron. uint8_t powerLimitEnable; // Allow toggling of power limit without changing value - uint8_t powerLimit; // Maximum power iron allowed to output + uint8_t powerLimit; // Maximum power iron allowed to output uint16_t TipGain; // uV/C * 10, it can be used to convert tip thermocouple voltage to temperateture TipV/TipGain = TipTemp uint8_t ReverseButtonTempChangeEnabled; // Change the plus and minus button assigment - uint16_t TempChangeLongStep; // Change the plus and minus button assigment - uint16_t TempChangeShortStep; // Change the plus and minus button assigment + uint16_t TempChangeLongStep; // Change the plus and minus button assigment + uint16_t TempChangeShortStep; // Change the plus and minus button assigment - uint32_t padding; // This is here for in case we are not an even divisor so - // that nothing gets cut off - //MUST BE LAST + uint32_t padding; // This is here for in case we are not an even divisor so + // that nothing gets cut off + //MUST BE LAST } systemSettingsType; diff --git a/workspace/TS100/Core/Inc/main.hpp b/workspace/TS100/Core/Inc/main.hpp index edfde783..0024c3a4 100644 --- a/workspace/TS100/Core/Inc/main.hpp +++ b/workspace/TS100/Core/Inc/main.hpp @@ -8,19 +8,20 @@ extern uint32_t currentTempTargetDegC; extern bool settingsWereReset; extern bool usb_pd_available; #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -void vApplicationStackOverflowHook(xTaskHandle *pxTask, - signed portCHAR *pcTaskName); + void vApplicationStackOverflowHook(TaskHandle_t *pxTask, + signed portCHAR *pcTaskName); -//Threads -void startGUITask(void const *argument); -void startPIDTask(void const *argument); -void startMOVTask(void const *argument); -extern TaskHandle_t pidTaskNotification; -extern uint8_t accelInit; -extern uint32_t lastMovementTime; + //Threads + void startGUITask(void const *argument); + void startPIDTask(void const *argument); + void startMOVTask(void const *argument); + extern TaskHandle_t pidTaskNotification; + extern uint8_t accelInit; + extern uint32_t lastMovementTime; #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index f7c56c6a..ee29864f 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -7,7 +7,9 @@ #include "FreeRTOSHooks.h" #include "BSP.h" -void vApplicationIdleHook(void) { +#include "cmsis_os.h" +void vApplicationIdleHook(void) +{ resetWatchdog(); } @@ -16,19 +18,19 @@ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, - StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) { + StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) +{ *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } - -void vApplicationStackOverflowHook(xTaskHandle *pxTask, - signed portCHAR *pcTaskName) { - (void) pxTask; - (void) pcTaskName; - asm("bkpt"); -// We dont have a good way to handle a stack overflow at this point in time +void vApplicationStackOverflowHook(TaskHandle_t *pxTask, + signed portCHAR *pcTaskName) +{ + (void)pxTask; + (void)pcTaskName; + // We dont have a good way to handle a stack overflow at this point in time reboot(); } diff --git a/workspace/TS100/Core/Threads/PIDThread.cpp b/workspace/TS100/Core/Threads/PIDThread.cpp index b0e523dc..95ffedd1 100644 --- a/workspace/TS100/Core/Threads/PIDThread.cpp +++ b/workspace/TS100/Core/Threads/PIDThread.cpp @@ -20,7 +20,8 @@ TaskHandle_t pidTaskNotification = NULL; uint32_t currentTempTargetDegC = 0; // Current temperature target in C /* StartPIDTask function */ -void startPIDTask(void const *argument __unused) { +void startPIDTask(void const *argument __unused) +{ /* * We take the current tip temperature & evaluate the next step for the tip * control PWM. @@ -29,27 +30,32 @@ void startPIDTask(void const *argument __unused) { TickType_t lastPowerPulseStart = 0; TickType_t lastPowerPulseEnd = 0; - history tempError = { { 0 }, 0, 0 }; + history tempError = {{0}, 0, 0}; currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will // be over-ridden rapidly pidTaskNotification = xTaskGetCurrentTaskHandle(); uint32_t PIDTempTarget = 0; - for (;;) { + for (;;) + { - if (ulTaskNotifyTake(pdTRUE, 2000)) { + if (ulTaskNotifyTake(pdTRUE, 2000)) + { // This is a call to block this thread until the ADC does its samples int32_t x10WattsOut = 0; // Do the reading here to keep the temp calculations churning along uint32_t currentTipTempInC = TipThermoModel::getTipInC(true); PIDTempTarget = currentTempTargetDegC; - if (PIDTempTarget) { + if (PIDTempTarget) + { // Cap the max set point to 450C - if (PIDTempTarget > (450)) { + if (PIDTempTarget > (450)) + { //Maximum allowed output PIDTempTarget = (450); } //Safety check that not aiming higher than current tip can measure - if (PIDTempTarget > TipThermoModel::getTipMaxInC()) { + if (PIDTempTarget > TipThermoModel::getTipMaxInC()) + { PIDTempTarget = TipThermoModel::getTipMaxInC(); } // Convert the current tip to degree's C @@ -73,7 +79,7 @@ void startPIDTask(void const *argument __unused) { // Once we have feed-forward temp estimation we should be able to better tune this. int32_t x10WattsNeeded = tempToX10Watts(tError); -// tempError.average()); + // tempError.average()); // note that milliWattsNeeded is sometimes negative, this counters overshoot // from I term's inertia. x10WattsOut += x10WattsNeeded; @@ -89,38 +95,41 @@ void startPIDTask(void const *argument __unused) { // and counters extra power if the iron is no longer losing temp. // basically: temp - lastTemp // Unfortunately, our temp signal is too noisy to really help. - } //If the user turns on the option of using an occasional pulse to keep the power bank on - if (systemSettings.KeepAwakePulse) { + if (systemSettings.KeepAwakePulse) + { - if (xTaskGetTickCount() - lastPowerPulseStart - > powerPulseRate) { + if (xTaskGetTickCount() - lastPowerPulseStart > powerPulseRate) + { lastPowerPulseStart = xTaskGetTickCount(); - lastPowerPulseEnd = lastPowerPulseStart - + powerPulseDuration; + lastPowerPulseEnd = lastPowerPulseStart + powerPulseDuration; } //If current PID is less than the pulse level, check if we want to constrain to the pulse as the floor - if (x10WattsOut < systemSettings.KeepAwakePulse - && xTaskGetTickCount() < lastPowerPulseEnd) { + if (x10WattsOut < systemSettings.KeepAwakePulse && xTaskGetTickCount() < lastPowerPulseEnd) + { x10WattsOut = systemSettings.KeepAwakePulse; } } //Secondary safety check to forcefully disable header when within ADC noise of top of ADC - if (getTipRawTemp(0) > (0x7FFF - 150)) { + if (getTipRawTemp(0) > (0x7FFF - 150)) + { x10WattsOut = 0; } - if (systemSettings.powerLimitEnable - && x10WattsOut > (systemSettings.powerLimit * 10)) { + if (systemSettings.powerLimitEnable && x10WattsOut > (systemSettings.powerLimit * 10)) + { setTipX10Watts(systemSettings.powerLimit * 10); - } else { + } + else + { setTipX10Watts(x10WattsOut); } - - HAL_IWDG_Refresh(&hiwdg); - } else { + resetWatchdog(); + } + else + { //ADC interrupt timeout setTipPWM(0); } diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds b/workspace/TS100/GD32VF103xB.ld similarity index 100% rename from workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds rename to workspace/TS100/GD32VF103xB.ld diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 94c29c24..75dfc3a0 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -27,6 +27,7 @@ MINIWARE_INC_DIR = ./Core/BSP/Miniware PINE_INC_DIR = ./Core/BSP/Pine64 PINE_VENDOR_INC_DIR = ./Core/BSP/Pine64/Vendor/Lib PINE_RISCV_INC_DIR = ./Core/BSP/Pine64/Vendor/RISCV +PINE_N200_INC_DIR = ./Core/BSP/Pine64/N200 SOURCE_THREADS_DIR = ./Core/Threads SOURCE_CORE_DIR = ./Core/Src SOURCE_DRIVERS_DIR = ./Core/Drivers @@ -45,6 +46,9 @@ DEVICE_INCLUDES = -I$(MINIWARE_INC_DIR) \ DEVICE_BSP_DIR = ./Core/BSP/Miniware S_SRCS := ./Startup/startup_stm32f103t8ux.S LDSCRIPT=stm32f103.ld +DEV_GLOBAL_DEFS= -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D GCC_ARMCM3 \ + -D ARM_MATH_CM3 \ + -D STM32F10X_MD DEV_LDFLAGS= DEV_AFLAGS= DEV_CFLAGS= @@ -55,12 +59,14 @@ ifeq ($(model),Pinecil) DEVICE_INCLUDES = -I$(PINE_INC_DIR) \ -I$(PINE_INC_DIR)/N200 \ -I$(PINE_VENDOR_INC_DIR) \ - -I$(PINE_RISCV_INC_DIR) + -I$(PINE_RISCV_INC_DIR) \ + -I$(PINE_N200_INC_DIR)\ + -I$(INC_PD_DRIVERS_DIR) DEVICE_BSP_DIR = ./Core/BSP/Pine64 -S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.s') +S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) -LDSCRIPT=GD32VF103x8.ld +LDSCRIPT=GD32VF103xB.ld DEV_LDFLAGS=-nostartfiles DEV_AFLAGS = -msmall-data-limit=8 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" @@ -97,9 +103,7 @@ OPTIM=-Os -flto -ffat-lto-objects -finline-small-functions -findirect-inlining - # global defines --------------------------------------------------------------- -GLOBAL_DEFINES += -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D LANG_$(lang) -D LANG -D MODEL_$(model) -D GCC_ARMCM3 \ - -D ARM_MATH_CM3 \ - -D STM32F10X_MD \ +GLOBAL_DEFINES += -D LANG_$(lang) -D LANG -D MODEL_$(model) $(DEV_GLOBAL_DEFS) # Enable debug code generation DEBUG=-g3 @@ -277,6 +281,7 @@ $(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCR $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) @echo Compiling ${<} + @echo @$(CC) -c $(CFLAGS) $< -o $@ @$(CC) -c $(CFLAGS) $< -o $@ @$(OBJDUMP) -d -S $@ > $@.lst diff --git a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c b/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c index 7ff30e9d..01593c8b 100644 --- a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c +++ b/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS/cmsis_os.c @@ -26,7 +26,7 @@ * *---------------------------------------------------------------------------- * - * Portions Copyright 2016 STMicroelectronics International N.V. All rights reserved. + * Portions Copyright � 2016 STMicroelectronics International N.V. All rights reserved. * Portions Copyright (c) 2013 ARM LIMITED * All rights reserved. * Redistribution and use in source and binary forms, with or without @@ -53,7 +53,7 @@ * POSSIBILITY OF SUCH DAMAGE. *---------------------------------------------------------------------------*/ - /** +/** ****************************************************************************** * @file cmsis_os.c * @author MCD Application Team @@ -94,7 +94,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** - */ + */ #include #include "cmsis_os.h" @@ -102,75 +102,74 @@ /* * ARM Compiler 4/5 */ -#if defined ( __CC_ARM ) +#if defined(__CC_ARM) - #define __ASM __asm - #define __INLINE __inline - #define __STATIC_INLINE static __inline - #include "cmsis_armcc.h" +#define __ASM __asm +#define __INLINE __inline +#define __STATIC_INLINE static __inline +#include "cmsis_armcc.h" /* * GNU Compiler */ -#elif defined ( __GNUC__ ) +#elif defined(__GNUC__) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - - - #include "cmsis_gcc.h" +#define __ASM __asm /*!< asm keyword for GNU Compiler */ +#define __INLINE inline /*!< inline keyword for GNU Compiler */ +#define __STATIC_INLINE static inline +// #include "cmsis_gcc.h" /* * IAR Compiler */ -#elif defined ( __ICCARM__ ) +#elif defined(__ICCARM__) - #ifndef __ASM - #define __ASM __asm - #endif - #ifndef __INLINE - #define __INLINE inline - #endif - #ifndef __STATIC_INLINE - #define __STATIC_INLINE static inline - #endif +#ifndef __ASM +#define __ASM __asm +#endif +#ifndef __INLINE +#define __INLINE inline +#endif +#ifndef __STATIC_INLINE +#define __STATIC_INLINE static inline +#endif - #include +#include #endif extern void xPortSysTickHandler(void); /* Convert from CMSIS type osPriority to FreeRTOS priority number */ -static unsigned portBASE_TYPE makeFreeRtosPriority (osPriority priority) +static unsigned portBASE_TYPE makeFreeRtosPriority(osPriority priority) { unsigned portBASE_TYPE fpriority = tskIDLE_PRIORITY; - - if (priority != osPriorityError) { + + if (priority != osPriorityError) + { fpriority += (priority - osPriorityIdle); } - + return fpriority; } #if (INCLUDE_uxTaskPriorityGet == 1) /* Convert from FreeRTOS priority number to CMSIS type osPriority */ -static osPriority makeCmsisPriority (unsigned portBASE_TYPE fpriority) +static osPriority makeCmsisPriority(unsigned portBASE_TYPE fpriority) { osPriority priority = osPriorityError; - - if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) { + + if ((fpriority - tskIDLE_PRIORITY) <= (osPriorityRealtime - osPriorityIdle)) + { priority = (osPriority)((int)osPriorityIdle + (int)(fpriority - tskIDLE_PRIORITY)); } - + return priority; } #endif - /* Determine whether we are in thread mode or handler mode. */ -static int inHandlerMode (void) +static int inHandlerMode(void) { return __get_IPSR() != 0; } @@ -181,7 +180,7 @@ static int inHandlerMode (void) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS. */ -osStatus osKernelInitialize (void); +osStatus osKernelInitialize(void); /** * @brief Start the RTOS Kernel with executing the specified thread. @@ -190,10 +189,10 @@ osStatus osKernelInitialize (void); * @retval status code that indicates the execution status of the function * @note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS. */ -osStatus osKernelStart (void) +osStatus osKernelStart(void) { vTaskStartScheduler(); - + return osOK; } @@ -207,17 +206,17 @@ osStatus osKernelStart (void) */ int32_t osKernelRunning(void) { -#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) +#if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1)) if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) return 0; else return 1; #else - return (-1); -#endif + return (-1); +#endif } -#if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available +#if (defined(osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available /** * @brief Get the value of the Kernel SysTick timer * @param None @@ -226,14 +225,16 @@ int32_t osKernelRunning(void) */ uint32_t osKernelSysTick(void) { - if (inHandlerMode()) { + if (inHandlerMode()) + { return xTaskGetTickCountFromISR(); } - else { + else + { return xTaskGetTickCount(); } } -#endif // System Timer available +#endif // System Timer available /*********************** Thread Management *****************************/ /** * @brief Create a thread and add it to Active Threads and set it to state READY. @@ -242,36 +243,40 @@ uint32_t osKernelSysTick(void) * @retval thread ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS. */ -osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) +osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) { TaskHandle_t handle; - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - if((thread_def->buffer != NULL) && (thread_def->controlblock != NULL)) { - handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - thread_def->buffer, thread_def->controlblock); - } - else { - if (xTaskCreate((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - &handle) != pdPASS) { - return NULL; - } - } -#elif( configSUPPORT_STATIC_ALLOCATION == 1 ) - handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - thread_def->buffer, thread_def->controlblock); +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + if ((thread_def->buffer != NULL) && (thread_def->controlblock != NULL)) + { + handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, + thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), + thread_def->buffer, thread_def->controlblock); + } + else + { + if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, + thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), + &handle) != pdPASS) + { + return NULL; + } + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + + handle = xTaskCreateStatic((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, + thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), + thread_def->buffer, thread_def->controlblock); #else - if (xTaskCreate((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name, - thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), - &handle) != pdPASS) { + if (xTaskCreate((TaskFunction_t)thread_def->pthread, (const portCHAR *)thread_def->name, + thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority), + &handle) != pdPASS) + { return NULL; - } + } #endif - + return handle; } @@ -280,12 +285,12 @@ osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) * @retval thread ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS. */ -osThreadId osThreadGetId (void) +osThreadId osThreadGetId(void) { -#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) +#if ((INCLUDE_xTaskGetCurrentTaskHandle == 1) || (configUSE_MUTEXES == 1)) return xTaskGetCurrentTaskHandle(); #else - return NULL; + return NULL; #endif } @@ -295,7 +300,7 @@ osThreadId osThreadGetId (void) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS. */ -osStatus osThreadTerminate (osThreadId thread_id) +osStatus osThreadTerminate(osThreadId thread_id) { #if (INCLUDE_vTaskDelete == 1) vTaskDelete(thread_id); @@ -310,10 +315,10 @@ osStatus osThreadTerminate (osThreadId thread_id) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS. */ -osStatus osThreadYield (void) +osStatus osThreadYield(void) { taskYIELD(); - + return osOK; } @@ -324,7 +329,7 @@ osStatus osThreadYield (void) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS. */ -osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) +osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority) { #if (INCLUDE_vTaskPrioritySet == 1) vTaskPrioritySet(thread_id, makeFreeRtosPriority(priority)); @@ -340,15 +345,15 @@ osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) * @retval current priority value of the thread function. * @note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS. */ -osPriority osThreadGetPriority (osThreadId thread_id) +osPriority osThreadGetPriority(osThreadId thread_id) { #if (INCLUDE_uxTaskPriorityGet == 1) if (inHandlerMode()) { - return makeCmsisPriority(uxTaskPriorityGetFromISR(thread_id)); + return makeCmsisPriority(uxTaskPriorityGetFromISR(thread_id)); } else - { + { return makeCmsisPriority(uxTaskPriorityGet(thread_id)); } #else @@ -362,31 +367,31 @@ osPriority osThreadGetPriority (osThreadId thread_id) * @param millisec time delay value * @retval status code that indicates the execution status of the function. */ -osStatus osDelay (uint32_t millisec) +osStatus osDelay(uint32_t millisec) { #if INCLUDE_vTaskDelay TickType_t ticks = millisec / portTICK_PERIOD_MS; - - vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ - + + vTaskDelay(ticks ? ticks : 1); /* Minimum delay = 1 tick */ + return osOK; #else - (void) millisec; - + (void)millisec; + return osErrorResource; #endif } -#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */ +#if (defined(osFeature_Wait) && (osFeature_Wait != 0)) /* Generic Wait available */ /** * @brief Wait for Signal, Message, Mail, or Timeout * @param millisec timeout value or 0 in case of no time-out * @retval event that contains signal, message, or mail information or error code. * @note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS. */ -osEvent osWait (uint32_t millisec); +osEvent osWait(uint32_t millisec); -#endif /* Generic Wait available */ +#endif /* Generic Wait available */ /*********************** Timer Management Functions ***************************/ /** @@ -397,43 +402,45 @@ osEvent osWait (uint32_t millisec); * @retval timer ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS. */ -osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) +osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument) { #if (configUSE_TIMERS == 1) -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - if(timer_def->controlblock != NULL) { +#if ((configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1)) + if (timer_def->controlblock != NULL) + { return xTimerCreateStatic((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *) argument, - (TaskFunction_t)timer_def->ptimer, - (StaticTimer_t *)timer_def->controlblock); + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, + (void *)argument, + (TaskFunction_t)timer_def->ptimer, + (StaticTimer_t *)timer_def->controlblock); } - else { + else + { return xTimerCreate((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *) argument, - (TaskFunction_t)timer_def->ptimer); - } -#elif( configSUPPORT_STATIC_ALLOCATION == 1 ) + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, + (void *)argument, + (TaskFunction_t)timer_def->ptimer); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) return xTimerCreateStatic((const char *)"", - 1, // period should be filled when starting the Timer using osTimerStart - (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *) argument, - (TaskFunction_t)timer_def->ptimer, - (StaticTimer_t *)timer_def->controlblock); + 1, // period should be filled when starting the Timer using osTimerStart + (type == osTimerPeriodic) ? pdTRUE : pdFALSE, + (void *)argument, + (TaskFunction_t)timer_def->ptimer, + (StaticTimer_t *)timer_def->controlblock); #else return xTimerCreate((const char *)"", 1, // period should be filled when starting the Timer using osTimerStart (type == osTimerPeriodic) ? pdTRUE : pdFALSE, - (void *) argument, + (void *)argument, (TaskFunction_t)timer_def->ptimer); #endif -#else - return NULL; +#else + return NULL; #endif } @@ -444,17 +451,17 @@ osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void * @retval status code that indicates the execution status of the function * @note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS. */ -osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) +osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) { osStatus result = osOK; -#if (configUSE_TIMERS == 1) +#if (configUSE_TIMERS == 1) portBASE_TYPE taskWoken = pdFALSE; TickType_t ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) ticks = 1; - - if (inHandlerMode()) + + if (inHandlerMode()) { if (xTimerChangePeriodFromISR(timer_id, ticks, &taskWoken) != pdPASS) { @@ -462,16 +469,16 @@ osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) } else { - portEND_SWITCHING_ISR(taskWoken); + portEND_SWITCHING_ISR(taskWoken); } } - else + else { if (xTimerChangePeriod(timer_id, ticks, 0) != pdPASS) result = osErrorOS; } -#else +#else result = osErrorOS; #endif return result; @@ -483,26 +490,30 @@ osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS. */ -osStatus osTimerStop (osTimerId timer_id) +osStatus osTimerStop(osTimerId timer_id) { osStatus result = osOK; -#if (configUSE_TIMERS == 1) +#if (configUSE_TIMERS == 1) portBASE_TYPE taskWoken = pdFALSE; - if (inHandlerMode()) { - if (xTimerStopFromISR(timer_id, &taskWoken) != pdPASS) { + if (inHandlerMode()) + { + if (xTimerStopFromISR(timer_id, &taskWoken) != pdPASS) + { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xTimerStop(timer_id, 0) != pdPASS) { + else + { + if (xTimerStop(timer_id, 0) != pdPASS) + { result = osErrorOS; } } -#else +#else result = osErrorOS; -#endif +#endif return result; } @@ -512,25 +523,28 @@ osStatus osTimerStop (osTimerId timer_id) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS. */ -osStatus osTimerDelete (osTimerId timer_id) +osStatus osTimerDelete(osTimerId timer_id) { -osStatus result = osOK; + osStatus result = osOK; #if (configUSE_TIMERS == 1) - if (inHandlerMode()) { - return osErrorISR; + if (inHandlerMode()) + { + return osErrorISR; } - else { - if ((xTimerDelete(timer_id, osWaitForever )) != pdPASS) { + else + { + if ((xTimerDelete(timer_id, osWaitForever)) != pdPASS) + { result = osErrorOS; } - } - -#else + } + +#else result = osErrorOS; -#endif - +#endif + return result; } @@ -542,28 +556,28 @@ osStatus result = osOK; * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. * @note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS. */ -int32_t osSignalSet (osThreadId thread_id, int32_t signal) +int32_t osSignalSet(osThreadId thread_id, int32_t signal) { -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if (configUSE_TASK_NOTIFICATIONS == 1) BaseType_t xHigherPriorityTaskWoken = pdFALSE; uint32_t ulPreviousNotificationValue = 0; - + if (inHandlerMode()) { - if(xTaskGenericNotifyFromISR( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken ) != pdPASS ) + if (xTaskGenericNotifyFromISR(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue, &xHigherPriorityTaskWoken) != pdPASS) return 0x80000000; - - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } - else if(xTaskGenericNotify( thread_id , (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS ) + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + else if (xTaskGenericNotify(thread_id, (uint32_t)signal, eSetBits, &ulPreviousNotificationValue) != pdPASS) return 0x80000000; - + return ulPreviousNotificationValue; #else - (void) thread_id; - (void) signal; + (void)thread_id; + (void)signal; - return 0x80000000; /* Task Notification not supported */ + return 0x80000000; /* Task Notification not supported */ #endif } @@ -574,7 +588,7 @@ int32_t osSignalSet (osThreadId thread_id, int32_t signal) * @retval previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters. * @note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS. */ -int32_t osSignalClear (osThreadId thread_id, int32_t signal); +int32_t osSignalClear(osThreadId thread_id, int32_t signal); /** * @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread. @@ -583,50 +597,56 @@ int32_t osSignalClear (osThreadId thread_id, int32_t signal); * @retval event flag information or error code. * @note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS. */ -osEvent osSignalWait (int32_t signals, uint32_t millisec) +osEvent osSignalWait(int32_t signals, uint32_t millisec) { osEvent ret; -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - +#if (configUSE_TASK_NOTIFICATIONS == 1) + TickType_t ticks; - ret.value.signals = 0; + ret.value.signals = 0; ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } - } - + } + if (inHandlerMode()) { - ret.status = osErrorISR; /*Not allowed in ISR*/ + ret.status = osErrorISR; /*Not allowed in ISR*/ } else { - if(xTaskNotifyWait( 0,(uint32_t) signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE) + if (xTaskNotifyWait(0, (uint32_t)signals, (uint32_t *)&ret.value.signals, ticks) != pdTRUE) { - if(ticks == 0) ret.status = osOK; - else ret.status = osEventTimeout; + if (ticks == 0) + ret.status = osOK; + else + ret.status = osEventTimeout; } - else if(ret.value.signals < 0) + else if (ret.value.signals < 0) { - ret.status = osErrorValue; + ret.status = osErrorValue; } - else ret.status = osEventSignal; + else + ret.status = osEventSignal; } #else - (void) signals; - (void) millisec; - - ret.status = osErrorOS; /* Task Notification not supported */ + (void)signals; + (void)millisec; + + ret.status = osErrorOS; /* Task Notification not supported */ #endif - + return ret; } @@ -637,22 +657,24 @@ osEvent osSignalWait (int32_t signals, uint32_t millisec) * @retval mutex ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS. */ -osMutexId osMutexCreate (const osMutexDef_t *mutex_def) +osMutexId osMutexCreate(const osMutexDef_t *mutex_def) { -#if ( configUSE_MUTEXES == 1) +#if (configUSE_MUTEXES == 1) -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if (mutex_def->controlblock != NULL) { - return xSemaphoreCreateMutexStatic( mutex_def->controlblock ); - } - else { - return xSemaphoreCreateMutex(); + if (mutex_def->controlblock != NULL) + { + return xSemaphoreCreateMutexStatic(mutex_def->controlblock); } -#elif ( configSUPPORT_STATIC_ALLOCATION == 1 ) - return xSemaphoreCreateMutexStatic( mutex_def->controlblock ); -#else - return xSemaphoreCreateMutex(); + else + { + return xSemaphoreCreateMutex(); + } +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xSemaphoreCreateMutexStatic(mutex_def->controlblock); +#else + return xSemaphoreCreateMutex(); #endif #else return NULL; @@ -666,37 +688,43 @@ osMutexId osMutexCreate (const osMutexDef_t *mutex_def) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS. */ -osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) +osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) { TickType_t ticks; - portBASE_TYPE taskWoken = pdFALSE; - - - if (mutex_id == NULL) { + portBASE_TYPE taskWoken = pdFALSE; + + if (mutex_id == NULL) + { return osErrorParameter; } - + ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } } - - if (inHandlerMode()) { - if (xSemaphoreTakeFromISR(mutex_id, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xSemaphoreTakeFromISR(mutex_id, &taskWoken) != pdTRUE) + { return osErrorOS; } - portEND_SWITCHING_ISR(taskWoken); - } - else if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) { + portEND_SWITCHING_ISR(taskWoken); + } + else if (xSemaphoreTake(mutex_id, ticks) != pdTRUE) + { return osErrorOS; } - + return osOK; } @@ -706,18 +734,20 @@ osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS. */ -osStatus osMutexRelease (osMutexId mutex_id) +osStatus osMutexRelease(osMutexId mutex_id) { osStatus result = osOK; portBASE_TYPE taskWoken = pdFALSE; - - if (inHandlerMode()) { - if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xSemaphoreGiveFromISR(mutex_id, &taskWoken) != pdTRUE) + { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } - else if (xSemaphoreGive(mutex_id) != pdTRUE) + else if (xSemaphoreGive(mutex_id) != pdTRUE) { result = osErrorOS; } @@ -730,9 +760,10 @@ osStatus osMutexRelease (osMutexId mutex_id) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS. */ -osStatus osMutexDelete (osMutexId mutex_id) +osStatus osMutexDelete(osMutexId mutex_id) { - if (inHandlerMode()) { + if (inHandlerMode()) + { return osErrorISR; } @@ -743,7 +774,7 @@ osStatus osMutexDelete (osMutexId mutex_id) /******************** Semaphore Management Functions **************************/ -#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) +#if (defined(osFeature_Semaphore) && (osFeature_Semaphore != 0)) /** * @brief Create and Initialize a Semaphore object used for managing resources @@ -752,58 +783,67 @@ osStatus osMutexDelete (osMutexId mutex_id) * @retval semaphore ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS. */ -osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) -{ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count) +{ +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) osSemaphoreId sema; - - if (semaphore_def->controlblock != NULL){ - if (count == 1) { - return xSemaphoreCreateBinaryStatic( semaphore_def->controlblock ); + + if (semaphore_def->controlblock != NULL) + { + if (count == 1) + { + return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); } - else { -#if (configUSE_COUNTING_SEMAPHORES == 1 ) - return xSemaphoreCreateCountingStatic( count, count, semaphore_def->controlblock ); + else + { +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); #else return NULL; #endif } } - else { - if (count == 1) { + else + { + if (count == 1) + { vSemaphoreCreateBinary(sema); return sema; } - else { -#if (configUSE_COUNTING_SEMAPHORES == 1 ) + else + { +#if (configUSE_COUNTING_SEMAPHORES == 1) return xSemaphoreCreateCounting(count, count); #else return NULL; -#endif +#endif } } -#elif ( configSUPPORT_STATIC_ALLOCATION == 1 ) // configSUPPORT_DYNAMIC_ALLOCATION == 0 - if(count == 1) { - return xSemaphoreCreateBinaryStatic( semaphore_def->controlblock ); +#elif (configSUPPORT_STATIC_ALLOCATION == 1) // configSUPPORT_DYNAMIC_ALLOCATION == 0 + if (count == 1) + { + return xSemaphoreCreateBinaryStatic(semaphore_def->controlblock); } else { -#if (configUSE_COUNTING_SEMAPHORES == 1 ) - return xSemaphoreCreateCountingStatic( count, count, semaphore_def->controlblock ); +#if (configUSE_COUNTING_SEMAPHORES == 1) + return xSemaphoreCreateCountingStatic(count, count, semaphore_def->controlblock); #else - return NULL; -#endif + return NULL; +#endif } -#else // configSUPPORT_STATIC_ALLOCATION == 0 && configSUPPORT_DYNAMIC_ALLOCATION == 1 +#else // configSUPPORT_STATIC_ALLOCATION == 0 && configSUPPORT_DYNAMIC_ALLOCATION == 1 osSemaphoreId sema; - - if (count == 1) { + + if (count == 1) + { vSemaphoreCreateBinary(sema); return sema; } - else { -#if (configUSE_COUNTING_SEMAPHORES == 1 ) + else + { +#if (configUSE_COUNTING_SEMAPHORES == 1) return xSemaphoreCreateCounting(count, count); #else return NULL; @@ -819,37 +859,43 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t * @retval number of available tokens, or -1 in case of incorrect parameters. * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS. */ -int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) +int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) { TickType_t ticks; - portBASE_TYPE taskWoken = pdFALSE; - - - if (semaphore_id == NULL) { + portBASE_TYPE taskWoken = pdFALSE; + + if (semaphore_id == NULL) + { return osErrorParameter; } - + ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } } - - if (inHandlerMode()) { - if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) + { return osErrorOS; } - portEND_SWITCHING_ISR(taskWoken); - } - else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) { + portEND_SWITCHING_ISR(taskWoken); + } + else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) + { return osErrorOS; } - + return osOK; } @@ -859,24 +905,27 @@ int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS. */ -osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) +osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) { osStatus result = osOK; portBASE_TYPE taskWoken = pdFALSE; - - - if (inHandlerMode()) { - if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) + { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xSemaphoreGive(semaphore_id) != pdTRUE) { + else + { + if (xSemaphoreGive(semaphore_id) != pdTRUE) + { result = osErrorOS; } } - + return result; } @@ -886,29 +935,30 @@ osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS. */ -osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) +osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) { - if (inHandlerMode()) { + if (inHandlerMode()) + { return osErrorISR; } vSemaphoreDelete(semaphore_id); - return osOK; + return osOK; } -#endif /* Use Semaphores */ +#endif /* Use Semaphores */ /******************* Memory Pool Management Functions ***********************/ -#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) +#if (defined(osFeature_Pool) && (osFeature_Pool != 0)) //TODO //This is a primitive and inefficient wrapper around the existing FreeRTOS memory management. //A better implementation will have to modify heap_x.c! - -typedef struct os_pool_cb { +typedef struct os_pool_cb +{ void *pool; uint8_t *markers; uint32_t pool_sz; @@ -916,55 +966,59 @@ typedef struct os_pool_cb { uint32_t currentIndex; } os_pool_cb_t; - /** * @brief Create and Initialize a memory pool * @param pool_def memory pool definition referenced with \ref osPool. * @retval memory pool ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS. */ -osPoolId osPoolCreate (const osPoolDef_t *pool_def) +osPoolId osPoolCreate(const osPoolDef_t *pool_def) { #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) osPoolId thePool; int itemSize = 4 * ((pool_def->item_sz + 3) / 4); uint32_t i; - - /* First have to allocate memory for the pool control block. */ - thePool = pvPortMalloc(sizeof(os_pool_cb_t)); - - if (thePool) { + /* First have to allocate memory for the pool control block. */ + thePool = pvPortMalloc(sizeof(os_pool_cb_t)); + + if (thePool) + { thePool->pool_sz = pool_def->pool_sz; thePool->item_sz = itemSize; thePool->currentIndex = 0; - + /* Memory for markers */ thePool->markers = pvPortMalloc(pool_def->pool_sz); - - if (thePool->markers) { + + if (thePool->markers) + { /* Now allocate the pool itself. */ - thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize); - - if (thePool->pool) { - for (i = 0; i < pool_def->pool_sz; i++) { + thePool->pool = pvPortMalloc(pool_def->pool_sz * itemSize); + + if (thePool->pool) + { + for (i = 0; i < pool_def->pool_sz; i++) + { thePool->markers[i] = 0; } } - else { + else + { vPortFree(thePool->markers); vPortFree(thePool); thePool = NULL; } } - else { + else + { vPortFree(thePool); thePool = NULL; } } return thePool; - + #else return NULL; #endif @@ -976,41 +1030,48 @@ osPoolId osPoolCreate (const osPoolDef_t *pool_def) * @retval address of the allocated memory block or NULL in case of no memory available. * @note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS. */ -void *osPoolAlloc (osPoolId pool_id) +void *osPoolAlloc(osPoolId pool_id) { int dummy = 0; void *p = NULL; uint32_t i; uint32_t index; - - if (inHandlerMode()) { + + if (inHandlerMode()) + { dummy = portSET_INTERRUPT_MASK_FROM_ISR(); } - else { + else + { vPortEnterCritical(); } - - for (i = 0; i < pool_id->pool_sz; i++) { + + for (i = 0; i < pool_id->pool_sz; i++) + { index = pool_id->currentIndex + i; - if (index >= pool_id->pool_sz) { + if (index >= pool_id->pool_sz) + { index = 0; } - - if (pool_id->markers[index] == 0) { + + if (pool_id->markers[index] == 0) + { pool_id->markers[index] = 1; p = (void *)((uint32_t)(pool_id->pool) + (index * pool_id->item_sz)); pool_id->currentIndex = index; break; } } - - if (inHandlerMode()) { + + if (inHandlerMode()) + { portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy); } - else { + else + { vPortExitCritical(); } - + return p; } @@ -1020,15 +1081,15 @@ void *osPoolAlloc (osPoolId pool_id) * @retval address of the allocated memory block or NULL in case of no memory available. * @note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS. */ -void *osPoolCAlloc (osPoolId pool_id) +void *osPoolCAlloc(osPoolId pool_id) { void *p = osPoolAlloc(pool_id); - + if (p != NULL) { memset(p, 0, sizeof(pool_id->pool_sz)); } - + return p; } @@ -1039,42 +1100,46 @@ void *osPoolCAlloc (osPoolId pool_id) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS. */ -osStatus osPoolFree (osPoolId pool_id, void *block) +osStatus osPoolFree(osPoolId pool_id, void *block) { uint32_t index; - - if (pool_id == NULL) { + + if (pool_id == NULL) + { return osErrorParameter; } - - if (block == NULL) { + + if (block == NULL) + { return osErrorParameter; } - - if (block < pool_id->pool) { + + if (block < pool_id->pool) + { return osErrorParameter; } - + index = (uint32_t)block - (uint32_t)(pool_id->pool); - if (index % pool_id->item_sz) { + if (index % pool_id->item_sz) + { return osErrorParameter; } index = index / pool_id->item_sz; - if (index >= pool_id->pool_sz) { + if (index >= pool_id->pool_sz) + { return osErrorParameter; } - + pool_id->markers[index] = 0; - + return osOK; } - -#endif /* Use Memory Pool Management */ +#endif /* Use Memory Pool Management */ /******************* Message Queue Management Functions *********************/ -#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */ +#if (defined(osFeature_MessageQ) && (osFeature_MessageQ != 0)) /* Use Message Queues */ /** * @brief Create and Initialize a Message Queue @@ -1083,21 +1148,23 @@ osStatus osPoolFree (osPoolId pool_id, void *block) * @retval message queue ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS. */ -osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) +osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id) { - (void) thread_id; - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + (void)thread_id; - if ((queue_def->buffer != NULL) && (queue_def->controlblock != NULL)) { +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) + + if ((queue_def->buffer != NULL) && (queue_def->controlblock != NULL)) + { return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); } - else { + else + { return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); } -#elif ( configSUPPORT_STATIC_ALLOCATION == 1 ) +#elif (configSUPPORT_STATIC_ALLOCATION == 1) return xQueueCreateStatic(queue_def->queue_sz, queue_def->item_sz, queue_def->buffer, queue_def->controlblock); -#else +#else return xQueueCreate(queue_def->queue_sz, queue_def->item_sz); #endif } @@ -1110,28 +1177,33 @@ osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId threa * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS. */ -osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) +osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec) { portBASE_TYPE taskWoken = pdFALSE; TickType_t ticks; - + ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } - - if (inHandlerMode()) { - if (xQueueSendFromISR(queue_id, &info, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xQueueSendFromISR(queue_id, &info, &taskWoken) != pdTRUE) + { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xQueueSend(queue_id, &info, ticks) != pdTRUE) { + else + { + if (xQueueSend(queue_id, &info, ticks) != pdTRUE) + { return osErrorOS; } } - + return osOK; } @@ -1142,63 +1214,73 @@ osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) * @retval event information that includes status code. * @note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS. */ -osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) +osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec) { portBASE_TYPE taskWoken; TickType_t ticks; osEvent event; - + event.def.message_id = queue_id; event.value.v = 0; - - if (queue_id == NULL) { + + if (queue_id == NULL) + { event.status = osErrorParameter; return event; } - + taskWoken = pdFALSE; - + ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } } - - if (inHandlerMode()) { - if (xQueueReceiveFromISR(queue_id, &event.value.v, &taskWoken) == pdTRUE) { + + if (inHandlerMode()) + { + if (xQueueReceiveFromISR(queue_id, &event.value.v, &taskWoken) == pdTRUE) + { /* We have mail */ event.status = osEventMessage; } - else { + else + { event.status = osOK; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xQueueReceive(queue_id, &event.value.v, ticks) == pdTRUE) { + else + { + if (xQueueReceive(queue_id, &event.value.v, ticks) == pdTRUE) + { /* We have mail */ event.status = osEventMessage; } - else { + else + { event.status = (ticks == 0) ? osOK : osEventTimeout; } } - + return event; } -#endif /* Use Message Queues */ +#endif /* Use Message Queues */ /******************** Mail Queue Management Functions ***********************/ -#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */ +#if (defined(osFeature_MailQ) && (osFeature_MailQ != 0)) /* Use Mail Queues */ - -typedef struct os_mailQ_cb { +typedef struct os_mailQ_cb +{ const osMailQDef_t *queue_def; QueueHandle_t handle; osPoolId pool; @@ -1211,39 +1293,41 @@ typedef struct os_mailQ_cb { * @retval mail queue ID for reference by other functions or NULL in case of error. * @note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS. */ -osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) +osMailQId osMailCreate(const osMailQDef_t *queue_def, osThreadId thread_id) { #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - (void) thread_id; - + (void)thread_id; + osPoolDef_t pool_def = {queue_def->queue_sz, queue_def->item_sz, NULL}; - + /* Create a mail queue control block */ *(queue_def->cb) = pvPortMalloc(sizeof(struct os_mailQ_cb)); - if (*(queue_def->cb) == NULL) { + if (*(queue_def->cb) == NULL) + { return NULL; } (*(queue_def->cb))->queue_def = queue_def; - + /* Create a queue in FreeRTOS */ (*(queue_def->cb))->handle = xQueueCreate(queue_def->queue_sz, sizeof(void *)); - - if ((*(queue_def->cb))->handle == NULL) { + if ((*(queue_def->cb))->handle == NULL) + { vPortFree(*(queue_def->cb)); return NULL; } - + /* Create a mail pool */ (*(queue_def->cb))->pool = osPoolCreate(&pool_def); - if ((*(queue_def->cb))->pool == NULL) { + if ((*(queue_def->cb))->pool == NULL) + { //TODO: Delete queue. How to do it in FreeRTOS? vPortFree(*(queue_def->cb)); return NULL; } - + return *(queue_def->cb); #else return NULL; @@ -1257,18 +1341,18 @@ osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) * @retval pointer to memory block that can be filled with mail or NULL in case error. * @note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS. */ -void *osMailAlloc (osMailQId queue_id, uint32_t millisec) +void *osMailAlloc(osMailQId queue_id, uint32_t millisec) { - (void) millisec; + (void)millisec; void *p; - - - if (queue_id == NULL) { + + if (queue_id == NULL) + { return NULL; } - + p = osPoolAlloc(queue_id->pool); - + return p; } @@ -1279,17 +1363,19 @@ void *osMailAlloc (osMailQId queue_id, uint32_t millisec) * @retval pointer to memory block that can be filled with mail or NULL in case error. * @note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS. */ -void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) +void *osMailCAlloc(osMailQId queue_id, uint32_t millisec) { uint32_t i; void *p = osMailAlloc(queue_id, millisec); - - if (p) { - for (i = 0; i < queue_id->queue_def->item_sz; i++) { + + if (p) + { + for (i = 0; i < queue_id->queue_def->item_sz; i++) + { ((uint8_t *)p)[i] = 0; } } - + return p; } @@ -1300,29 +1386,33 @@ void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS. */ -osStatus osMailPut (osMailQId queue_id, void *mail) +osStatus osMailPut(osMailQId queue_id, void *mail) { portBASE_TYPE taskWoken; - - - if (queue_id == NULL) { + + if (queue_id == NULL) + { return osErrorParameter; } - + taskWoken = pdFALSE; - - if (inHandlerMode()) { - if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) { + + if (inHandlerMode()) + { + if (xQueueSendFromISR(queue_id->handle, &mail, &taskWoken) != pdTRUE) + { return osErrorOS; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xQueueSend(queue_id->handle, &mail, 0) != pdTRUE) { + else + { + if (xQueueSend(queue_id->handle, &mail, 0) != pdTRUE) + { return osErrorOS; } } - + return osOK; } @@ -1333,52 +1423,62 @@ osStatus osMailPut (osMailQId queue_id, void *mail) * @retval event that contains mail information or error code. * @note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS. */ -osEvent osMailGet (osMailQId queue_id, uint32_t millisec) +osEvent osMailGet(osMailQId queue_id, uint32_t millisec) { portBASE_TYPE taskWoken; TickType_t ticks; osEvent event; - + event.def.mail_id = queue_id; - - if (queue_id == NULL) { + + if (queue_id == NULL) + { event.status = osErrorParameter; return event; } - + taskWoken = pdFALSE; - + ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } } - - if (inHandlerMode()) { - if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) { + + if (inHandlerMode()) + { + if (xQueueReceiveFromISR(queue_id->handle, &event.value.p, &taskWoken) == pdTRUE) + { /* We have mail */ event.status = osEventMail; } - else { + else + { event.status = osOK; } portEND_SWITCHING_ISR(taskWoken); } - else { - if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) { + else + { + if (xQueueReceive(queue_id->handle, &event.value.p, ticks) == pdTRUE) + { /* We have mail */ event.status = osEventMail; } - else { + else + { event.status = (ticks == 0) ? osOK : osEventTimeout; } } - + return event; } @@ -1389,15 +1489,16 @@ osEvent osMailGet (osMailQId queue_id, uint32_t millisec) * @retval status code that indicates the execution status of the function. * @note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS. */ -osStatus osMailFree (osMailQId queue_id, void *mail) +osStatus osMailFree(osMailQId queue_id, void *mail) { - if (queue_id == NULL) { + if (queue_id == NULL) + { return osErrorParameter; } - + return osPoolFree(queue_id->pool, mail); } -#endif /* Use Mail Queues */ +#endif /* Use Mail Queues */ /*************************** Additional specific APIs to Free RTOS ************/ /** @@ -1408,17 +1509,17 @@ osStatus osMailFree (osMailQId queue_id, void *mail) void osSystickHandler(void) { -#if (INCLUDE_xTaskGetSchedulerState == 1 ) +#if (INCLUDE_xTaskGetSchedulerState == 1) if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { -#endif /* INCLUDE_xTaskGetSchedulerState */ +#endif /* INCLUDE_xTaskGetSchedulerState */ xPortSysTickHandler(); -#if (INCLUDE_xTaskGetSchedulerState == 1 ) +#if (INCLUDE_xTaskGetSchedulerState == 1) } -#endif /* INCLUDE_xTaskGetSchedulerState */ +#endif /* INCLUDE_xTaskGetSchedulerState */ } -#if ( INCLUDE_eTaskGetState == 1 ) +#if (INCLUDE_eTaskGetState == 1) /** * @brief Obtain the state of any thread. * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. @@ -1428,30 +1529,30 @@ osThreadState osThreadGetState(osThreadId thread_id) { eTaskState ThreadState; osThreadState result; - + ThreadState = eTaskGetState(thread_id); - + switch (ThreadState) { - case eRunning : + case eRunning: result = osThreadRunning; break; - case eReady : + case eReady: result = osThreadReady; break; - case eBlocked : + case eBlocked: result = osThreadBlocked; break; - case eSuspended : + case eSuspended: result = osThreadSuspended; break; - case eDeleted : + case eDeleted: result = osThreadDeleted; break; default: result = osThreadError; - } - + } + return result; } #endif /* INCLUDE_eTaskGetState */ @@ -1475,11 +1576,11 @@ osStatus osThreadIsSuspended(osThreadId thread_id) * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. * @retval status code that indicates the execution status of the function. */ -osStatus osThreadSuspend (osThreadId thread_id) +osStatus osThreadSuspend(osThreadId thread_id) { #if (INCLUDE_vTaskSuspend == 1) - vTaskSuspend(thread_id); - + vTaskSuspend(thread_id); + return osOK; #else return osErrorResource; @@ -1491,10 +1592,10 @@ osStatus osThreadSuspend (osThreadId thread_id) * @param thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId. * @retval status code that indicates the execution status of the function. */ -osStatus osThreadResume (osThreadId thread_id) +osStatus osThreadResume(osThreadId thread_id) { -#if (INCLUDE_vTaskSuspend == 1) - if(inHandlerMode()) +#if (INCLUDE_vTaskSuspend == 1) + if (inHandlerMode()) { if (xTaskResumeFromISR(thread_id) == pdTRUE) { @@ -1515,10 +1616,10 @@ osStatus osThreadResume (osThreadId thread_id) * @brief Suspend execution of a all active threads. * @retval status code that indicates the execution status of the function. */ -osStatus osThreadSuspendAll (void) +osStatus osThreadSuspendAll(void) { vTaskSuspendAll(); - + return osOK; } @@ -1526,13 +1627,12 @@ osStatus osThreadSuspendAll (void) * @brief Resume execution of a all suspended threads. * @retval status code that indicates the execution status of the function. */ -osStatus osThreadResumeAll (void) +osStatus osThreadResumeAll(void) { if (xTaskResumeAll() == pdTRUE) return osOK; else return osErrorOS; - } /** @@ -1543,17 +1643,17 @@ osStatus osThreadResumeAll (void) * @param millisec time delay value * @retval status code that indicates the execution status of the function. */ -osStatus osDelayUntil (uint32_t *PreviousWakeTime, uint32_t millisec) +osStatus osDelayUntil(uint32_t *PreviousWakeTime, uint32_t millisec) { #if INCLUDE_vTaskDelayUntil TickType_t ticks = (millisec / portTICK_PERIOD_MS); - vTaskDelayUntil((TickType_t *) PreviousWakeTime, ticks ? ticks : 1); - + vTaskDelayUntil((TickType_t *)PreviousWakeTime, ticks ? ticks : 1); + return osOK; #else - (void) millisec; - (void) PreviousWakeTime; - + (void)millisec; + (void)PreviousWakeTime; + return osErrorResource; #endif } @@ -1566,13 +1666,13 @@ osStatus osDelayUntil (uint32_t *PreviousWakeTime, uint32_t millisec) osStatus osAbortDelay(osThreadId thread_id) { #if INCLUDE_xTaskAbortDelay - + xTaskAbortDelay(thread_id); - + return osOK; #else - (void) thread_id; - + (void)thread_id; + return osErrorResource; #endif } @@ -1584,9 +1684,9 @@ osStatus osAbortDelay(osThreadId thread_id) * will be written * @retval status code that indicates the execution status of the function. */ -osStatus osThreadList (uint8_t *buffer) +osStatus osThreadList(uint8_t *buffer) { -#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) +#if ((configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)) vTaskList((char *)buffer); #endif return osOK; @@ -1598,39 +1698,43 @@ osStatus osThreadList (uint8_t *buffer) * @param millisec timeout value or 0 in case of no time-out. * @retval event information that includes status code. */ -osEvent osMessagePeek (osMessageQId queue_id, uint32_t millisec) +osEvent osMessagePeek(osMessageQId queue_id, uint32_t millisec) { TickType_t ticks; osEvent event; - + event.def.message_id = queue_id; - - if (queue_id == NULL) { + + if (queue_id == NULL) + { event.status = osErrorParameter; return event; } - + ticks = 0; - if (millisec == osWaitForever) { + if (millisec == osWaitForever) + { ticks = portMAX_DELAY; } - else if (millisec != 0) { + else if (millisec != 0) + { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) { + if (ticks == 0) + { ticks = 1; } } - - if (xQueuePeek(queue_id, &event.value.v, ticks) == pdTRUE) + + if (xQueuePeek(queue_id, &event.value.v, ticks) == pdTRUE) { /* We have mail */ event.status = osEventMessage; } - else + else { event.status = (ticks == 0) ? osOK : osEventTimeout; } - + return event; } @@ -1641,7 +1745,8 @@ osEvent osMessagePeek (osMessageQId queue_id, uint32_t millisec) */ uint32_t osMessageWaiting(osMessageQId queue_id) { - if (inHandlerMode()) { + if (inHandlerMode()) + { return uxQueueMessagesWaitingFromISR(queue_id); } else @@ -1655,7 +1760,7 @@ uint32_t osMessageWaiting(osMessageQId queue_id) * @param queue_id message queue ID obtained with \ref osMessageCreate. * @retval available space in a message queue. */ -uint32_t osMessageAvailableSpace(osMessageQId queue_id) +uint32_t osMessageAvailableSpace(osMessageQId queue_id) { return uxQueueSpacesAvailable(queue_id); } @@ -1665,15 +1770,16 @@ uint32_t osMessageAvailableSpace(osMessageQId queue_id) * @param queue_id message queue ID obtained with \ref osMessageCreate. * @retval status code that indicates the execution status of the function. */ -osStatus osMessageDelete (osMessageQId queue_id) +osStatus osMessageDelete(osMessageQId queue_id) { - if (inHandlerMode()) { + if (inHandlerMode()) + { return osErrorISR; } vQueueDelete(queue_id); - return osOK; + return osOK; } /** @@ -1681,25 +1787,27 @@ osStatus osMessageDelete (osMessageQId queue_id) * @param mutex_def mutex definition referenced with \ref osMutex. * @retval mutex ID for reference by other functions or NULL in case of error.. */ -osMutexId osRecursiveMutexCreate (const osMutexDef_t *mutex_def) +osMutexId osRecursiveMutexCreate(const osMutexDef_t *mutex_def) { #if (configUSE_RECURSIVE_MUTEXES == 1) -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if (configSUPPORT_STATIC_ALLOCATION == 1) && (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if (mutex_def->controlblock != NULL){ - return xSemaphoreCreateRecursiveMutexStatic( mutex_def->controlblock ); + if (mutex_def->controlblock != NULL) + { + return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); } - else { + else + { return xSemaphoreCreateRecursiveMutex(); } -#elif ( configSUPPORT_STATIC_ALLOCATION == 1 ) - return xSemaphoreCreateRecursiveMutexStatic( mutex_def->controlblock ); -#else +#elif (configSUPPORT_STATIC_ALLOCATION == 1) + return xSemaphoreCreateRecursiveMutexStatic(mutex_def->controlblock); +#else return xSemaphoreCreateRecursiveMutex(); #endif #else return NULL; -#endif +#endif } /** @@ -1707,18 +1815,18 @@ osMutexId osRecursiveMutexCreate (const osMutexDef_t *mutex_def) * @param mutex_id mutex ID obtained by \ref osRecursiveMutexCreate. * @retval status code that indicates the execution status of the function. */ -osStatus osRecursiveMutexRelease (osMutexId mutex_id) +osStatus osRecursiveMutexRelease(osMutexId mutex_id) { #if (configUSE_RECURSIVE_MUTEXES == 1) osStatus result = osOK; - - if (xSemaphoreGiveRecursive(mutex_id) != pdTRUE) + + if (xSemaphoreGiveRecursive(mutex_id) != pdTRUE) { result = osErrorOS; } return result; #else - return osErrorResource; + return osErrorResource; #endif } @@ -1728,37 +1836,37 @@ osStatus osRecursiveMutexRelease (osMutexId mutex_id) * @param millisec timeout value or 0 in case of no time-out. * @retval status code that indicates the execution status of the function. */ -osStatus osRecursiveMutexWait (osMutexId mutex_id, uint32_t millisec) +osStatus osRecursiveMutexWait(osMutexId mutex_id, uint32_t millisec) { #if (configUSE_RECURSIVE_MUTEXES == 1) TickType_t ticks; - + if (mutex_id == NULL) { return osErrorParameter; } - + ticks = 0; - if (millisec == osWaitForever) + if (millisec == osWaitForever) { ticks = portMAX_DELAY; } - else if (millisec != 0) + else if (millisec != 0) { ticks = millisec / portTICK_PERIOD_MS; - if (ticks == 0) + if (ticks == 0) { ticks = 1; } } - - if (xSemaphoreTakeRecursive(mutex_id, ticks) != pdTRUE) + + if (xSemaphoreTakeRecursive(mutex_id, ticks) != pdTRUE) { return osErrorOS; } return osOK; #else - return osErrorResource; + return osErrorResource; #endif } diff --git a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h b/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h deleted file mode 100644 index e048e6cd..00000000 --- a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/deprecated_definitions.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * FreeRTOS Kernel V10.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef DEPRECATED_DEFINITIONS_H -#define DEPRECATED_DEFINITIONS_H - - -/* Each FreeRTOS port has a unique portmacro.h header file. Originally a -pre-processor definition was used to ensure the pre-processor found the correct -portmacro.h file for the port being used. That scheme was deprecated in favour -of setting the compiler's include path such that it found the correct -portmacro.h file - removing the need for the constant and allowing the -portmacro.h file to be located anywhere in relation to the port being used. The -definitions below remain in the code for backward compatibility only. New -projects should not use them. */ - -#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT - #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT - #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef GCC_MEGA_AVR - #include "../portable/GCC/ATMega323/portmacro.h" -#endif - -#ifdef IAR_MEGA_AVR - #include "../portable/IAR/ATMega323/portmacro.h" -#endif - -#ifdef MPLAB_PIC24_PORT - #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" -#endif - -#ifdef MPLAB_DSPIC_PORT - #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" -#endif - -#ifdef MPLAB_PIC18F_PORT - #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" -#endif - -#ifdef MPLAB_PIC32MX_PORT - #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" -#endif - -#ifdef _FEDPICC - #include "libFreeRTOS/Include/portmacro.h" -#endif - -#ifdef SDCC_CYGNAL - #include "../../Source/portable/SDCC/Cygnal/portmacro.h" -#endif - -#ifdef GCC_ARM7 - #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" -#endif - -#ifdef GCC_ARM7_ECLIPSE - #include "portmacro.h" -#endif - -#ifdef ROWLEY_LPC23xx - #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" -#endif - -#ifdef IAR_MSP430 - #include "..\..\Source\portable\IAR\MSP430\portmacro.h" -#endif - -#ifdef GCC_MSP430 - #include "../../Source/portable/GCC/MSP430F449/portmacro.h" -#endif - -#ifdef ROWLEY_MSP430 - #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" -#endif - -#ifdef ARM7_LPC21xx_KEIL_RVDS - #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" -#endif - -#ifdef SAM7_GCC - #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" -#endif - -#ifdef SAM7_IAR - #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" -#endif - -#ifdef SAM9XE_IAR - #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" -#endif - -#ifdef LPC2000_IAR - #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" -#endif - -#ifdef STR71X_IAR - #include "..\..\Source\portable\IAR\STR71x\portmacro.h" -#endif - -#ifdef STR75X_IAR - #include "..\..\Source\portable\IAR\STR75x\portmacro.h" -#endif - -#ifdef STR75X_GCC - #include "..\..\Source\portable\GCC\STR75x\portmacro.h" -#endif - -#ifdef STR91X_IAR - #include "..\..\Source\portable\IAR\STR91x\portmacro.h" -#endif - -#ifdef GCC_H8S - #include "../../Source/portable/GCC/H8S2329/portmacro.h" -#endif - -#ifdef GCC_AT91FR40008 - #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" -#endif - -#ifdef RVDS_ARMCM3_LM3S102 - #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3_LM3S102 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef GCC_ARMCM3 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARM_CM3 - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef IAR_ARMCM3_LM - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" -#endif - -#ifdef HCS12_CODE_WARRIOR - #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" -#endif - -#ifdef MICROBLAZE_GCC - #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" -#endif - -#ifdef TERN_EE - #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" -#endif - -#ifdef GCC_HCS12 - #include "../../Source/portable/GCC/HCS12/portmacro.h" -#endif - -#ifdef GCC_MCF5235 - #include "../../Source/portable/GCC/MCF5235/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_GCC - #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" -#endif - -#ifdef COLDFIRE_V2_CODEWARRIOR - #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" -#endif - -#ifdef GCC_PPC405 - #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" -#endif - -#ifdef GCC_PPC440 - #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" -#endif - -#ifdef _16FX_SOFTUNE - #include "..\..\Source\portable\Softune\MB96340\portmacro.h" -#endif - -#ifdef BCC_INDUSTRIAL_PC_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef BCC_FLASH_LITE_186_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); -#endif - -#ifdef __GNUC__ - #ifdef __AVR32_AVR32A__ - #include "portmacro.h" - #endif -#endif - -#ifdef __ICCAVR32__ - #ifdef __CORE__ - #if __CORE__ == __AVR32A__ - #include "portmacro.h" - #endif - #endif -#endif - -#ifdef __91467D - #include "portmacro.h" -#endif - -#ifdef __96340 - #include "portmacro.h" -#endif - - -#ifdef __IAR_V850ES_Fx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx3_L__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Jx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_V850ES_Hx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -#ifdef __IAR_78K0R_Kx3L__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" -#endif - -#endif /* DEPRECATED_DEFINITIONS_H */ - diff --git a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h b/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h index 47ceab9f..ac644e45 100644 --- a/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h +++ b/workspace/TS100/Middlewares/Third_Party/FreeRTOS/Source/include/portable.h @@ -42,58 +42,58 @@ Purely for reasons of backward compatibility the old method is still valid, but to make it clear that new projects should not use it, support for the port specific constants has been moved into the deprecated_definitions.h header file. */ -#include "deprecated_definitions.h" /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h did not result in a portmacro.h header file being included - and it should be included here. In this case the path to the correct portmacro.h header file must be set in the compiler's include path. */ #ifndef portENTER_CRITICAL - #include "portmacro.h" +#include "portmacro.h" #endif #if portBYTE_ALIGNMENT == 32 - #define portBYTE_ALIGNMENT_MASK ( 0x001f ) +#define portBYTE_ALIGNMENT_MASK (0x001f) #endif #if portBYTE_ALIGNMENT == 16 - #define portBYTE_ALIGNMENT_MASK ( 0x000f ) +#define portBYTE_ALIGNMENT_MASK (0x000f) #endif #if portBYTE_ALIGNMENT == 8 - #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#define portBYTE_ALIGNMENT_MASK (0x0007) #endif #if portBYTE_ALIGNMENT == 4 - #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#define portBYTE_ALIGNMENT_MASK (0x0003) #endif #if portBYTE_ALIGNMENT == 2 - #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#define portBYTE_ALIGNMENT_MASK (0x0001) #endif #if portBYTE_ALIGNMENT == 1 - #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#define portBYTE_ALIGNMENT_MASK (0x0000) #endif #ifndef portBYTE_ALIGNMENT_MASK - #error "Invalid portBYTE_ALIGNMENT definition" +#error "Invalid portBYTE_ALIGNMENT definition" #endif #ifndef portNUM_CONFIGURABLE_REGIONS - #define portNUM_CONFIGURABLE_REGIONS 1 +#define portNUM_CONFIGURABLE_REGIONS 1 #endif #ifndef portHAS_STACK_OVERFLOW_CHECKING - #define portHAS_STACK_OVERFLOW_CHECKING 0 +#define portHAS_STACK_OVERFLOW_CHECKING 0 #endif #ifndef portARCH_NAME - #define portARCH_NAME NULL +#define portARCH_NAME NULL #endif #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #include "mpu_wrappers.h" @@ -104,41 +104,41 @@ extern "C" { * the order that the port expects to find them. * */ -#if( portUSING_MPU_WRAPPERS == 1 ) - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; - #else - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; - #endif +#if (portUSING_MPU_WRAPPERS == 1) +#if (portHAS_STACK_OVERFLOW_CHECKING == 1) + StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged) PRIVILEGED_FUNCTION; #else - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; - #else - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; - #endif + StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged) PRIVILEGED_FUNCTION; +#endif +#else +#if (portHAS_STACK_OVERFLOW_CHECKING == 1) +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters) PRIVILEGED_FUNCTION; +#else +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) PRIVILEGED_FUNCTION; +#endif #endif -/* Used by heap_5.c to define the start address and size of each memory region + /* Used by heap_5.c to define the start address and size of each memory region that together comprise the total FreeRTOS heap space. */ -typedef struct HeapRegion -{ - uint8_t *pucStartAddress; - size_t xSizeInBytes; -} HeapRegion_t; + typedef struct HeapRegion + { + uint8_t *pucStartAddress; + size_t xSizeInBytes; + } HeapRegion_t; -/* Used to pass information about the heap out of vPortGetHeapStats(). */ -typedef struct xHeapStats -{ - size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ - size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ - size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ - size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ -} HeapStats_t; + /* Used to pass information about the heap out of vPortGetHeapStats(). */ + typedef struct xHeapStats + { + size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ + size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ + size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ + size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ + } HeapStats_t; -/* + /* * Used to define multiple heap regions for use by heap_5.c. This function * must be called before any calls to pvPortMalloc() - not creating a task, * queue, semaphore, mutex, software timer, event group, etc. will result in @@ -149,35 +149,35 @@ typedef struct xHeapStats * terminated by a HeapRegions_t structure that has a size of 0. The region * with the lowest start address must appear first in the array. */ -void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; + void vPortDefineHeapRegions(const HeapRegion_t *const pxHeapRegions) PRIVILEGED_FUNCTION; -/* + /* * Returns a HeapStats_t structure filled with information about the current * heap state. */ -void vPortGetHeapStats( HeapStats_t *pxHeapStats ); + void vPortGetHeapStats(HeapStats_t *pxHeapStats); -/* + /* * Map to the memory management routines required for the port. */ -void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; -void vPortFree( void *pv ) PRIVILEGED_FUNCTION; -void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; -size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; -size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; + void *pvPortMalloc(size_t xSize) PRIVILEGED_FUNCTION; + void vPortFree(void *pv) PRIVILEGED_FUNCTION; + void vPortInitialiseBlocks(void) PRIVILEGED_FUNCTION; + size_t xPortGetFreeHeapSize(void) PRIVILEGED_FUNCTION; + size_t xPortGetMinimumEverFreeHeapSize(void) PRIVILEGED_FUNCTION; -/* + /* * Setup the hardware ready for the scheduler to take control. This generally * sets up a tick interrupt and sets timers for the correct tick frequency. */ -BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + BaseType_t xPortStartScheduler(void) PRIVILEGED_FUNCTION; -/* + /* * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so * the hardware is left in its original condition after the scheduler stops * executing. */ -void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + void vPortEndScheduler(void) PRIVILEGED_FUNCTION; /* * The structures and methods of manipulating the MPU are contained within the @@ -186,9 +186,9 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; * Fills the xMPUSettings structure with the memory region information * contained in xRegions. */ -#if( portUSING_MPU_WRAPPERS == 1 ) +#if (portUSING_MPU_WRAPPERS == 1) struct xMEMORY_REGION; - void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; + void vPortStoreTaskMPUSettings(xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth) PRIVILEGED_FUNCTION; #endif #ifdef __cplusplus @@ -196,4 +196,3 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; #endif #endif /* PORTABLE_H */ - diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 57bdc23e..01990aed 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -13,22 +13,22 @@ * Default soldering temp is 320.0 C * Temperature the iron sleeps at - default 150.0 C */ -#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C -#define SLEEP_TEMP 150 // Default sleep temperature -#define BOOST_TEMP 420 // Default boost temp. -#define BOOST_MODE_ENABLED 1 // 0: Disable 1: Enable +#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C +#define SLEEP_TEMP 150 // Default sleep temperature +#define BOOST_TEMP 420 // Default boost temp. +#define BOOST_MODE_ENABLED 1 // 0: Disable 1: Enable /** * Blink the temperature on the cooling screen when its > 50C */ -#define COOLING_TEMP_BLINK 0 // 0: Disable 1: Enable +#define COOLING_TEMP_BLINK 0 // 0: Disable 1: Enable /** * How many seconds/minutes we wait until going to sleep/shutdown. * Values -> SLEEP_TIME * 10; i.e. 5*10 = 50 Seconds! */ -#define SLEEP_TIME 5 // x10 Seconds -#define SHUTDOWN_TIME 10 // Minutes +#define SLEEP_TIME 5 // x10 Seconds +#define SHUTDOWN_TIME 10 // Minutes /** * Auto start off for safety. @@ -38,22 +38,22 @@ * 2 - Sleep Temperature * 3 - Sleep Off Temperature */ -#define AUTO_START_MODE 0 // Default to none +#define AUTO_START_MODE 0 // Default to none /** * OLED Orientation * */ -#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right -#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperatur change +#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right +#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperatur change /** * Temp change settings */ -#define TEMP_CHANGE_SHORT_STEP 1 // Default temp change short step +1 -#define TEMP_CHANGE_LONG_STEP 10 // Default temp change long step +10 -#define TEMP_CHANGE_SHORT_STEP_MAX 50 // Temp change short step MAX value -#define TEMP_CHANGE_LONG_STEP_MAX 100 // Temp change long step MAX value +#define TEMP_CHANGE_SHORT_STEP 1 // Default temp change short step +1 +#define TEMP_CHANGE_LONG_STEP 10 // Default temp change long step +10 +#define TEMP_CHANGE_SHORT_STEP_MAX 50 // Temp change short step MAX value +#define TEMP_CHANGE_LONG_STEP_MAX 100 // Temp change long step MAX value /* Power pulse for keeping power banks awake*/ #define POWER_PULSE_INCREMENT 1 @@ -68,70 +68,83 @@ * OLED Orientation Sensitivity on Automatic mode! * Motion Sensitivity <0=Off 1=Least Sensitive 9=Most Sensitive> */ -#define SENSITIVITY 7 // Default 7 +#define SENSITIVITY 7 // Default 7 /** * Detailed soldering screen * Detailed idle screen (off for first time users) */ -#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 -#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 +#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 +#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 -#define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) -#define TEMPERATURE_INF 0 // default to 0 -#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow -#define POWER_LIMIT_ENABLE 0 // 0: Disable 1: Enable - Default disabled power limit +#define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) +#define TEMPERATURE_INF 0 // default to 0 +#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow +#define POWER_LIMIT_ENABLE 0 // 0: Disable 1: Enable - Default disabled power limit -#define TIP_GAIN 210 // 21 uV/C * 10, uV per deg C constant of the tip, Tip uV * 10 / coeff = tip temp +#define TIP_GAIN 210 // 21 uV/C * 10, uV per deg C constant of the tip, Tip uV * 10 / coeff = tip temp -#define OP_AMP_Rf_TS100 750*1000 // 750 Kilo-ohms -> From schematic, R1 -#define OP_AMP_Rin_TS100 2370 // 2.37 Kilo-ohms -> From schematic, R2 +#define OP_AMP_Rf_TS100 750 * 1000 // 750 Kilo-ohms -> From schematic, R1 +#define OP_AMP_Rin_TS100 2370 // 2.37 Kilo-ohms -> From schematic, R2 -#define OP_AMP_GAIN_STAGE_TS100 (1+(OP_AMP_Rf_TS100/OP_AMP_Rin_TS100)) +#define OP_AMP_GAIN_STAGE_TS100 (1 + (OP_AMP_Rf_TS100 / OP_AMP_Rin_TS100)) -#define OP_AMP_Rf_TS80 180*1000 // 180 Kilo-ohms -> From schematic, R6 -#define OP_AMP_Rin_TS80 2000 // 2.0 Kilo-ohms -> From schematic, R3 +#define OP_AMP_Rf_TS80 180 * 1000 // 180 Kilo-ohms -> From schematic, R6 +#define OP_AMP_Rin_TS80 2000 // 2.0 Kilo-ohms -> From schematic, R3 -#define OP_AMP_GAIN_STAGE_TS80 (1+(OP_AMP_Rf_TS80/OP_AMP_Rin_TS80)) +#define OP_AMP_GAIN_STAGE_TS80 (1 + (OP_AMP_Rf_TS80 / OP_AMP_Rin_TS80)) //Deriving the Voltage div: // Vin_max = (3.3*(r1+r2))/(r2) //vdiv = (32768*4)/(vin_max*10) #ifdef MODEL_TS100 - #define VOLTAGE_DIV 467 // 467 - Default divider from schematic - #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV - #define PID_POWER_LIMIT 70 // Sets the max pwm power limit - #define POWER_LIMIT 30 // 30 watts default limit - #define MAX_POWER_LIMIT 65 // - #define POWER_LIMIT_STEPS 5 // - #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 +#define VOLTAGE_DIV 467 // 467 - Default divider from schematic +#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV +#define PID_POWER_LIMIT 70 // Sets the max pwm power limit +#define POWER_LIMIT 30 // 30 watts default limit +#define MAX_POWER_LIMIT 65 // +#define POWER_LIMIT_STEPS 5 // +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 +#endif + +#ifdef MODEL_Pinecil +#define VOLTAGE_DIV 467 // 467 - Default divider from schematic +#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV +#define PID_POWER_LIMIT 70 // Sets the max pwm power limit +#define POWER_LIMIT 30 // 30 watts default limit +#define MAX_POWER_LIMIT 65 // +#define POWER_LIMIT_STEPS 5 // +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 #endif #ifdef MODEL_TS80 -#define VOLTAGE_DIV 780 // Default divider from schematic -#define PID_POWER_LIMIT 24 // Sets the max pwm power limit -#define CALIBRATION_OFFSET 900 // the adc offset in uV -#define POWER_LIMIT 24 // 24 watts default power limit -#define MAX_POWER_LIMIT 30 // -#define POWER_LIMIT_STEPS 2 -#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#define VOLTAGE_DIV 780 // Default divider from schematic +#define PID_POWER_LIMIT 24 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 24 // 24 watts default power limit +#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT_STEPS 2 +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 #endif #ifdef MODEL_TS80P -#define VOLTAGE_DIV 650 // Default for TS80P with slightly different resistors -#define PID_POWER_LIMIT 35 // Sets the max pwm power limit -#define CALIBRATION_OFFSET 900 // the adc offset in uV -#define POWER_LIMIT 30 // 30 watts default power limit -#define MAX_POWER_LIMIT 35 // -#define POWER_LIMIT_STEPS 2 -#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#define VOLTAGE_DIV 650 // Default for TS80P with slightly different resistors +#define PID_POWER_LIMIT 35 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 30 // 30 watts default power limit +#define MAX_POWER_LIMIT 35 // +#define POWER_LIMIT_STEPS 2 +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 #endif - - #ifdef MODEL_TS100 -const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second +const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second +const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 +#endif + +#ifdef MODEL_Pinecil +const int32_t tipMass = 45; // X10 watts to raise 1 deg C in 1 second const uint8_t tipResistance = 85; //x10 ohms, 8.5 typical for ts100, 4.5 typical for ts80 #endif From 275708ee25c299a8371fa4a6c600722f38a019e3 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Aug 2020 19:14:15 +1000 Subject: [PATCH 06/72] Mimimum Buildable --- workspace/TS100/Core/BSP/BSP_Common.c | 1 + workspace/TS100/Core/BSP/Miniware/BSP.cpp | 249 +++++++------- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 116 ++++++- .../TS100/Core/BSP/Pine64/Model_Config.h | 2 +- workspace/TS100/Core/BSP/Pine64/Power.cpp | 41 ++- workspace/TS100/Core/BSP/Pine64/fusb302b.cpp | 303 ++++++++++++++++++ workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 4 + workspace/TS100/build.sh | 2 +- 8 files changed, 590 insertions(+), 128 deletions(-) create mode 100644 workspace/TS100/Core/BSP/BSP_Common.c create mode 100644 workspace/TS100/Core/BSP/Pine64/fusb302b.cpp diff --git a/workspace/TS100/Core/BSP/BSP_Common.c b/workspace/TS100/Core/BSP/BSP_Common.c new file mode 100644 index 00000000..67a76d18 --- /dev/null +++ b/workspace/TS100/Core/BSP/BSP_Common.c @@ -0,0 +1 @@ +#include "BSP.h" diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index a2afb4f3..1b5ed75f 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -13,87 +13,92 @@ volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; //2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = { { 0 }, 0, 0 }; -void resetWatchdog() { +history rawTempFilter = {{0}, 0, 0}; +void resetWatchdog() +{ HAL_IWDG_Refresh(&hiwdg); } #ifdef TEMP_NTC //Lookup table for the NTC //Stored as ADCReading,Temp in degC static const uint16_t NTCHandleLookup[] = { -//ADC Reading , Temp in C - 29189, 0, // - 29014, 1, // - 28832, 2, // - 28644, 3, // - 28450, 4, // - 28249, 5, // - 28042, 6, // - 27828, 7, // - 27607, 8, // - 27380, 9, // - 27146, 10, // - 26906, 11, // - 26660, 12, // - 26407, 13, // - 26147, 14, // - 25882, 15, // - 25610, 16, // - 25332, 17, // - 25049, 18, // - 24759, 19, // - 24465, 20, // - 24164, 21, // - 23859, 22, // - 23549, 23, // - 23234, 24, // - 22915, 25, // - 22591, 26, // - 22264, 27, // - 21933, 28, // - 21599, 29, // -// 21261, 30, // -// 20921, 31, // -// 20579, 32, // -// 20234, 33, // -// 19888, 34, // -// 19541, 35, // -// 19192, 36, // -// 18843, 37, // -// 18493, 38, // -// 18143, 39, // -// 17793, 40, // -// 17444, 41, // -// 17096, 42, // -// 16750, 43, // -// 16404, 44, // -// 16061, 45, // -// 15719, 46, // -// 15380, 47, // -// 15044, 48, // -// 14710, 49, // -// 14380, 50, // -// 14053, 51, // -// 13729, 52, // -// 13410, 53, // -// 13094, 54, // -// 12782, 55, // -// 12475, 56, // -// 12172, 57, // -// 11874, 58, // -// 11580, 59, // -// 11292, 60, // - }; + //ADC Reading , Temp in C + 29189, 0, // + 29014, 1, // + 28832, 2, // + 28644, 3, // + 28450, 4, // + 28249, 5, // + 28042, 6, // + 27828, 7, // + 27607, 8, // + 27380, 9, // + 27146, 10, // + 26906, 11, // + 26660, 12, // + 26407, 13, // + 26147, 14, // + 25882, 15, // + 25610, 16, // + 25332, 17, // + 25049, 18, // + 24759, 19, // + 24465, 20, // + 24164, 21, // + 23859, 22, // + 23549, 23, // + 23234, 24, // + 22915, 25, // + 22591, 26, // + 22264, 27, // + 21933, 28, // + 21599, 29, // + // 21261, 30, // + // 20921, 31, // + // 20579, 32, // + // 20234, 33, // + // 19888, 34, // + // 19541, 35, // + // 19192, 36, // + // 18843, 37, // + // 18493, 38, // + // 18143, 39, // + // 17793, 40, // + // 17444, 41, // + // 17096, 42, // + // 16750, 43, // + // 16404, 44, // + // 16061, 45, // + // 15719, 46, // + // 15380, 47, // + // 15044, 48, // + // 14710, 49, // + // 14380, 50, // + // 14053, 51, // + // 13729, 52, // + // 13410, 53, // + // 13094, 54, // + // 12782, 55, // + // 12475, 56, // + // 12172, 57, // + // 11874, 58, // + // 11580, 59, // + // 11292, 60, // +}; #endif -uint16_t getHandleTemperature() { + +uint16_t getHandleTemperature() +{ #ifdef TEMP_NTC //TS80P uses 100k NTC resistors instead //NTCG104EF104FT1X from TDK //For now not doing interpolation int32_t result = getADC(0); for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); - i++) { - if (result > NTCHandleLookup[(i * 2) + 0]) { + i++) + { + if (result > NTCHandleLookup[(i * 2) + 0]) + { return NTCHandleLookup[(i * 2) + 1] * 10; } } @@ -108,7 +113,7 @@ uint16_t getHandleTemperature() { // (4964.8 counts) // int32_t result = getADC(0); - result -= 4965; // remove 0.5V offset + result -= 4965; // remove 0.5V offset // 10mV per C // 99.29 counts per Deg C above 0C result *= 100; @@ -117,12 +122,13 @@ uint16_t getHandleTemperature() { #endif } -uint16_t getTipInstantTemperature() { - uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits +uint16_t getTipInstantTemperature() +{ + uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t readings[8]; -//Looking to reject the highest outlier readings. -//As on some hardware these samples can run into the op-amp recovery time -//Once this time is up the signal stabilises quickly, so no need to reject minimums + //Looking to reject the highest outlier readings. + //As on some hardware these samples can run into the op-amp recovery time + //Once this time is up the signal stabilises quickly, so no need to reject minimums readings[0] = hadc1.Instance->JDR1; readings[1] = hadc1.Instance->JDR2; readings[2] = hadc1.Instance->JDR3; @@ -132,23 +138,29 @@ uint16_t getTipInstantTemperature() { readings[6] = hadc2.Instance->JDR3; readings[7] = hadc2.Instance->JDR4; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) + { sum += readings[i]; } - return sum; // 8x over sample + return sum; // 8x over sample } -uint16_t getTipRawTemp(uint8_t refresh) { - if (refresh) { +uint16_t getTipRawTemp(uint8_t refresh) +{ + if (refresh) + { uint16_t lastSample = getTipInstantTemperature(); rawTempFilter.update(lastSample); return lastSample; - } else { + } + else + { return rawTempFilter.average(); } } -uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) +{ // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN // Therefore we can divide down from there // Multiplying ADC max by 4 for additional calibration options, @@ -162,12 +174,14 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; static uint8_t index = 0; - if (preFillneeded) { + if (preFillneeded) + { for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) samples[i] = getADC(1); preFillneeded--; } - if (sample) { + if (sample) + { samples[index] = getADC(1); index = (index + 1) % BATTFILTERDEPTH; } @@ -177,13 +191,15 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { sum += samples[i]; sum /= BATTFILTERDEPTH; - if (divisor == 0) { + if (divisor == 0) + { divisor = 1; } return sum * 4 / divisor; } -void setTipPWM(uint8_t pulse) { +void setTipPWM(uint8_t pulse) +{ PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. @@ -193,9 +209,11 @@ void setTipPWM(uint8_t pulse) { // These are called by the HAL after the corresponding events from the system // timers. -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { -// Period has elapsed - if (htim->Instance == TIM2) { +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + // Period has elapsed + if (htim->Instance == TIM2) + { // we want to turn on the output again PWMSafetyTimer--; // We decrement this safety value so that lockups in the @@ -204,35 +222,43 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { // While we could assume this could never happen, its a small price for // increased safety htim2.Instance->CCR4 = pendingPWM; - if (htim2.Instance->CCR4 && PWMSafetyTimer) { + if (htim2.Instance->CCR4 && PWMSafetyTimer) + { HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); - } else { + } + else + { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } - } else if (htim->Instance == TIM1) { + } + else if (htim->Instance == TIM1) + { // STM uses this for internal functions as a counter for timeouts HAL_IncTick(); } } -void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { -// This was a when the PWM for the output has timed out - if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) { +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) +{ + // This was a when the PWM for the output has timed out + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) + { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } } -void unstick_I2C() { +void unstick_I2C() +{ GPIO_InitTypeDef GPIO_InitStruct; int timeout = 100; int timeout_cnt = 0; -// 1. Clear PE bit. + // 1. Clear PE bit. hi2c1.Instance->CR1 &= ~(0x0001); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ -// 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). + // 2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR). GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -245,7 +271,8 @@ void unstick_I2C() { HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { + while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) + { //Move clock to release I2C HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); asm("nop"); @@ -259,7 +286,7 @@ void unstick_I2C() { return; } -// 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. + // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain. GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; @@ -273,37 +300,39 @@ void unstick_I2C() { HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); -// 13. Set SWRST bit in I2Cx_CR1 register. + // 13. Set SWRST bit in I2Cx_CR1 register. hi2c1.Instance->CR1 |= 0x8000; asm("nop"); -// 14. Clear SWRST bit in I2Cx_CR1 register. + // 14. Clear SWRST bit in I2Cx_CR1 register. hi2c1.Instance->CR1 &= ~0x8000; asm("nop"); -// 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register + // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register hi2c1.Instance->CR1 |= 0x0001; -// Call initialization function. + // Call initialization function. HAL_I2C_Init(&hi2c1); } -uint8_t getButtonA() { - return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? - 1 : 0; +uint8_t getButtonA() +{ + return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? 1 : 0; } -uint8_t getButtonB() { - return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? - 1 : 0; +uint8_t getButtonB() +{ + return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? 1 : 0; } -void reboot() { +void reboot() +{ NVIC_SystemReset(); } -void delay_ms(uint16_t count) { +void delay_ms(uint16_t count) +{ HAL_Delay(count); } diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 0a31b154..9517a596 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -10,14 +10,20 @@ #include "systick.h" #include -void resetWatchdog() { +//2 second filter (ADC is PID_TIM_HZ Hz) +history rawTempFilter = {{0}, 0, 0}; + +void resetWatchdog() +{ //TODO } -uint16_t getTipInstantTemperature() { +uint16_t getTipInstantTemperature() +{ uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { sum += adc_inserted_data_read(ADC0, i); sum += adc_inserted_data_read(ADC1, i); } @@ -28,23 +34,113 @@ uint16_t getTipInstantTemperature() { // TODO // Handle callback of the PWM modulator to enable / disable the output PWM -void unstick_I2C() { +uint16_t getTipRawTemp(uint8_t refresh) +{ + if (refresh) + { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } + else + { + return rawTempFilter.average(); + } +} +void unstick_I2C() +{ // TODO } -uint8_t getButtonA() { - // TODO +uint8_t getButtonA() +{ return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == RESET) ? 1 : 0; } -uint8_t getButtonB() { - // TODO +uint8_t getButtonB() +{ return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == RESET) ? 1 : 0; } -void reboot() { +void reboot() +{ // TODO - for (;;) { + for (;;) + { } } void delay_ms(uint16_t count) { delay_1ms(count); } + +uint16_t getHandleTemperature() +{ +#ifdef TEMP_NTC + //TS80P uses 100k NTC resistors instead + //NTCG104EF104FT1X from TDK + //For now not doing interpolation + int32_t result = getADC(0); + for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); + i++) + { + if (result > NTCHandleLookup[(i * 2) + 0]) + { + return NTCHandleLookup[(i * 2) + 1] * 10; + } + } + return 0; +#endif +#ifdef TEMP_TMP36 + // We return the current handle temperature in X10 C + // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for + // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = + // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 + // mV per count So we need to subtract an offset of 0.5V to center on 0C + // (4964.8 counts) + // + int32_t result = getADC(0); + result -= 4965; // remove 0.5V offset + // 10mV per C + // 99.29 counts per Deg C above 0C + result *= 100; + result /= 993; + return result; +#endif +} + +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) +{ +// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN +// Therefore we can divide down from there +// Multiplying ADC max by 4 for additional calibration options, +// ideal term is 467 +#ifdef MODEL_TS100 +#define BATTFILTERDEPTH 32 +#else +#define BATTFILTERDEPTH 8 + +#endif + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) + { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) + { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; + + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; + + sum /= BATTFILTERDEPTH; + if (divisor == 0) + { + divisor = 1; + } + return sum * 4 / divisor; +} \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 6d274997..3424b60f 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -21,7 +21,7 @@ #define ACCEL_LIS #define TEMP_TMP36 #define POW_QC -#define POW_PD +// #define POW_PD #endif #endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/Power.cpp b/workspace/TS100/Core/BSP/Pine64/Power.cpp index 522802a3..ae6d8520 100644 --- a/workspace/TS100/Core/BSP/Pine64/Power.cpp +++ b/workspace/TS100/Core/BSP/Pine64/Power.cpp @@ -2,10 +2,39 @@ #include "BSP_Power.h" #include "QC3.h" #include "Settings.h" -void power_probe() { - //TODO -- Check for PD -} +#include "Pins.h" +#include "fusbpd.h" +#include "Model_Config.h" +#include "policy_engine.h" +#include "int_n.h" +bool FUSB302_present = false; -void power_check() { - //TODO -- Checks for PD? -} \ No newline at end of file +void power_check() +{ +#ifdef POW_PD + if (FUSB302_present) + { + //Cant start QC until either PD works or fails + if (PolicyEngine::setupCompleteOrTimedOut() == false) + { + return; + } + if (PolicyEngine::pdHasNegotiated()) + { + return; + } + } +#endif +#ifdef POW_QC + QC_resync(); +#endif +} +uint8_t usb_pd_detect() +{ +#ifdef POW_PD + FUSB302_present = fusb302_detect(); + + return FUSB302_present; +#endif + return false; +} diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp new file mode 100644 index 00000000..2304ecf2 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -0,0 +1,303 @@ +/* + * PD Buddy Firmware Library - USB Power Delivery for everyone + * Copyright 2017-2018 Clayton G. Hobbs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "Model_Config.h" +#ifdef POW_PD +#include "BSP.h" +#include "fusb302b.h" +#include "I2C_Wrapper.hpp" +#include +#include "int_n.h" +/* + * Read a single byte from the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address from which to read + * + * Returns the value read from addr. + */ +static uint8_t fusb_read_byte(uint8_t addr) +{ + uint8_t data[1]; + if (!FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, (uint8_t *)data, 1)) + { + return 0; + } + return data[0]; +} + +/* + * Read multiple bytes from the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address from which to read + * size: The number of bytes to read + * buf: The buffer into which data will be read + */ +static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) +{ + return FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, buf, size); +} + +/* + * Write a single byte to the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address to which we will write + * byte: The value to write + */ +static bool fusb_write_byte(uint8_t addr, uint8_t byte) +{ + return FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t *)&byte, 1); +} + +/* + * Write multiple bytes to the FUSB302B + * + * cfg: The FUSB302B to communicate with + * addr: The memory address to which we will write + * size: The number of bytes to write + * buf: The buffer to write + */ +static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) +{ + return FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, buf, size); +} + +void fusb_send_message(const union pd_msg *msg) +{ + if (!FRToSI2C::lock2()) + { + return; + } + /* Token sequences for the FUSB302B */ + static uint8_t sop_seq[5] = { + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP2, + FUSB_FIFO_TX_PACKSYM}; + static const uint8_t eop_seq[4] = { + FUSB_FIFO_TX_JAM_CRC, + FUSB_FIFO_TX_EOP, + FUSB_FIFO_TX_TXOFF, + FUSB_FIFO_TX_TXON}; + + /* Take the I2C2 mutex now so there can't be a race condition on sop_seq */ + /* Get the length of the message: a two-octet header plus NUMOBJ four-octet + * data objects */ + uint8_t msg_len = 2 + 4 * PD_NUMOBJ_GET(msg); + + /* Set the number of bytes to be transmitted in the packet */ + sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len; + + /* Write all three parts of the message to the TX FIFO */ + fusb_write_buf(FUSB_FIFOS, 5, sop_seq); + fusb_write_buf(FUSB_FIFOS, msg_len, msg->bytes); + fusb_write_buf(FUSB_FIFOS, 4, eop_seq); + + FRToSI2C::unlock2(); +} + +uint8_t fusb_read_message(union pd_msg *msg) +{ + if (!FRToSI2C::lock2()) + { + asm("bkpt"); + } + static uint8_t garbage[4]; + uint8_t numobj; + + // Read the header. If its not a SOP we dont actually want it at all + // But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck + fusb_read_byte(FUSB_FIFOS); + /* Read the message header into msg */ + fusb_read_buf(FUSB_FIFOS, 2, msg->bytes); + /* Get the number of data objects */ + numobj = PD_NUMOBJ_GET(msg); + /* If there is at least one data object, read the data objects */ + if (numobj > 0) + { + fusb_read_buf(FUSB_FIFOS, numobj * 4, msg->bytes + 2); + } + /* Throw the CRC32 in the garbage, since the PHY already checked it. */ + fusb_read_buf(FUSB_FIFOS, 4, garbage); + + FRToSI2C::unlock2(); + return 0; +} + +void fusb_send_hardrst() +{ + + if (!FRToSI2C::lock2()) + { + return; + } + /* Send a hard reset */ + fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); + + FRToSI2C::unlock2(); +} + +void fusb_setup() +{ + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_NVIC_SetPriority(EXTI9_5_IRQn, 12, 0); + HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); + + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::lock2()) + { + return; + } + } + /* Fully reset the FUSB302B */ + fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES); + osDelay(2); + if (!fusb_read_id()) + { + return; + } + + /* Turn on all power */ + fusb_write_byte(FUSB_POWER, 0x0F); + + /* Set interrupt masks */ + //Setting to 0 so interrupts are allowed + fusb_write_byte(FUSB_MASK1, 0x00); + fusb_write_byte(FUSB_MASKA, 0x00); + fusb_write_byte(FUSB_MASKB, 0x00); + fusb_write_byte(FUSB_CONTROL0, 0b11 << 2); + + /* Enable automatic retransmission */ + fusb_write_byte(FUSB_CONTROL3, 0x07); + //set defaults + fusb_write_byte(FUSB_CONTROL2, 0x00); + /* Flush the RX buffer */ + fusb_write_byte(FUSB_CONTROL1, + FUSB_CONTROL1_RX_FLUSH); + + /* Measure CC1 */ + fusb_write_byte(FUSB_SWITCHES0, 0x07); + osDelay(10); + uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + + /* Measure CC2 */ + fusb_write_byte(FUSB_SWITCHES0, 0x0B); + osDelay(10); + uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + + /* Select the correct CC line for BMC signaling; also enable AUTO_CRC */ + if (cc1 > cc2) + { + fusb_write_byte(FUSB_SWITCHES1, 0x25); + fusb_write_byte(FUSB_SWITCHES0, 0x07); + } + else + { + fusb_write_byte(FUSB_SWITCHES1, 0x26); + fusb_write_byte(FUSB_SWITCHES0, 0x0B); + } + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + FRToSI2C::unlock2(); + } + fusb_reset(); +} + +void fusb_get_status(union fusb_status *status) +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::lock2()) + { + return; + } + } + + /* Read the interrupt and status flags into status */ + fusb_read_buf(FUSB_STATUS0A, 7, status->bytes); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + FRToSI2C::unlock2(); + } +} + +enum fusb_typec_current fusb_get_typec_current() +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::lock2()) + { + return fusb_tcc_none; + } + } + /* Read the BC_LVL into a variable */ + enum fusb_typec_current bc_lvl = (enum fusb_typec_current)(fusb_read_byte( + FUSB_STATUS0) & + FUSB_STATUS0_BC_LVL); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + FRToSI2C::unlock2(); + } + return bc_lvl; +} + +void fusb_reset() +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + if (!FRToSI2C::lock2()) + { + return; + } + } + + /* Flush the TX buffer */ + fusb_write_byte(FUSB_CONTROL0, 0x44); + /* Flush the RX buffer */ + fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + /* Reset the PD logic */ + // fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) + { + FRToSI2C::unlock2(); + } +} + +bool fusb_read_id() +{ + //Return true if read of the revision ID is sane + uint8_t version = 0; + fusb_read_buf(FUSB_DEVICE_ID, 1, &version); + if (version == 0 || version == 0xFF) + return false; + return true; +} +uint8_t fusb302_detect() +{ + //Probe the I2C bus for its address + return FRToSI2C::probe(FUSB302B_ADDR); +} + +#endif diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 224b7d41..caf51e19 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -48,6 +48,10 @@ public: static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); + //These are public locks that let code lock the bus for back-to-back operations + static bool lock2(); + static void unlock2(); + private: static bool lock(); static void unlock(); diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 068d7f20..29260de8 100755 --- a/workspace/TS100/build.sh +++ b/workspace/TS100/build.sh @@ -6,7 +6,7 @@ TRANSLATION_SCRIPT="make_translation.py" # AVAILABLE_LANGUAGES will be calculating according to json files in $TRANSLATION_DIR AVAILABLE_LANGUAGES=() BUILD_LANGUAGES=() -AVAILABLE_MODELS=("TS100" "TS80" "TS80P") +AVAILABLE_MODELS=("TS100" "TS80" "TS80P" "Pinecil") BUILD_MODELS=() usage() { From 3f6819287df4a746213731a0fe221e4cddf409a8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 18 Aug 2020 19:31:25 +1000 Subject: [PATCH 07/72] Fix TS80P build --- .github/workflows/{ccpp.yml => pr.yml} | 8 +++----- .github/workflows/push.yml | 22 ++++++++++++++++++++++ workspace/TS100/Makefile | 6 +++--- 3 files changed, 28 insertions(+), 8 deletions(-) rename .github/workflows/{ccpp.yml => pr.yml} (84%) create mode 100644 .github/workflows/push.yml diff --git a/.github/workflows/ccpp.yml b/.github/workflows/pr.yml similarity index 84% rename from .github/workflows/ccpp.yml rename to .github/workflows/pr.yml index a13fc675..ab5a00c1 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/pr.yml @@ -1,12 +1,10 @@ -name: C/C++ CI +name: CI PR -on: [pull_request, push] +on: [pull_request] jobs: build: - - runs-on: ubuntu-latest - + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: chmod diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000..d4a34454 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,22 @@ +name: CI Push + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: chmod + run: chmod +x build.sh + - name: translation + run: | + cd Translation\ Editor + python3 make_translation.py + - name: make + run: ./build.sh -l EN + - name: Archive production artifacts + uses: actions/upload-artifact@v1 + with: + name: compiled + path: ci/artefacts diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 75dfc3a0..f3eaf5d8 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -35,7 +35,7 @@ INC_PD_DRIVERS_DIR = ./Core/Drivers/FUSB302 SOURCE_MIDDLEWARES_DIR = ./Middlewares # Device dependent settings -ifeq ($(model),$(filter $(model),TS100 TS80)) +ifeq ($(model),$(filter $(model),TS100 TS80 TS80P)) $(info Building for Miniware ) DEVICE_INCLUDES = -I$(MINIWARE_INC_DIR) \ -I$(INC_CMSIS_DEVICE)\ @@ -116,7 +116,7 @@ LIBS= COMPILER=gcc # arm-none-eabi is the general ARM compiler, #riscv-none-embed- is the riscv compiler -ifeq ($(model),$(filter $(model),TS100 TS80)) +ifeq ($(model),$(filter $(model),TS100 TS80 TS80P)) COMPILER_PREFIX=arm-none-eabi endif ifeq ($(model),Pinecil) @@ -137,7 +137,7 @@ ifeq ($(model),Pinecil) AS=$(COMPILER_PREFIX)-gcc -x assembler-with-cpp endif # compiler flags --------------------------------------------------------------- -ifeq ($(model),$(filter $(model),TS100 TS80)) +ifeq ($(model),$(filter $(model),TS100 TS80 TS80P)) CPUFLAGS= -mthumb \ -mcpu=cortex-m3 \ -mfloat-abi=soft From b4c8fc2aab3d3ddca72eefa37de7b4b14671a67d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 17 Sep 2020 18:37:57 +1000 Subject: [PATCH 08/72] Update configs for newer pinout --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 118 +------ workspace/TS100/Core/BSP/Pine64/BSP_PD.c | 22 ++ .../TS100/Core/BSP/Pine64/FreeRTOSConfig.h | 2 +- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 287 ++++++++---------- .../TS100/Core/BSP/Pine64/Model_Config.h | 51 ++-- workspace/TS100/Core/BSP/Pine64/N200/port.c | 192 ++++++------ .../TS100/Core/BSP/Pine64/N200/portmacro.h | 152 +++++----- workspace/TS100/Core/BSP/Pine64/NOTES.md | 22 +- workspace/TS100/Core/BSP/Pine64/Pins.h | 36 +-- workspace/TS100/Core/BSP/Pine64/Power.cpp | 36 +-- workspace/TS100/Core/BSP/Pine64/Setup.c | 8 +- .../BSP/Pine64/Vendor/Lib/GD32VF103xB.lds | 176 +++++++++++ workspace/TS100/Core/BSP/Pine64/fusb302b.cpp | 201 +++++------- workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 7 +- workspace/TS100/Core/BSP/Pine64/preRTOS.cpp | 2 +- 15 files changed, 668 insertions(+), 644 deletions(-) create mode 100644 workspace/TS100/Core/BSP/Pine64/BSP_PD.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 9517a596..13bb458d 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -10,20 +10,14 @@ #include "systick.h" #include -//2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = {{0}, 0, 0}; - -void resetWatchdog() -{ +void resetWatchdog() { //TODO } -uint16_t getTipInstantTemperature() -{ +uint16_t getTipInstantTemperature() { uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits - for (int i = 0; i < 4; i++) - { + for (int i = 0; i < 4; i++) { sum += adc_inserted_data_read(ADC0, i); sum += adc_inserted_data_read(ADC1, i); } @@ -34,113 +28,21 @@ uint16_t getTipInstantTemperature() // TODO // Handle callback of the PWM modulator to enable / disable the output PWM -uint16_t getTipRawTemp(uint8_t refresh) -{ - if (refresh) - { - uint16_t lastSample = getTipInstantTemperature(); - rawTempFilter.update(lastSample); - return lastSample; - } - else - { - return rawTempFilter.average(); - } -} -void unstick_I2C() -{ +void unstick_I2C() { // TODO } -uint8_t getButtonA() -{ - return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == RESET) ? 1 : 0; +uint8_t getButtonA() { + return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; } -uint8_t getButtonB() -{ - return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == RESET) ? 1 : 0; +uint8_t getButtonB() { + return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; } -void reboot() -{ +void reboot() { // TODO - for (;;) - { + for (;;) { } } void delay_ms(uint16_t count) { delay_1ms(count); } - -uint16_t getHandleTemperature() -{ -#ifdef TEMP_NTC - //TS80P uses 100k NTC resistors instead - //NTCG104EF104FT1X from TDK - //For now not doing interpolation - int32_t result = getADC(0); - for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); - i++) - { - if (result > NTCHandleLookup[(i * 2) + 0]) - { - return NTCHandleLookup[(i * 2) + 1] * 10; - } - } - return 0; -#endif -#ifdef TEMP_TMP36 - // We return the current handle temperature in X10 C - // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for - // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = - // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 - // mV per count So we need to subtract an offset of 0.5V to center on 0C - // (4964.8 counts) - // - int32_t result = getADC(0); - result -= 4965; // remove 0.5V offset - // 10mV per C - // 99.29 counts per Deg C above 0C - result *= 100; - result /= 993; - return result; -#endif -} - -uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) -{ -// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN -// Therefore we can divide down from there -// Multiplying ADC max by 4 for additional calibration options, -// ideal term is 467 -#ifdef MODEL_TS100 -#define BATTFILTERDEPTH 32 -#else -#define BATTFILTERDEPTH 8 - -#endif - static uint8_t preFillneeded = 10; - static uint32_t samples[BATTFILTERDEPTH]; - static uint8_t index = 0; - if (preFillneeded) - { - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - samples[i] = getADC(1); - preFillneeded--; - } - if (sample) - { - samples[index] = getADC(1); - index = (index + 1) % BATTFILTERDEPTH; - } - uint32_t sum = 0; - - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - sum += samples[i]; - - sum /= BATTFILTERDEPTH; - if (divisor == 0) - { - divisor = 1; - } - return sum * 4 / divisor; -} \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/BSP_PD.c b/workspace/TS100/Core/BSP/Pine64/BSP_PD.c new file mode 100644 index 00000000..0b3c2af9 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/BSP_PD.c @@ -0,0 +1,22 @@ +/* + * BSP_PD.c + * + * Created on: 21 Jul 2020 + * Author: Ralim + */ + +#include "BSP_PD.h" +#include "Model_Config.h" +#ifdef POW_PD +/* + * An array of all of the desired voltages & minimum currents in preferred order + */ +const uint16_t USB_PD_Desired_Levels[] = { +//mV desired input, mA minimum required current + 12000, 2400, //12V @ 2.4A + 9000, 2000, //9V @ 2A + 5000, 100, //5V @ whatever + + }; +const uint8_t USB_PD_Desired_Levels_Len = 3; +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h index d1e9b3fd..72625f02 100644 --- a/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h +++ b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h @@ -14,7 +14,7 @@ extern uint32_t SystemCoreClock; #define configUSE_TICKLESS_IDLE 0 #define configCPU_CLOCK_HZ ((uint32_t)SystemCoreClock) #define configRTC_CLOCK_HZ ((uint32_t)TIMER_FREQ) -#define configTICK_RATE_HZ ((TickType_t)100) +#define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES (4) //0 - 3 å…±6等级,idle独å� 0,Tmr_svc独å� 3 #define configMINIMAL_STACK_SIZE ((unsigned short)128) #define configMAX_TASK_NAME_LEN 24 diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 73f94629..6d62cee2 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -7,13 +7,13 @@ #include "BSP.h" #include "Setup.h" #include -#define I2CUSESDMA SemaphoreHandle_t FRToSI2C::I2CSemaphore; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; +SemaphoreHandle_t FRToSI2C::I2CSemaphore2; +StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2; #define FLAG_TIMEOUT 1000 -void FRToSI2C::CpltCallback() -{ +void FRToSI2C::CpltCallback() { //TODO } @@ -21,31 +21,28 @@ void FRToSI2C::CpltCallback() * * @param obj The I2C object */ -int i2c_start() -{ +int i2c_start() { int timeout; /* clear I2C_FLAG_AERR Flag */ i2c_flag_clear(I2C0, I2C_FLAG_AERR); /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { - return (int)-1; + return (int) -1; } } /* ensure the i2c has been stopped */ - timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) - { - if ((timeout--) == 0) - { - return (int)-1; + timeout = FLAG_TIMEOUT + ; + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { + if ((timeout--) == 0) { + return (int) -1; } } @@ -53,34 +50,30 @@ int i2c_start() i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) - { - if ((timeout--) == 0) - { - return (int)-1; + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { + return (int) -1; } } - return (int)0; + return (int) 0; } /** Send STOP command * * @param obj The I2C object */ -int i2c_stop() -{ +int i2c_stop() { /* generate a STOP condition */ i2c_stop_on_bus(I2C0); /* wait for STOP bit reset */ int timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) - { - if ((timeout--) == 0) - { + while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) { + if ((timeout--) == 0) { return -1; } } @@ -94,32 +87,26 @@ int i2c_stop() * @param last Acknoledge * @return The read byte */ -int i2c_byte_read(int last) -{ +int i2c_byte_read(int last) { int timeout; - if (last) - { + if (last) { /* disable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } - else - { + } else { /* enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); } /* wait until the byte is received */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) - { - if ((timeout--) == 0) - { + while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) { + if ((timeout--) == 0) { return -1; } } - return (int)i2c_data_receive(I2C0); + return (int) i2c_data_receive(I2C0); } /** Write one byte @@ -128,17 +115,15 @@ int i2c_byte_read(int last) * @param data Byte to be written * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. */ -int i2c_byte_write(int data) -{ +int i2c_byte_write(int data) { int timeout; i2c_data_transmit(I2C0, data); /* wait until the byte is transmitted */ timeout = FLAG_TIMEOUT; - while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) - { - if ((timeout--) == 0) - { + while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) + || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { + if ((timeout--) == 0) { return 2; } } @@ -147,8 +132,7 @@ int i2c_byte_write(int data) } bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) -{ + uint8_t *pData, uint16_t Size) { if (!lock()) return false; @@ -157,18 +141,13 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, /* wait until I2C_FLAG_I2CBSY flag is reset */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) - { - if ((timeout--) == 0) - { + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); return false; - } - else - { - if (timeout % 5 == 0) - { + } else { + if (timeout % 5 == 0) { i2c_stop(); } } @@ -177,11 +156,10 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); return false; @@ -193,11 +171,9 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) - { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { timeout++; - if (timeout > 100000) - { + if (timeout > 100000) { i2c_stop(); unlock(); return false; @@ -205,8 +181,7 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, } bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - if (no_ack) - { + if (no_ack) { i2c_stop(); unlock(); return false; @@ -216,23 +191,21 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, int status = i2c_byte_write(MemAddress); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB); - if (status == 2 || no_ack) - { + if (status == 2 || no_ack) { i2c_stop(); unlock(); return false; } - //////////////////////////// //Restart into read +//////////////////////////// //Restart into read /* generate a START condition */ i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); return false; @@ -244,11 +217,9 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) - { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { timeout++; - if (timeout > 100000) - { + if (timeout > 100000) { i2c_stop(); unlock(); return false; @@ -258,15 +229,13 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - if (no_ack) - { + if (no_ack) { i2c_stop(); unlock(); return false; } - for (count = 0; count < Size; count++) - { - pData[count] = i2c_byte_read(count == (uint32_t)(Size - 1)); + for (count = 0; count < Size; count++) { + pData[count] = i2c_byte_read(count == (Size - 1)); } /* if not sequential write, then send stop */ @@ -275,40 +244,33 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, unlock(); return true; } -void FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) -{ - Mem_Write(address, reg, &data, 1); +bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { + return Mem_Write(address, reg, &data, 1); } -uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) -{ +uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { uint8_t temp = 0; Mem_Read(add, reg, &temp, 1); return temp; } -void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) -{ +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size) { if (!lock()) - return; + return false; uint32_t count = 0; int timeout = 0; /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); - return; - } - else - { - if (timeout % 5 == 0) - { + return false; + } else { + if (timeout % 5 == 0) { i2c_stop(); } } @@ -317,14 +279,13 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); - return; + return false; } } @@ -333,28 +294,24 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) - { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { timeout++; - if (timeout > 100000) - { + if (timeout > 100000) { i2c_stop(); unlock(); - return; + return false; } } /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); int status = i2c_byte_write(MemAddress); - for (count = 0; count < Size; count++) - { + for (count = 0; count < Size; count++) { status = i2c_byte_write(pData[count]); - if (status != 1) - { + if (status != 1) { i2c_stop(); unlock(); - return; + return false; } } @@ -362,29 +319,24 @@ void FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, i2c_stop(); unlock(); + return true; } -void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) -{ +bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { if (!lock()) - return; + return false; uint32_t count = 0; int timeout = 0; /* wait until I2C_FLAG_I2CBSY flag is reset */ timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) - { - if ((timeout--) == 0) - { + while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); - return; - } - else - { - if (timeout % 5 == 0) - { + return false; + } else { + if (timeout % 5 == 0) { i2c_stop(); } } @@ -393,14 +345,13 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) - { - if ((timeout--) == 0) - { + timeout = FLAG_TIMEOUT + ; + while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { + if ((timeout--) == 0) { i2c_stop(); unlock(); - return; + return false; } } @@ -409,28 +360,24 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) timeout = 0; /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) - { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { timeout++; - if (timeout > 100000) - { + if (timeout > 100000) { i2c_stop(); unlock(); - return; + return false; } } /* clear ADDSEND */ i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - for (count = 0; count < Size; count++) - { + for (count = 0; count < Size; count++) { int status = i2c_byte_write(pData[count]); - if (status != 1) - { + if (status != 1) { i2c_stop(); unlock(); - return; + return false; } } @@ -438,10 +385,10 @@ void FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) i2c_stop(); unlock(); + return true; } -bool FRToSI2C::probe(uint16_t DevAddress) -{ +bool FRToSI2C::probe(uint16_t DevAddress) { if (!lock()) return false; i2c_start(); @@ -449,16 +396,14 @@ bool FRToSI2C::probe(uint16_t DevAddress) i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); /* wait until ADDSEND bit is set */ int timeout = FLAG_TIMEOUT; - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) - { - if (i2c_flag_get(I2C0, I2C_FLAG_AERR) || i2c_flag_get(I2C0, I2C_FLAG_BERR)) - { + while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + if (i2c_flag_get(I2C0, I2C_FLAG_AERR) + || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { i2c_stop(); unlock(); return false; } - if (timeout-- == 0) - { + if (timeout-- == 0) { i2c_stop(); unlock(); return false; @@ -480,21 +425,29 @@ bool FRToSI2C::probe(uint16_t DevAddress) return !no_ack; } -void FRToSI2C::I2C_Unstick() -{ +void FRToSI2C::I2C_Unstick() { unstick_I2C(); } -bool FRToSI2C::lock() -{ +bool FRToSI2C::lock() { if (I2CSemaphore == nullptr) return true; - return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; + return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; } -void FRToSI2C::unlock() -{ +void FRToSI2C::unlock() { if (I2CSemaphore == nullptr) return; xSemaphoreGive(I2CSemaphore); } +bool FRToSI2C::lock2() { + if (I2CSemaphore2 == nullptr) + return true; + return xSemaphoreTake(I2CSemaphore2,1000) == pdTRUE; +} + +void FRToSI2C::unlock2() { + if (I2CSemaphore2 == nullptr) + return; + xSemaphoreGive(I2CSemaphore2); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 3424b60f..3a3e0afd 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -1,27 +1,24 @@ -/* - * Model_Config.h - * - * Created on: 25 Jul 2020 - * Author: Ralim - */ - -#ifndef BSP_MINIWARE_MODEL_CONFIG_H_ -#define BSP_MINIWARE_MODEL_CONFIG_H_ -/* - * Lookup for mapping features <-> Models - */ - -#if defined(MODEL_Pinecil) > 1 -#error "Multiple models defined!" -#elif defined(MODEL_Pinecil) == 0 -#error "No model defined!" -#endif - -#ifdef MODEL_Pinecil -#define ACCEL_LIS -#define TEMP_TMP36 -#define POW_QC -// #define POW_PD -#endif - -#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ +/* + * Model_Config.h + * + * Created on: 25 Jul 2020 + * Author: Ralim + */ + +#ifndef BSP_MINIWARE_MODEL_CONFIG_H_ +#define BSP_MINIWARE_MODEL_CONFIG_H_ +/* + * Lookup for mapping features <-> Models + */ + +#if defined(MODEL_Pinecil) == 0 +#error "No model defined!" +#endif + +#ifdef MODEL_Pinecil +#define POW_PD +#define POW_QC +#define TEMP_TMP36 +#endif + +#endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/N200/port.c b/workspace/TS100/Core/BSP/Pine64/N200/port.c index 13b06f47..ac7c84fd 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/port.c +++ b/workspace/TS100/Core/BSP/Pine64/N200/port.c @@ -1,4 +1,3 @@ -#include "FreeRTOSConfig.h" #include "FreeRTOS.h" #include "task.h" #include "portmacro.h" @@ -7,32 +6,36 @@ #include "riscv_encoding.h" #include "n200_timer.h" #include "n200_eclic.h" + /* Standard Includes */ #include #include #include + /* Each task maintains its own interrupt status in the critical nesting variable. */ UBaseType_t uxCriticalNesting = 0xaaaaaaaa; #if USER_MODE_TASKS #ifdef __riscv_flen -unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); + unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); #else -unsigned long MSTATUS_INIT = (MSTATUS_MPIE); + unsigned long MSTATUS_INIT = (MSTATUS_MPIE); #endif #else #ifdef __riscv_flen -unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); + unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); #else -unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); + unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); #endif #endif + /* * Used to catch tasks that attempt to return from their implementing function. */ -static void prvTaskExitError(void); +static void prvTaskExitError( void ); + /** * @brief System Call Trap @@ -44,51 +47,52 @@ static void prvTaskExitError(void); */ unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) { - switch (mcause & 0X00000fff) + switch(mcause&0X00000fff) { - //on User and Machine ECALL, handler the request - case 8: - case 11: - { - if (arg1 == IRQ_DISABLE) + //on User and Machine ECALL, handler the request + case 8: + case 11: { - //zero out mstatus.mpie - clear_csr(mstatus, MSTATUS_MPIE); + if(arg1==IRQ_DISABLE) + { + //zero out mstatus.mpie + clear_csr(mstatus,MSTATUS_MPIE); + } + else if(arg1==IRQ_ENABLE) + { + //set mstatus.mpie + set_csr(mstatus,MSTATUS_MPIE); + } + else if(arg1==PORT_YIELD) + { + //always yield from machine mode + //fix up mepc on sync trap + unsigned long epc = read_csr(mepc); + vPortYield_from_ulSynchTrap(sp,epc+4); + } + else if(arg1==PORT_YIELD_TO_RA) + { + vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp)))); + } + break; } - else if (arg1 == IRQ_ENABLE) + default: { - //set mstatus.mpie - set_csr(mstatus, MSTATUS_MPIE); + /* 异常处理 */ + extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); + handle_trap(mcause,sp); } - else if (arg1 == PORT_YIELD) - { - //always yield from machine mode - //fix up mepc on sync trap - unsigned long epc = read_csr(mepc); - vPortYield_from_ulSynchTrap(sp, epc + 4); - } - else if (arg1 == PORT_YIELD_TO_RA) - { - vPortYield_from_ulSynchTrap(sp, (*(unsigned long *)(sp + 1 * sizeof(sp)))); - } - break; - } - default: - { - /* 异常处理 */ - extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); - handle_trap(mcause, sp); - } } //fix mepc and return unsigned long epc = read_csr(mepc); - write_csr(mepc, epc + 4); + write_csr(mepc,epc+4); return sp; } /*-----------------------------------------------------------*/ + /** * @brief 设置触发软中断 * @note 目的是在软中断内进行任务上下文切换 @@ -96,22 +100,24 @@ unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long */ void vPortSetMSIPInt(void) { - *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) |= 0x01; + *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01; __asm volatile("fence"); __asm volatile("fence.i"); } /*-----------------------------------------------------------*/ + /** * @brief 清除软中断 * */ void vPortClearMSIPInt(void) { - *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; + *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; } /*-----------------------------------------------------------*/ + /** * @brief 执行任务上下文切换,在portasm.S中被调用 * @@ -119,22 +125,23 @@ void vPortClearMSIPInt(void) * @param arg1 * @return unsigned long sp地址 */ -unsigned long taskswitch(unsigned long sp, unsigned long arg1) +unsigned long taskswitch( unsigned long sp, unsigned long arg1) { //always yield from machine mode //fix up mepc on unsigned long epc = read_csr(mepc); - vPortYield(sp, epc); //never returns + vPortYield(sp,epc); //never returns return sp; } /*-----------------------------------------------------------*/ + /** * @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用 * */ -void vDoTaskSwitchContext(void) +void vDoTaskSwitchContext( void ) { portDISABLE_INTERRUPTS(); vTaskSwitchContext(); @@ -142,42 +149,45 @@ void vDoTaskSwitchContext(void) } /*-----------------------------------------------------------*/ + /** * @brief 进入临界段 * */ -void vPortEnterCritical(void) +void vPortEnterCritical( void ) { -#if USER_MODE_TASKS - ECALL(IRQ_DISABLE); -#else - portDISABLE_INTERRUPTS(); -#endif + #if USER_MODE_TASKS + ECALL(IRQ_DISABLE); + #else + portDISABLE_INTERRUPTS(); + #endif uxCriticalNesting++; } /*-----------------------------------------------------------*/ + /** * @brief 退出临界段 * */ -void vPortExitCritical(void) +void vPortExitCritical( void ) { - configASSERT(uxCriticalNesting); + configASSERT( uxCriticalNesting ); uxCriticalNesting--; - if (uxCriticalNesting == 0) + if( uxCriticalNesting == 0 ) { -#if USER_MODE_TASKS - ECALL(IRQ_ENABLE); -#else - portENABLE_INTERRUPTS(); -#endif + #if USER_MODE_TASKS + ECALL(IRQ_ENABLE); + #else + portENABLE_INTERRUPTS(); + #endif } return; } /*-----------------------------------------------------------*/ + /** * @brief Clear current interrupt mask and set given mask * @@ -185,10 +195,11 @@ void vPortExitCritical(void) */ void vPortClearInterruptMask(int int_mask) { - eclic_set_mth(int_mask); + eclic_set_mth (int_mask); } /*-----------------------------------------------------------*/ + /** * @brief Set interrupt mask and return current interrupt enable register * @@ -196,14 +207,15 @@ void vPortClearInterruptMask(int int_mask) */ int xPortSetInterruptMask(void) { - int int_mask = 0; - int_mask = eclic_get_mth(); + int int_mask=0; + int_mask=eclic_get_mth(); portDISABLE_INTERRUPTS(); return int_mask; } /*-----------------------------------------------------------*/ + /** * @brief 初始化任务栈帧 * @@ -212,30 +224,30 @@ int xPortSetInterruptMask(void) * @param pvParameters 任务参数 * @return StackType_t* 完成初始化后的栈顶 */ -StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { /* Simulate the stack frame as it would be created by a context switch interrupt. */ #ifdef __riscv_flen - pxTopOfStack -= 32; /* 浮点寄存器 */ + pxTopOfStack -= 32; /* 浮点寄存器 */ #endif pxTopOfStack--; - *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ + *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ pxTopOfStack--; - *pxTopOfStack = 0x40; /* CSR_SUBM */ + *pxTopOfStack = 0x40; /* CSR_SUBM */ pxTopOfStack--; - *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ + *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ pxTopOfStack--; - *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ + *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ pxTopOfStack -= 22; - *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ + *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ - pxTopOfStack -= 9; + pxTopOfStack -=9; *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */ pxTopOfStack--; @@ -243,24 +255,25 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC } /*-----------------------------------------------------------*/ + /** * @brief 任务退出函数 * */ -void prvTaskExitError(void) +void prvTaskExitError( void ) { /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it should instead call vTaskDelete( NULL ). Artificially force an assert() to be triggered if configASSERT() is defined, then stop here so application writers can catch the error. */ - configASSERT(uxCriticalNesting == ~0UL); + configASSERT( uxCriticalNesting == ~0UL ); portDISABLE_INTERRUPTS(); - for (;;) - ; + for( ;; ); } /*-----------------------------------------------------------*/ + /** * @brief tick中断 * @note 由于该中断配置为向量模式,则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler @@ -268,38 +281,39 @@ void prvTaskExitError(void) */ void vPortSysTickHandler(void) { - volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); + volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); -#if CONFIG_SYSTEMVIEW_EN + #if CONFIG_SYSTEMVIEW_EN traceISR_ENTER(); -#endif + #endif uint64_t now = *mtime; now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); *mtimecmp = now; /* 调用freertos的tick增加接口 */ - if (xTaskIncrementTick() != pdFALSE) + if( xTaskIncrementTick() != pdFALSE ) { -#if CONFIG_SYSTEMVIEW_EN + #if CONFIG_SYSTEMVIEW_EN traceISR_EXIT_TO_SCHEDULER(); -#endif + #endif portYIELD(); } -#if CONFIG_SYSTEMVIEW_EN + #if CONFIG_SYSTEMVIEW_EN else { traceISR_EXIT(); } -#endif + #endif - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); } /*-----------------------------------------------------------*/ + /** * @brief 初始化tick * @@ -307,20 +321,21 @@ void vPortSysTickHandler(void) void vPortSetupTimer(void) { /* 内核timer定时器使用64位的计数器来实现 */ - volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); + volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); portENTER_CRITICAL(); - uint64_t now = *mtime; - now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); - *mtimecmp = now; + uint64_t now = *mtime; + now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); + *mtimecmp = now; portEXIT_CRITICAL(); eclic_set_vmode(CLIC_INT_TMR); - eclic_irq_enable(CLIC_INT_TMR, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); + eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); } /*-----------------------------------------------------------*/ + /** * @brief 初始化软中断 * @@ -328,10 +343,11 @@ void vPortSetupTimer(void) void vPortSetupMSIP(void) { eclic_set_vmode(CLIC_INT_SFT); - eclic_irq_enable(CLIC_INT_SFT, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); + eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); } /*-----------------------------------------------------------*/ + /** * @brief 调度启动前的初始化准备 * diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h index 29ccc744..50383ac5 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h +++ b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h @@ -1,13 +1,14 @@ -#ifndef PINE_PORTMACRO_H -#define PINE_PORTMACRO_H +#ifndef PORTMACRO_H +#define PORTMACRO_H #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif + #include "riscv_encoding.h" + /*----------------------------------------------------------- * Port specific definitions. * @@ -19,128 +20,123 @@ extern "C" */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; -#if (configUSE_16_BIT_TICKS == 1) +#if( configUSE_16_BIT_TICKS == 1 ) typedef uint16_t TickType_t; -#define portMAX_DELAY (TickType_t)0xffff + #define portMAX_DELAY ( TickType_t ) 0xffff #else -typedef uint32_t TickType_t; -#define portMAX_DELAY (TickType_t)0xffffffffUL + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #endif /*-----------------------------------------------------------*/ /* Architecture specifics. */ -#define portSTACK_GROWTH (-1) -#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ) -#define portBYTE_ALIGNMENT 8 - /*-----------------------------------------------------------*/ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +extern void vPortYield(unsigned long,unsigned long); +extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long); +extern int xPortSetInterruptMask(void); +extern void vPortClearInterruptMask( int uxSavedStatusValue ); - /* Architecture specifics. */ - extern void vPortYield(unsigned long, unsigned long); - extern void vPortYield_from_ulSynchTrap(unsigned long, unsigned long); - extern int xPortSetInterruptMask(void); - extern void vPortClearInterruptMask(int uxSavedStatusValue); /*-----------------------------------------------------------*/ /*System Calls */ /*-----------------------------------------------------------*/ //ecall macro used to store argument in a3 -#define ECALL(arg) ({ \ - register uintptr_t a2 asm("a2") = (uintptr_t)(arg); \ - asm volatile("ecall" \ - : "+r"(a2) \ - : \ - : "memory"); \ - a2; \ +#define ECALL(arg) ({ \ + register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \ + asm volatile ("ecall" \ + : "+r" (a2) \ + : \ + : "memory"); \ + a2; \ }) - extern void vPortSetMSIPInt(void); + +extern void vPortSetMSIPInt(void); #define port_MSIPSET_BIT vPortSetMSIPInt() -#define IRQ_DISABLE 20 -#define IRQ_ENABLE 30 -#define PORT_YIELD 40 -#define PORT_YIELD_TO_RA 50 +#define IRQ_DISABLE 20 +#define IRQ_ENABLE 30 +#define PORT_YIELD 40 +#define PORT_YIELD_TO_RA 50 /*-----------------------------------------------------------*/ + /* Scheduler utilities. */ /* the return after the ECALL is VERY important */ //#define portYIELD() ECALL(PORT_YIELD); #define portYIELD() port_MSIPSET_BIT; -#ifdef CONFIG_SYSTEMVIEW_EN -#define portEND_SWITCHING_ISR(xSwitchRequired) \ - { \ - if (xSwitchRequired != pdFALSE) \ - { \ - traceISR_EXIT_TO_SCHEDULER(); \ - portYIELD(); \ - } \ - else \ - { \ - traceISR_EXIT(); \ - } \ - } +#if CONFIG_SYSTEMVIEW_EN +#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } } #else -#define portEND_SWITCHING_ISR(xSwitchRequired) \ - if (xSwitchRequired != pdFALSE) \ - portYIELD() +#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD() #endif -#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) +#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) - /* Critical section management. */ - extern void vPortEnterCritical(void); - extern void vPortExitCritical(void); - extern void eclic_set_mth(uint8_t mth); -#define portDISABLE_INTERRUPTS() \ - { \ - eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY) | 0x1f); \ - __asm volatile("fence"); \ - __asm volatile("fence.i"); \ - } -#define portENABLE_INTERRUPTS() eclic_set_mth(0) -#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern void eclic_set_mth (uint8_t mth); +#define portDISABLE_INTERRUPTS() \ +{ \ + eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \ + __asm volatile("fence"); \ + __asm volatile("fence.i"); \ +} +#define portENABLE_INTERRUPTS() eclic_set_mth(0) +#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. These are not necessary for to use this port. They are defined so the common demo files (which build with all the ports) will build. */ -#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) -#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ /* Tickless idle/low power functionality. */ #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); -#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime) + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #endif - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ -#define portINLINE __inline + +#define portINLINE __inline #ifndef portFORCE_INLINE -#define portFORCE_INLINE inline __attribute__((always_inline)) + #define portFORCE_INLINE inline __attribute__(( always_inline)) #endif + + + #ifdef __cplusplus } #endif #endif /* PORTMACRO_H */ + diff --git a/workspace/TS100/Core/BSP/Pine64/NOTES.md b/workspace/TS100/Core/BSP/Pine64/NOTES.md index 7a697725..2482821e 100644 --- a/workspace/TS100/Core/BSP/Pine64/NOTES.md +++ b/workspace/TS100/Core/BSP/Pine64/NOTES.md @@ -7,17 +7,17 @@ | 17 | PB2 | BOOT2 | Pulldown | | 32 | | IMU INT 1 | N/A | | 30 | | IMU INT 2 | N/A | -| 14 | PA7 | Handle Temp | ADC Input 7 | -| 15 | PB0 | Tip Temp | ADC Input 8 | -| 13 | PA6 | B Button | Active Low | -| 21 | PA9 | A Button | Active Low | -| 23 | PA11 | USB D- | - | -| 24 | PA12 | USB D+ | - | -| 31 | PB4 | Tip PWM Out | TIMER2_CH0 | -| 16 | PB1 | Input DC V Sense | ADC Input 9 | -| 20 | PA8 | OLED Reset | | -| 34 | PB7 | SDA | I2C0_SDA | -| 33 | PB6 | SCL | I2C0_SCL | +| | PA4 | Handle Temp | ADC Input ? | +| | PA1 | Tip Temp | ADC Input ? | +| | PB1 | B Button | Active High | +| | PB0 | A Button | Active High | +| | PA11 | USB D- | - | +| | PA12 | USB D+ | - | +| | PA6 | Tip PWM Out | - | +| | PA0 | Input DC V Sense | ADC Input ? | +| | PA9 | OLED Reset | | +| | PB7 | SDA | I2C0_SDA | +| | PB6 | SCL | I2C0_SCL | ## ADC Configuration diff --git a/workspace/TS100/Core/BSP/Pine64/Pins.h b/workspace/TS100/Core/BSP/Pine64/Pins.h index 9ab0ecd2..461ec9b8 100644 --- a/workspace/TS100/Core/BSP/Pine64/Pins.h +++ b/workspace/TS100/Core/BSP/Pine64/Pins.h @@ -9,27 +9,27 @@ #define BSP_MINIWARE_PINS_H_ #include "Vendor/Lib/gd32vf103_gpio.h" //TODO -#define KEY_B_Pin BIT(6) -#define KEY_B_GPIO_Port GPIOA -#define TMP36_INPUT_Pin BIT(7) +#define KEY_B_Pin BIT(1) +#define KEY_B_GPIO_Port GPIOB +#define TMP36_INPUT_Pin BIT(4) #define TMP36_INPUT_GPIO_Port GPIOA -#define TMP36_ADC1_CHANNEL ADC_CHANNEL_7 -#define TMP36_ADC2_CHANNEL ADC_CHANNEL_7 -#define TIP_TEMP_Pin BIT(0) -#define TIP_TEMP_GPIO_Port GPIOB -#define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_8 -#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_8 +#define TMP36_ADC1_CHANNEL ADC_CHANNEL_4 +#define TMP36_ADC2_CHANNEL ADC_CHANNEL_4 +#define TIP_TEMP_Pin BIT(1) +#define TIP_TEMP_GPIO_Port GPIOA +#define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_1 +#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_1 -#define VIN_Pin BIT(1) -#define VIN_GPIO_Port GPIOB -#define VIN_ADC1_CHANNEL ADC_CHANNEL_9 -#define VIN_ADC2_CHANNEL ADC_CHANNEL_9 -#define OLED_RESET_Pin BIT(8) +#define VIN_Pin BIT(0) +#define VIN_GPIO_Port GPIOA +#define VIN_ADC1_CHANNEL ADC_CHANNEL_0 +#define VIN_ADC2_CHANNEL ADC_CHANNEL_0 +#define OLED_RESET_Pin BIT(9) #define OLED_RESET_GPIO_Port GPIOA -#define KEY_A_Pin BIT(9) -#define KEY_A_GPIO_Port GPIOA -#define PWM_Out_Pin BIT(4) -#define PWM_Out_GPIO_Port GPIOB +#define KEY_A_Pin BIT(0) +#define KEY_A_GPIO_Port GPIOB +#define PWM_Out_Pin BIT(6) +#define PWM_Out_GPIO_Port GPIOA #define SCL_Pin BIT(6) #define SCL_GPIO_Port GPIOB #define SDA_Pin BIT(7) diff --git a/workspace/TS100/Core/BSP/Pine64/Power.cpp b/workspace/TS100/Core/BSP/Pine64/Power.cpp index ae6d8520..23b02783 100644 --- a/workspace/TS100/Core/BSP/Pine64/Power.cpp +++ b/workspace/TS100/Core/BSP/Pine64/Power.cpp @@ -9,32 +9,28 @@ #include "int_n.h" bool FUSB302_present = false; -void power_check() -{ +void power_check() { #ifdef POW_PD - if (FUSB302_present) - { - //Cant start QC until either PD works or fails - if (PolicyEngine::setupCompleteOrTimedOut() == false) - { - return; - } - if (PolicyEngine::pdHasNegotiated()) - { - return; - } - } + if (FUSB302_present) { + //Cant start QC until either PD works or fails + if (PolicyEngine::setupCompleteOrTimedOut() == false) { + return; + } + if (PolicyEngine::pdHasNegotiated()) { + return; + } + } #endif #ifdef POW_QC - QC_resync(); + QC_resync(); #endif } -uint8_t usb_pd_detect() -{ +uint8_t usb_pd_detect() { #ifdef POW_PD - FUSB302_present = fusb302_detect(); + FUSB302_present = fusb302_detect(); - return FUSB302_present; + return FUSB302_present; #endif - return false; + return false; } + diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 9c9aa327..0812d5ec 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -55,8 +55,8 @@ void setup_gpio() { //Alternate function clock enable rcu_periph_clock_enable(RCU_AF); //Buttons as input - gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, KEY_A_Pin); - gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, KEY_B_Pin); + gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin); + gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin); //OLED reset as output gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin); @@ -73,7 +73,7 @@ void setup_gpio() { TIP_TEMP_Pin); gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, VIN_Pin); //Timer 2 remap to move timer 2 ch0 to pin PB4 - gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE); +// gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE); //Remap PB4 away from JTAG NJRST gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); //TODO - rest of pins as floating @@ -112,7 +112,7 @@ void setup_i2c() { /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 100kHz with DMA? - i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); + i2c_clock_config(I2C0, 100 * 1000, I2C_DTCY_16_9); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); /* enable acknowledge */ diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds new file mode 100644 index 00000000..83ce13a0 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds @@ -0,0 +1,176 @@ +OUTPUT_ARCH( "riscv" ) + +ENTRY( _start ) + +MEMORY +{ + /* Run in FLASH */ + flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k + ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K + + /* Run in RAM */ +/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k + ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K +*/ +} + + +SECTIONS +{ + __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; + + + .init : + { + KEEP (*(SORT_NONE(.init))) + } >flash AT>flash + + .ilalign : + { + . = ALIGN(4); + PROVIDE( _ilm_lma = . ); + } >flash AT>flash + + .ialign : + { + PROVIDE( _ilm = . ); + } >flash AT>flash + + .text : + { + *(.rodata .rodata.*) + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >flash AT>flash + + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } >flash AT>flash + + . = ALIGN(4); + + PROVIDE (__etext = .); + PROVIDE (_etext = .);/*0x80022c8*/ + PROVIDE (etext = .);/*0x80022c8*/ + PROVIDE( _eilm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >flash AT>flash + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >flash AT>flash + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >flash AT>flash + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >flash AT>flash + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >flash AT>flash + + . = ALIGN(4); + PROVIDE( _eilm = . ); + + .lalign : + { + . = ALIGN(4); + PROVIDE( _data_lma = . ); + } >flash AT>flash + + .dalign : + { + . = ALIGN(4); + PROVIDE( _data = . ); + } >ram AT>flash + + + .data : + { + *(.rdata) + + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram AT>flash + + . = ALIGN(4); + PROVIDE( _edata = . ); + PROVIDE( edata = . ); + + PROVIDE( _fbss = . ); /*0X200052A0 0X200002A0*/ + PROVIDE( __bss_start = . ); + .bss : + { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + } >ram AT>ram + + . = ALIGN(8); + PROVIDE( _end = . ); /*0X2000,0340*/ + PROVIDE( end = . ); + PROVIDE( heap_start = . ); + + .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : + { + PROVIDE( heap_end = . ); + . = __stack_size; + PROVIDE( _sp = . ); + } >ram AT>ram +} diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp index 2304ecf2..6d35bb57 100644 --- a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -29,11 +29,9 @@ * * Returns the value read from addr. */ -static uint8_t fusb_read_byte(uint8_t addr) -{ +static uint8_t fusb_read_byte(uint8_t addr) { uint8_t data[1]; - if (!FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, (uint8_t *)data, 1)) - { + if (!FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, (uint8_t*) data, 1)) { return 0; } return data[0]; @@ -47,8 +45,7 @@ static uint8_t fusb_read_byte(uint8_t addr) * size: The number of bytes to read * buf: The buffer into which data will be read */ -static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) -{ +static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) { return FRToSI2C::Mem_Read(FUSB302B_ADDR, addr, buf, size); } @@ -59,9 +56,9 @@ static bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf) * addr: The memory address to which we will write * byte: The value to write */ -static bool fusb_write_byte(uint8_t addr, uint8_t byte) -{ - return FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t *)&byte, 1); +static bool fusb_write_byte(uint8_t addr, uint8_t byte) { + FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) &byte, 1); + return true; } /* @@ -72,29 +69,27 @@ static bool fusb_write_byte(uint8_t addr, uint8_t byte) * size: The number of bytes to write * buf: The buffer to write */ -static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) -{ - return FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, buf, size); +static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { + FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*)buf, size); + return true; //TODO } -void fusb_send_message(const union pd_msg *msg) -{ - if (!FRToSI2C::lock2()) - { +void fusb_send_message(const union pd_msg *msg) { + if (!FRToSI2C::lock2()) { return; } /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP2, - FUSB_FIFO_TX_PACKSYM}; + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP2, + FUSB_FIFO_TX_PACKSYM }; static const uint8_t eop_seq[4] = { - FUSB_FIFO_TX_JAM_CRC, - FUSB_FIFO_TX_EOP, - FUSB_FIFO_TX_TXOFF, - FUSB_FIFO_TX_TXON}; + FUSB_FIFO_TX_JAM_CRC, + FUSB_FIFO_TX_EOP, + FUSB_FIFO_TX_TXOFF, + FUSB_FIFO_TX_TXON }; /* Take the I2C2 mutex now so there can't be a race condition on sop_seq */ /* Get the length of the message: a two-octet header plus NUMOBJ four-octet @@ -105,188 +100,155 @@ void fusb_send_message(const union pd_msg *msg) sop_seq[4] = FUSB_FIFO_TX_PACKSYM | msg_len; /* Write all three parts of the message to the TX FIFO */ - fusb_write_buf(FUSB_FIFOS, 5, sop_seq); - fusb_write_buf(FUSB_FIFOS, msg_len, msg->bytes); - fusb_write_buf(FUSB_FIFOS, 4, eop_seq); + fusb_write_buf( FUSB_FIFOS, 5, sop_seq); + fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes); + fusb_write_buf( FUSB_FIFOS, 4, eop_seq); FRToSI2C::unlock2(); + } -uint8_t fusb_read_message(union pd_msg *msg) -{ - if (!FRToSI2C::lock2()) - { - asm("bkpt"); +uint8_t fusb_read_message(union pd_msg *msg) { + if (!FRToSI2C::lock2()) { + return 1; } static uint8_t garbage[4]; uint8_t numobj; // Read the header. If its not a SOP we dont actually want it at all // But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck - fusb_read_byte(FUSB_FIFOS); + fusb_read_byte( FUSB_FIFOS); /* Read the message header into msg */ - fusb_read_buf(FUSB_FIFOS, 2, msg->bytes); + fusb_read_buf( FUSB_FIFOS, 2, msg->bytes); /* Get the number of data objects */ numobj = PD_NUMOBJ_GET(msg); /* If there is at least one data object, read the data objects */ - if (numobj > 0) - { - fusb_read_buf(FUSB_FIFOS, numobj * 4, msg->bytes + 2); + if (numobj > 0) { + fusb_read_buf( FUSB_FIFOS, numobj * 4, msg->bytes + 2); } /* Throw the CRC32 in the garbage, since the PHY already checked it. */ - fusb_read_buf(FUSB_FIFOS, 4, garbage); + fusb_read_buf( FUSB_FIFOS, 4, garbage); FRToSI2C::unlock2(); return 0; } -void fusb_send_hardrst() -{ +void fusb_send_hardrst() { - if (!FRToSI2C::lock2()) - { + if (!FRToSI2C::lock2()) { return; } /* Send a hard reset */ - fusb_write_byte(FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); + fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); FRToSI2C::unlock2(); } -void fusb_setup() -{ - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - HAL_NVIC_SetPriority(EXTI9_5_IRQn, 12, 0); - HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); +void fusb_setup() { - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { - if (!FRToSI2C::lock2()) - { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!FRToSI2C::lock2()) { return; } } /* Fully reset the FUSB302B */ - fusb_write_byte(FUSB_RESET, FUSB_RESET_SW_RES); + fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); osDelay(2); - if (!fusb_read_id()) - { + if (!fusb_read_id()) { return; } /* Turn on all power */ - fusb_write_byte(FUSB_POWER, 0x0F); + fusb_write_byte( FUSB_POWER, 0x0F); /* Set interrupt masks */ //Setting to 0 so interrupts are allowed - fusb_write_byte(FUSB_MASK1, 0x00); - fusb_write_byte(FUSB_MASKA, 0x00); - fusb_write_byte(FUSB_MASKB, 0x00); - fusb_write_byte(FUSB_CONTROL0, 0b11 << 2); + fusb_write_byte( FUSB_MASK1, 0x00); + fusb_write_byte( FUSB_MASKA, 0x00); + fusb_write_byte( FUSB_MASKB, 0x00); + fusb_write_byte( FUSB_CONTROL0, 0b11 << 2); /* Enable automatic retransmission */ - fusb_write_byte(FUSB_CONTROL3, 0x07); + fusb_write_byte( FUSB_CONTROL3, 0x07); //set defaults - fusb_write_byte(FUSB_CONTROL2, 0x00); + fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ - fusb_write_byte(FUSB_CONTROL1, - FUSB_CONTROL1_RX_FLUSH); + fusb_write_byte( FUSB_CONTROL1, + FUSB_CONTROL1_RX_FLUSH); /* Measure CC1 */ - fusb_write_byte(FUSB_SWITCHES0, 0x07); + fusb_write_byte( FUSB_SWITCHES0, 0x07); osDelay(10); - uint8_t cc1 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + uint8_t cc1 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; /* Measure CC2 */ - fusb_write_byte(FUSB_SWITCHES0, 0x0B); + fusb_write_byte( FUSB_SWITCHES0, 0x0B); osDelay(10); - uint8_t cc2 = fusb_read_byte(FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; + uint8_t cc2 = fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL; /* Select the correct CC line for BMC signaling; also enable AUTO_CRC */ - if (cc1 > cc2) - { - fusb_write_byte(FUSB_SWITCHES1, 0x25); - fusb_write_byte(FUSB_SWITCHES0, 0x07); + if (cc1 > cc2) { + fusb_write_byte( FUSB_SWITCHES1, 0x25); + fusb_write_byte( FUSB_SWITCHES0, 0x07); + } else { + fusb_write_byte( FUSB_SWITCHES1, 0x26); + fusb_write_byte( FUSB_SWITCHES0, 0x0B); } - else - { - fusb_write_byte(FUSB_SWITCHES1, 0x26); - fusb_write_byte(FUSB_SWITCHES0, 0x0B); - } - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { FRToSI2C::unlock2(); } fusb_reset(); } -void fusb_get_status(union fusb_status *status) -{ - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { - if (!FRToSI2C::lock2()) - { +void fusb_get_status(union fusb_status *status) { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!FRToSI2C::lock2()) { return; } } /* Read the interrupt and status flags into status */ - fusb_read_buf(FUSB_STATUS0A, 7, status->bytes); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { + fusb_read_buf( FUSB_STATUS0A, 7, status->bytes); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { FRToSI2C::unlock2(); } + } -enum fusb_typec_current fusb_get_typec_current() -{ - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { - if (!FRToSI2C::lock2()) - { +enum fusb_typec_current fusb_get_typec_current() { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!FRToSI2C::lock2()) { return fusb_tcc_none; } } /* Read the BC_LVL into a variable */ - enum fusb_typec_current bc_lvl = (enum fusb_typec_current)(fusb_read_byte( - FUSB_STATUS0) & - FUSB_STATUS0_BC_LVL); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { + enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( + FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { FRToSI2C::unlock2(); } return bc_lvl; } -void fusb_reset() -{ - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { - if (!FRToSI2C::lock2()) - { +void fusb_reset() { + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (!FRToSI2C::lock2()) { return; } } /* Flush the TX buffer */ - fusb_write_byte(FUSB_CONTROL0, 0x44); + fusb_write_byte( FUSB_CONTROL0, 0x44); /* Flush the RX buffer */ - fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); + fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); /* Reset the PD logic */ - // fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) - { +// fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { FRToSI2C::unlock2(); } } -bool fusb_read_id() -{ +bool fusb_read_id() { //Return true if read of the revision ID is sane uint8_t version = 0; fusb_read_buf(FUSB_DEVICE_ID, 1, &version); @@ -294,8 +256,7 @@ bool fusb_read_id() return false; return true; } -uint8_t fusb302_detect() -{ +uint8_t fusb302_detect() { //Probe the I2C bus for its address return FRToSI2C::probe(FUSB302B_ADDR); } diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp index deb78e5d..fa55ab11 100644 --- a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -8,7 +8,12 @@ #include "stdlib.h" #include "task.h" #include "I2C_Wrapper.hpp" +#include "fusbpd.h" void postRToSInit() { - // Any after RTos setup + // Any after RTos setup FRToSI2C::FRToSInit(); +#ifdef POW_PD + //Spawn all of the USB-C processors + fusb302_start_processing(); +#endif } diff --git a/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp index f31610d5..222cc096 100644 --- a/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp @@ -14,7 +14,7 @@ void preRToSInit() { eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); eclic_global_interrupt_enable(); hardware_init(); - FRToSI2C::init(); + FRToSI2C::FRToSInit(); gpio_bit_reset(OLED_RESET_GPIO_Port, OLED_RESET_Pin); delay_ms(50); gpio_bit_set(OLED_RESET_GPIO_Port, OLED_RESET_Pin); From 8074255b9ea269f474a74da54e1775483d798227 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 17 Sep 2020 19:05:55 +1000 Subject: [PATCH 09/72] Backport some master changes --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 78 +++- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 13 +- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 26 +- .../Core/Drivers/FUSB302/policy_engine.cpp | 29 +- workspace/TS100/Core/Drivers/I2CBB.cpp | 11 +- workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 32 +- workspace/TS100/Core/Drivers/LIS2DH12.cpp | 50 +-- workspace/TS100/Core/Drivers/LIS2DH12.hpp | 17 +- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 171 +++++++ workspace/TS100/Core/Inc/FreeRTOSHooks.h | 13 +- workspace/TS100/Core/Inc/Settings.h | 59 ++- workspace/TS100/Core/Inc/Translation.h | 4 - workspace/TS100/Core/Inc/gui.hpp | 12 +- workspace/TS100/Core/Inc/main.hpp | 21 +- workspace/TS100/Core/Inc/stm32f1xx_it.h | 134 +++--- workspace/TS100/Core/Src/FreeRTOSHooks.c | 18 +- workspace/TS100/Core/Src/Settings.cpp | 6 +- workspace/TS100/Core/Src/freertos.c | 104 ++--- workspace/TS100/Core/Src/gui.cpp | 424 +++++++++--------- workspace/TS100/Core/Src/main.cpp | 29 -- workspace/TS100/Core/Threads/GUIThread.cpp | 3 +- workspace/TS100/Core/Threads/MOVThread.cpp | 28 +- workspace/TS100/Core/Threads/PIDThread.cpp | 53 +-- 23 files changed, 754 insertions(+), 581 deletions(-) create mode 100644 workspace/TS100/Core/Inc/FreeRTOSConfig.h diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 13bb458d..e1632cfb 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -10,6 +10,8 @@ #include "systick.h" #include +//2 second filter (ADC is PID_TIM_HZ Hz) +history rawTempFilter = {{0}, 0, 0}; void resetWatchdog() { //TODO } @@ -24,9 +26,79 @@ uint16_t getTipInstantTemperature() { return sum; // 8x over sample } -// Timer callbacks -// TODO -// Handle callback of the PWM modulator to enable / disable the output PWM +uint16_t getTipRawTemp(uint8_t refresh) +{ + if (refresh) + { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } + else + { + return rawTempFilter.average(); + } +} + +uint16_t getHandleTemperature() +{ +#ifdef TEMP_TMP36 + // We return the current handle temperature in X10 C + // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for + // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = + // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 + // mV per count So we need to subtract an offset of 0.5V to center on 0C + // (4964.8 counts) + // + int32_t result = getADC(0); + result -= 4965; // remove 0.5V offset + // 10mV per C + // 99.29 counts per Deg C above 0C + result *= 100; + result /= 993; + return result; +#else +#error +#endif +} +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) +{ +// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN +// Therefore we can divide down from there +// Multiplying ADC max by 4 for additional calibration options, +// ideal term is 467 +#ifdef MODEL_TS100 +#define BATTFILTERDEPTH 32 +#else +#define BATTFILTERDEPTH 8 + +#endif + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) + { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) + { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; + + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; + + sum /= BATTFILTERDEPTH; + if (divisor == 0) + { + divisor = 1; + } + return sum * 4 / divisor; +} void unstick_I2C() { // TODO diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index f6bb58e1..fb8c833c 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -15,24 +15,13 @@ #include "protocol_rx.h" #include "protocol_tx.h" #include "int_n.h" -#include "hard_reset.h" - - void fusb302_start_processing() { /* Initialize the FUSB302B */ - resetWatchdog(); fusb_setup(); - resetWatchdog(); - /* Create the policy engine thread. */ PolicyEngine::init(); - - /* Create the protocol layer threads. */ - ProtocolReceive::init(); ProtocolTransmit::init(); - ResetHandler::init(); - resetWatchdog(); - /* Create the INT_N thread. */ + ProtocolReceive::init(); InterruptHandler::init(); } #endif diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index 52d7701b..a94e21b7 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -21,14 +21,13 @@ #include "fusb302b.h" #include "protocol_rx.h" #include "protocol_tx.h" -#include "hard_reset.h" #include "policy_engine.h" #include "protocol_rx.h" #include "protocol_tx.h" #include "task.h" #include "BSP.h" -osThreadId InterruptHandler::TaskHandle=NULL; +osThreadId InterruptHandler::TaskHandle = NULL; uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; osStaticThreadDef_t InterruptHandler::TaskControlBlock; @@ -41,8 +40,6 @@ void InterruptHandler::init() { void InterruptHandler::Thread(const void *arg) { (void) arg; union fusb_status status; - volatile uint32_t events; - bool notifSent = false; while (true) { /* If the INT_N line is low */ if (xTaskNotifyWait(0x00, 0x0F, NULL, @@ -50,7 +47,6 @@ void InterruptHandler::Thread(const void *arg) { //delay slightly so we catch the crc with better timing osDelay(1); } - notifSent = false; /* Read the FUSB302B status and interrupt registers */ fusb_get_status(&status); /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX @@ -58,43 +54,23 @@ void InterruptHandler::Thread(const void *arg) { if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT); - notifSent = true; } if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { ProtocolTransmit::notify( ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); - notifSent = true; } /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ //This means a message was recieved with a good CRC if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) { ProtocolReceive::notify(PDB_EVT_PRLRX_I_GCRCSENT); - notifSent = true; } - /* If the I_HARDRST or I_HARDSENT flag is set, tell the Hard Reset - * thread */ - - if (notifSent == false) { - events = 0; - if (status.interrupta & FUSB_INTERRUPTA_I_HARDRST) { - events |= PDB_EVT_HARDRST_I_HARDRST; - notifSent = true; - } else if (status.interrupta & FUSB_INTERRUPTA_I_HARDSENT) { - events |= PDB_EVT_HARDRST_I_HARDSENT; - notifSent = true; - } - if (events) { - ResetHandler::notify(events); - } - } /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy * Engine thread */ if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP && status.status1 & FUSB_STATUS1_OVRTEMP) { PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); - notifSent = true; } } } diff --git a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp index 0e8464fc..21eac827 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/policy_engine.cpp @@ -20,7 +20,6 @@ #include "int_n.h" #include #include "protocol_tx.h" -#include "hard_reset.h" #include "fusb302b.h" bool PolicyEngine::pdNegotiationComplete; int PolicyEngine::current_voltage_mv; @@ -189,15 +188,15 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_wait_cap() { && PD_NUMOBJ_GET(&tempMessage) > 0) { /* First, determine what PD revision we're using */ if ((hdr_template & PD_HDR_SPECREV) == PD_SPECREV_1_0) { -// /* If the other end is using at least version 3.0, we'll -// * use version 3.0. */ -// if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { -// hdr_template |= PD_SPECREV_3_0; -// /* Otherwise, use 2.0. Don't worry about the 1.0 case -// * because we don't have hardware for PD 1.0 signaling. */ -// } else { - hdr_template |= PD_SPECREV_2_0; -// } + /* If the other end is using at least version 3.0, we'll + * use version 3.0. */ + if ((tempMessage.hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) { + hdr_template |= PD_SPECREV_3_0; + /* Otherwise, use 2.0. Don't worry about the 1.0 case + * because we don't have hardware for PD 1.0 signaling. */ + } else { + hdr_template |= PD_SPECREV_2_0; + } } return PESinkEvalCap; /* If the message was a Soft_Reset, do the soft reset procedure */ @@ -516,11 +515,8 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_hard_reset() { if (_hard_reset_counter > PD_N_HARD_RESET_COUNT) { return PESinkSourceUnresponsive; } - - /* Generate a hard reset signal */ - ResetHandler::notify(PDB_EVT_HARDRST_RESET); - waitForEvent(PDB_EVT_PE_HARD_SENT); - + //So, we could send a hardreset here; however that will cause a power cycle on the PSU end.. Which will then reset this MCU + //So therefore we went get anywhere :) /* Increment HardResetCounter */ _hard_reset_counter++; @@ -537,9 +533,6 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_transition_default() { /* Since we never change our data role from UFP, there is no reason to set * it here. */ - /* Tell the protocol layer we're done with the reset */ - ResetHandler::notify( PDB_EVT_HARDRST_DONE); - return PESinkStartup; } diff --git a/workspace/TS100/Core/Drivers/I2CBB.cpp b/workspace/TS100/Core/Drivers/I2CBB.cpp index c21a3a97..200fecfe 100644 --- a/workspace/TS100/Core/Drivers/I2CBB.cpp +++ b/workspace/TS100/Core/Drivers/I2CBB.cpp @@ -17,28 +17,31 @@ void I2CBB::init() { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = SDA2_Pin ; + GPIO_InitStruct.Pin = SDA2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SDA2_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; - GPIO_InitStruct.Pin = SCL2_Pin; + GPIO_InitStruct.Pin = SCL2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(SCL2_GPIO_Port, &GPIO_InitStruct); SOFT_SDA_HIGH(); SOFT_SCL_HIGH(); - I2CSemaphore = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer); - I2CSemaphore2 = xSemaphoreCreateMutexStatic (&xSemaphoreBuffer2); + I2CSemaphore = xSemaphoreCreateMutexStatic(&xSemaphoreBuffer); + I2CSemaphore2 = xSemaphoreCreateMutexStatic(&xSemaphoreBuffer2); unlock(); unlock2(); } bool I2CBB::probe(uint8_t address) { + if (!lock()) + return false; start(); bool ack = send(address); stop(); + unlock(); return ack; } diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index caf51e19..d7ed3e66 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -18,46 +18,42 @@ * * */ -class FRToSI2C -{ +class FRToSI2C { public: - static void init() - { - I2CSemaphore = nullptr; - } - static void FRToSInit() - { + static void FRToSInit() { I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); xSemaphoreGive(I2CSemaphore); + I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); + xSemaphoreGive(I2CSemaphore2); } static void CpltCallback(); //Normal Tx Callback static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); - static void Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); + uint8_t *pData, uint16_t Size); + static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size); //Returns true if device ACK's being addressed static bool probe(uint16_t DevAddress); - static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); + static bool Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, - uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); - static void I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); + uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); + static bool I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); - //These are public locks that let code lock the bus for back-to-back operations - static bool lock2(); static void unlock2(); - + static bool lock2(); private: - static bool lock(); static void unlock(); + static bool lock(); static void I2C_Unstick(); static SemaphoreHandle_t I2CSemaphore; static StaticSemaphore_t xSemaphoreBuffer; + static SemaphoreHandle_t I2CSemaphore2; + static StaticSemaphore_t xSemaphoreBuffer2; }; #endif /* FRTOSI2C_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.cpp b/workspace/TS100/Core/Drivers/LIS2DH12.cpp index dfd2de43..888e1231 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.cpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.cpp @@ -10,55 +10,43 @@ #include "LIS2DH12.hpp" #include "cmsis_os.h" -typedef struct -{ +typedef struct { const uint8_t reg; const uint8_t value; } LIS_REG; -static const LIS_REG i2c_registers[] = {{LIS_CTRL_REG1, 0x17}, // 25Hz - {LIS_CTRL_REG2, 0b00001000}, // Highpass filter off - {LIS_CTRL_REG3, 0b01100000}, // Setup interrupt pins - {LIS_CTRL_REG4, 0b00001000}, // Block update mode off, HR on - {LIS_CTRL_REG5, 0b00000010}, - {LIS_CTRL_REG6, 0b01100010}, - //Basically setup the unit to run, and enable 4D orientation detection - {LIS_INT2_CFG, 0b01111110}, //setup for movement detection - {LIS_INT2_THS, 0x28}, - {LIS_INT2_DURATION, 64}, - {LIS_INT1_CFG, 0b01111110}, - {LIS_INT1_THS, 0x28}, - {LIS_INT1_DURATION, 64}}; +static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz + { LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off + { LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins + { LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on + { LIS_CTRL_REG5, 0b00000010 }, { LIS_CTRL_REG6, 0b01100010 }, + //Basically setup the unit to run, and enable 4D orientation detection + { LIS_INT2_CFG, 0b01111110 }, //setup for movement detection + { LIS_INT2_THS, 0x28 }, { LIS_INT2_DURATION, 64 }, { + LIS_INT1_CFG, 0b01111110 }, { LIS_INT1_THS, 0x28 }, { + LIS_INT1_DURATION, 64 } }; -void LIS2DH12::initalize() -{ -#ifdef ACCEL_LIS +void LIS2DH12::initalize() { for (size_t index = 0; - index < (sizeof(i2c_registers) / sizeof(i2c_registers[0])); - index++) - { + index < (sizeof(i2c_registers) / sizeof(i2c_registers[0])); + index++) { FRToSI2C::I2C_RegisterWrite(LIS2DH_I2C_ADDRESS, - i2c_registers[index].reg, i2c_registers[index].value); + i2c_registers[index].reg, i2c_registers[index].value); } -#endif } -void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) -{ -#ifdef ACCEL_LIS +void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { std::array sensorData; FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8, - reinterpret_cast(sensorData.begin()), - sensorData.size() * sizeof(int16_t)); + reinterpret_cast(sensorData.begin()), + sensorData.size() * sizeof(int16_t)); x = sensorData[0]; y = sensorData[1]; z = sensorData[2]; -#endif } -bool LIS2DH12::detect() -{ +bool LIS2DH12::detect() { return FRToSI2C::probe(LIS2DH_I2C_ADDRESS); } diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.hpp b/workspace/TS100/Core/Drivers/LIS2DH12.hpp index e4bef50f..79346e98 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.hpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.hpp @@ -11,18 +11,15 @@ #include "LIS2DH12_defines.hpp" #include "BSP.h" -class LIS2DH12 -{ +class LIS2DH12 { public: static bool detect(); static void initalize(); //1 = rh, 2,=lh, 8=flat - static Orientation getOrientation() - { + static Orientation getOrientation() { #ifdef LIS_ORI_FLIP uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, - LIS_INT2_SRC) >> - 2); + LIS_INT2_SRC) >> 2); if (val == 8) val = 3; else if (val == 1) @@ -33,13 +30,11 @@ public: val = 3; return static_cast(val); #endif -#ifdef ACCEL_LIS - return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, LIS_INT2_SRC) >> 2) - 1); -#else - return Orientation::ORIENTATION_FLAT; +#ifdef MODEL_TS100 + return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1); #endif } - static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z); + static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z); private: }; diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h new file mode 100644 index 00000000..e2c1c4c7 --- /dev/null +++ b/workspace/TS100/Core/Inc/FreeRTOSConfig.h @@ -0,0 +1,171 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ +/* Section where include file can be added */ +/* USER CODE END Includes */ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +#define configUSE_PREEMPTION 1 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMAX_PRIORITIES ( 6 ) +#define configMINIMAL_STACK_SIZE ((uint16_t)256) +#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ +#define configMAX_TASK_NAME_LEN ( 32 ) +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_TIMERS 0 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Set the following definitions to 1 to include the API function, or zero + to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 0 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" + function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 + +/* The highest interrupt priority that can be used by any interrupt service + routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL + INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER + PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic + to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* Normal assert() semantics without relying on the provision of an assert.h + header file. */ +/* USER CODE BEGIN 1 */ +#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} +/* USER CODE END 1 */ + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +#if configUSE_TIMERS +#define configTIMER_TASK_PRIORITY 2 +#define configTIMER_QUEUE_LENGTH 8 +#define configTIMER_TASK_STACK_DEPTH (512/4) +#endif + +#endif /* FREERTOS_CONFIG_H */ diff --git a/workspace/TS100/Core/Inc/FreeRTOSHooks.h b/workspace/TS100/Core/Inc/FreeRTOSHooks.h index c7653775..8dca47e6 100644 --- a/workspace/TS100/Core/Inc/FreeRTOSHooks.h +++ b/workspace/TS100/Core/Inc/FreeRTOSHooks.h @@ -9,19 +9,20 @@ #define INC_FREERTOSHOOKS_H_ #include "FreeRTOS.h" +#include "cmsis_os.h" #include "unit.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - // RToS - void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, - StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize); - void vApplicationIdleHook(void); +// RToS +void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, + StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize); +void vApplicationIdleHook(void); #ifdef __cplusplus } #endif + #endif /* INC_FREERTOSHOOKS_H_ */ diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index 8ddd11d5..08e4b830 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -11,7 +11,7 @@ #define SETTINGS_H_ #include #include "unit.h" -#define SETTINGSVERSION (0x20) +#define SETTINGSVERSION ( 0x21 ) /*Change this if you change the struct below to prevent people getting \ out of sync*/ @@ -19,48 +19,45 @@ * This struct must be a multiple of 2 bytes as it is saved / restored from * flash in uint16_t chunks */ -typedef struct -{ - uint8_t version; // Used to track if a reset is needed on firmware upgrade +typedef struct { + uint8_t version; // Used to track if a reset is needed on firmware upgrade - uint16_t SolderingTemp; // current set point for the iron - uint16_t SleepTemp; // temp to drop to in sleep - uint8_t SleepTime; // minutes timeout to sleep - uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80 - uint8_t OrientationMode : 2; // If true we want to invert the display for lefties - uint8_t sensitivity : 4; // Sensitivity of accelerometer (5 bits) - uint8_t autoStartMode : 2; // Should the unit automatically jump straight - // into soldering mode when power is applied - uint8_t ShutdownTime; // Time until unit shuts down if left alone - uint8_t boostModeEnabled : 1; // Boost mode swaps BUT_A in soldering mode to - // temporary soldering temp over-ride - uint8_t coolingTempBlink : 1; // Should the temperature blink on the cool - // down screen until its <50C - uint8_t detailedIDLE : 1; // Detailed idle screen - uint8_t detailedSoldering : 1; // Detailed soldering screens + uint16_t SolderingTemp; // current set point for the iron + uint16_t SleepTemp; // temp to drop to in sleep + uint8_t SleepTime; // minutes timeout to sleep + uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80 + uint8_t OrientationMode :2; // If true we want to invert the display for lefties + uint8_t sensitivity :4; // Sensitivity of accelerometer (5 bits) + uint8_t autoStartMode :2; // Should the unit automatically jump straight + // into soldering mode when power is applied + uint8_t ShutdownTime; // Time until unit shuts down if left alone + + uint8_t coolingTempBlink :1; // Should the temperature blink on the cool + // down screen until its <50C + uint8_t detailedIDLE :1; // Detailed idle screen + uint8_t detailedSoldering :1; // Detailed soldering screens #ifdef ENABLED_FAHRENHEIT_SUPPORT - uint8_t temperatureInF : 1; // Should the temp be in F or C (true is F) + uint8_t temperatureInF :1; // Should the temp be in F or C (true is F) #endif - uint8_t descriptionScrollSpeed : 1; // Description scroll speed - uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) + uint8_t descriptionScrollSpeed :1; // Description scroll speed + uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) - uint16_t voltageDiv; // Voltage divisor factor - uint16_t BoostTemp; // Boost mode set point for the iron + uint16_t voltageDiv; // Voltage divisor factor + uint16_t BoostTemp; // Boost mode set point for the iron uint16_t CalibrationOffset; // This stores the temperature offset for this tip // in the iron. - uint8_t powerLimitEnable; // Allow toggling of power limit without changing value - uint8_t powerLimit; // Maximum power iron allowed to output + uint8_t powerLimit; // Maximum power iron allowed to output uint16_t TipGain; // uV/C * 10, it can be used to convert tip thermocouple voltage to temperateture TipV/TipGain = TipTemp uint8_t ReverseButtonTempChangeEnabled; // Change the plus and minus button assigment - uint16_t TempChangeLongStep; // Change the plus and minus button assigment - uint16_t TempChangeShortStep; // Change the plus and minus button assigment + uint16_t TempChangeLongStep; // Change the plus and minus button assigment + uint16_t TempChangeShortStep; // Change the plus and minus button assigment - uint32_t padding; // This is here for in case we are not an even divisor so - // that nothing gets cut off - //MUST BE LAST + uint32_t padding; // This is here for in case we are not an even divisor so + // that nothing gets cut off + //MUST BE LAST } systemSettingsType; diff --git a/workspace/TS100/Core/Inc/Translation.h b/workspace/TS100/Core/Inc/Translation.h index 614ea12f..b0ef244b 100644 --- a/workspace/TS100/Core/Inc/Translation.h +++ b/workspace/TS100/Core/Inc/Translation.h @@ -9,16 +9,12 @@ #define TRANSLATION_H_ #include "unit.h" #include "stdint.h" -enum ShortNameType { - SHORT_NAME_SINGLE_LINE = 1, SHORT_NAME_DOUBLE_LINE = 2, -}; extern const uint8_t USER_FONT_12[]; extern const uint8_t USER_FONT_6x8[]; /* * When SettingsShortNameType is SHORT_NAME_SINGLE_LINE * use SettingsShortNames as SettingsShortNames[16][1].. second column undefined */ -extern const enum ShortNameType SettingsShortNameType; extern const char *SettingsShortNames[28][2]; extern const char *SettingsDescriptions[28]; extern const char *SettingsMenuEntries[4]; diff --git a/workspace/TS100/Core/Inc/gui.hpp b/workspace/TS100/Core/Inc/gui.hpp index 1b7827d3..b199a376 100644 --- a/workspace/TS100/Core/Inc/gui.hpp +++ b/workspace/TS100/Core/Inc/gui.hpp @@ -11,7 +11,7 @@ #include "Settings.h" #include "BSP.h" -#define PRESS_ACCEL_STEP 3 +#define PRESS_ACCEL_STEP 30 #define PRESS_ACCEL_INTERVAL_MIN 100 #define PRESS_ACCEL_INTERVAL_MAX 300 @@ -19,16 +19,12 @@ //Declarations for all the methods for the settings menu (at end of this file) -//Wrapper for holding a function pointer -typedef struct state_func_t { - void (*func)(void); -} state_func; - //Struct for holding the function pointers and descriptions typedef struct { const char *description; - const state_func incrementHandler; - const state_func draw; + // return true if increment reached the maximum value + bool (* const incrementHandler)(void); + void (* const draw)(void); } menuitem; void enterSettingsMenu(); diff --git a/workspace/TS100/Core/Inc/main.hpp b/workspace/TS100/Core/Inc/main.hpp index 0024c3a4..0a45c1c2 100644 --- a/workspace/TS100/Core/Inc/main.hpp +++ b/workspace/TS100/Core/Inc/main.hpp @@ -8,20 +8,19 @@ extern uint32_t currentTempTargetDegC; extern bool settingsWereReset; extern bool usb_pd_available; #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - void vApplicationStackOverflowHook(TaskHandle_t *pxTask, - signed portCHAR *pcTaskName); +void vApplicationStackOverflowHook(TaskHandle_t *pxTask, + signed portCHAR *pcTaskName); - //Threads - void startGUITask(void const *argument); - void startPIDTask(void const *argument); - void startMOVTask(void const *argument); - extern TaskHandle_t pidTaskNotification; - extern uint8_t accelInit; - extern uint32_t lastMovementTime; +//Threads +void startGUITask(void const *argument); +void startPIDTask(void const *argument); +void startMOVTask(void const *argument); +extern TaskHandle_t pidTaskNotification; +extern uint8_t accelInit; +extern uint32_t lastMovementTime; #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/Inc/stm32f1xx_it.h b/workspace/TS100/Core/Inc/stm32f1xx_it.h index 37d70a0e..c40b6bdf 100644 --- a/workspace/TS100/Core/Inc/stm32f1xx_it.h +++ b/workspace/TS100/Core/Inc/stm32f1xx_it.h @@ -1,67 +1,67 @@ -/** - ****************************************************************************** - * @file stm32f1xx_it.h - * @brief This file contains the headers of the interrupt handlers. - ****************************************************************************** - * - * COPYRIGHT(c) 2017 STMicroelectronics - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F1xx_IT_H -#define __STM32F1xx_IT_H - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -void NMI_Handler(void); -void HardFault_Handler(void); -void MemManage_Handler(void); -void BusFault_Handler(void); -void UsageFault_Handler(void); -void DebugMon_Handler(void); -void SysTick_Handler(void); -void DMA1_Channel1_IRQHandler(void); -void DMA1_Channel6_IRQHandler(void); -void DMA1_Channel7_IRQHandler(void); -void ADC1_2_IRQHandler(void); -void TIM1_UP_IRQHandler(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __STM32F1xx_IT_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * @file stm32f1xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * + * COPYRIGHT(c) 2017 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F1xx_IT_H +#define __STM32F1xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void DebugMon_Handler(void); +void SysTick_Handler(void); +void DMA1_Channel1_IRQHandler(void); +void DMA1_Channel6_IRQHandler(void); +void DMA1_Channel7_IRQHandler(void); +void ADC1_2_IRQHandler(void); +void TIM1_UP_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F1xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/workspace/TS100/Core/Src/FreeRTOSHooks.c b/workspace/TS100/Core/Src/FreeRTOSHooks.c index ee29864f..d801f9d9 100644 --- a/workspace/TS100/Core/Src/FreeRTOSHooks.c +++ b/workspace/TS100/Core/Src/FreeRTOSHooks.c @@ -7,9 +7,7 @@ #include "FreeRTOSHooks.h" #include "BSP.h" -#include "cmsis_os.h" -void vApplicationIdleHook(void) -{ +void vApplicationIdleHook(void) { resetWatchdog(); } @@ -18,19 +16,19 @@ static StaticTask_t xIdleTaskTCBBuffer; static StackType_t xIdleStack[configMINIMAL_STACK_SIZE]; void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, - StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) -{ + StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) { *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer; *ppxIdleTaskStackBuffer = &xIdleStack[0]; *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* place for user code */ } + void vApplicationStackOverflowHook(TaskHandle_t *pxTask, - signed portCHAR *pcTaskName) -{ - (void)pxTask; - (void)pcTaskName; - // We dont have a good way to handle a stack overflow at this point in time + signed portCHAR *pcTaskName) { + (void) pxTask; + (void) pcTaskName; + +// We dont have a good way to handle a stack overflow at this point in time reboot(); } diff --git a/workspace/TS100/Core/Src/Settings.cpp b/workspace/TS100/Core/Src/Settings.cpp index 716d7c9c..77cc341f 100644 --- a/workspace/TS100/Core/Src/Settings.cpp +++ b/workspace/TS100/Core/Src/Settings.cpp @@ -12,9 +12,7 @@ #include "Setup.h" #include "../../configuration.h" #include "BSP.h" -#define FLASH_ADDR \ - (0x8000000 | \ - 0xFC00) /*Flash start OR'ed with the maximum amount of flash - 1024 bytes*/ + #include "string.h" volatile systemSettingsType systemSettings; @@ -65,7 +63,6 @@ void resetSettings() { systemSettings.sensitivity = SENSITIVITY; // Default high sensitivity systemSettings.voltageDiv = VOLTAGE_DIV; // Default divider from schematic systemSettings.ShutdownTime = SHUTDOWN_TIME; // How many minutes until the unit turns itself off - systemSettings.boostModeEnabled = BOOST_MODE_ENABLED; // Default to having boost mode on as most people prefer it systemSettings.BoostTemp = BOOST_TEMP; // default to 400C systemSettings.autoStartMode = AUTO_START_MODE; // Auto start off for safety systemSettings.coolingTempBlink = COOLING_TEMP_BLINK; // Blink the temperature on the cooling screen when its > 50C @@ -73,7 +70,6 @@ void resetSettings() { systemSettings.temperatureInF = TEMPERATURE_INF; // default to 0 #endif systemSettings.descriptionScrollSpeed = DESCRIPTION_SCROLL_SPEED; // default to slow - systemSettings.powerLimitEnable = POWER_LIMIT_ENABLE; // Default to no power limit systemSettings.CalibrationOffset = CALIBRATION_OFFSET; // the adc offset in uV systemSettings.powerLimit = POWER_LIMIT; // 30 watts default limit systemSettings.ReverseButtonTempChangeEnabled = REVERSE_BUTTON_TEMP_CHANGE; // diff --git a/workspace/TS100/Core/Src/freertos.c b/workspace/TS100/Core/Src/freertos.c index 9dd3a9c0..dd171c8e 100644 --- a/workspace/TS100/Core/Src/freertos.c +++ b/workspace/TS100/Core/Src/freertos.c @@ -1,52 +1,52 @@ -/** - ****************************************************************************** - * File Name : freertos.c - * Description : Code for freertos applications - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "FreeRTOS.h" -#include "task.h" -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +/** + ****************************************************************************** + * File Name : freertos.c + * Description : Code for freertos applications + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "FreeRTOS.h" +#include "task.h" +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index eaf71811..2431a7a9 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -18,70 +18,66 @@ void gui_Menu(const menuitem *menu); #ifdef MODEL_TS100 -static void settings_setInputVRange(void); +static bool settings_setInputVRange(void); static void settings_displayInputVRange(void); #else -static void settings_setInputPRange(void); +static bool settings_setInputPRange(void); static void settings_displayInputPRange(void); #endif -static void settings_setSleepTemp(void); +static bool settings_setSleepTemp(void); static void settings_displaySleepTemp(void); -static void settings_setSleepTime(void); +static bool settings_setSleepTime(void); static void settings_displaySleepTime(void); -static void settings_setShutdownTime(void); +static bool settings_setShutdownTime(void); static void settings_displayShutdownTime(void); -static void settings_setSensitivity(void); +static bool settings_setSensitivity(void); static void settings_displaySensitivity(void); #ifdef ENABLED_FAHRENHEIT_SUPPORT -static void settings_setTempF(void); +static bool settings_setTempF(void); static void settings_displayTempF(void); #endif -static void settings_setAdvancedSolderingScreens(void); +static bool settings_setAdvancedSolderingScreens(void); static void settings_displayAdvancedSolderingScreens(void); -static void settings_setAdvancedIDLEScreens(void); +static bool settings_setAdvancedIDLEScreens(void); static void settings_displayAdvancedIDLEScreens(void); -static void settings_setScrollSpeed(void); +static bool settings_setScrollSpeed(void); static void settings_displayScrollSpeed(void); -static void settings_setPowerLimitEnable(void); -static void settings_displayPowerLimitEnable(void); -static void settings_setPowerLimit(void); +static bool settings_setPowerLimit(void); static void settings_displayPowerLimit(void); -static void settings_setDisplayRotation(void); +static bool settings_setDisplayRotation(void); static void settings_displayDisplayRotation(void); -static void settings_setBoostModeEnabled(void); -static void settings_displayBoostModeEnabled(void); -static void settings_setBoostTemp(void); +static bool settings_setBoostTemp(void); static void settings_displayBoostTemp(void); -static void settings_setAutomaticStartMode(void); +static bool settings_setAutomaticStartMode(void); static void settings_displayAutomaticStartMode(void); -static void settings_setCoolingBlinkEnabled(void); +static bool settings_setCoolingBlinkEnabled(void); static void settings_displayCoolingBlinkEnabled(void); -static void settings_setResetSettings(void); +static bool settings_setResetSettings(void); static void settings_displayResetSettings(void); -static void settings_setCalibrate(void); +static bool settings_setCalibrate(void); static void settings_displayCalibrate(void); -static void settings_setTipGain(void); +static bool settings_setTipGain(void); static void settings_displayTipGain(void); -static void settings_setCalibrateVIN(void); +static bool settings_setCalibrateVIN(void); static void settings_displayCalibrateVIN(void); static void settings_displayReverseButtonTempChangeEnabled(void); -static void settings_setReverseButtonTempChangeEnabled(void); +static bool settings_setReverseButtonTempChangeEnabled(void); static void settings_displayTempChangeShortStep(void); -static void settings_setTempChangeShortStep(void); +static bool settings_setTempChangeShortStep(void); static void settings_displayTempChangeLongStep(void); -static void settings_setTempChangeLongStep(void); +static bool settings_setTempChangeLongStep(void); static void settings_displayPowerPulse(void); -static void settings_setPowerPulse(void); +static bool settings_setPowerPulse(void); // Menu functions static void settings_displaySolderingMenu(void); -static void settings_enterSolderingMenu(void); +static bool settings_enterSolderingMenu(void); static void settings_displayPowerMenu(void); -static void settings_enterPowerMenu(void); +static bool settings_enterPowerMenu(void); static void settings_displayUIMenu(void); -static void settings_enterUIMenu(void); +static bool settings_enterUIMenu(void); static void settings_displayAdvancedMenu(void); -static void settings_enterAdvancedMenu(void); +static bool settings_enterAdvancedMenu(void); /* * Root Settings Menu * @@ -129,21 +125,19 @@ const menuitem rootSettingsMenu[] { * Exit */ #ifdef MODEL_TS100 - { (const char*) SettingsDescriptions[0], { settings_setInputVRange }, { - settings_displayInputVRange } }, /*Voltage input*/ + { (const char*) SettingsDescriptions[0], settings_setInputVRange, + settings_displayInputVRange }, /*Voltage input*/ #else - { (const char*) SettingsDescriptions[20], { settings_setInputPRange }, { - settings_displayInputPRange } }, /*Voltage input*/ + { (const char*) SettingsDescriptions[19], settings_setInputPRange, + settings_displayInputPRange }, /*Voltage input*/ #endif - { (const char*) NULL, { settings_enterSolderingMenu }, { - settings_displaySolderingMenu } }, /*Soldering*/ - { (const char*) NULL, { settings_enterPowerMenu }, { - settings_displayPowerMenu } }, /*Sleep Options Menu*/ - { (const char*) NULL, { settings_enterUIMenu }, - { settings_displayUIMenu } }, /*UI Menu*/ - { (const char*) NULL, { settings_enterAdvancedMenu }, { - settings_displayAdvancedMenu } }, /*Advanced Menu*/ - { NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE + { (const char*) NULL, settings_enterSolderingMenu, + settings_displaySolderingMenu }, /*Soldering*/ + { (const char*) NULL, settings_enterPowerMenu, settings_displayPowerMenu }, /*Sleep Options Menu*/ + { (const char*) NULL, settings_enterUIMenu, settings_displayUIMenu }, /*UI Menu*/ + { (const char*) NULL, settings_enterAdvancedMenu, + settings_displayAdvancedMenu }, /*Advanced Menu*/ + { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem solderingMenu[] = { @@ -154,17 +148,15 @@ const menuitem solderingMenu[] = { * Temp change short step * Temp change long step */ -{ (const char*) SettingsDescriptions[8], { settings_setBoostModeEnabled }, { - settings_displayBoostModeEnabled } }, /*Enable Boost*/ -{ (const char*) SettingsDescriptions[9], { settings_setBoostTemp }, { - settings_displayBoostTemp } }, /*Boost Temp*/ -{ (const char*) SettingsDescriptions[10], { settings_setAutomaticStartMode }, { - settings_displayAutomaticStartMode } }, /*Auto start*/ -{ (const char*) SettingsDescriptions[24], { settings_setTempChangeShortStep }, { - settings_displayTempChangeShortStep } }, /*Temp change short step*/ -{ (const char*) SettingsDescriptions[25], { settings_setTempChangeLongStep }, { - settings_displayTempChangeLongStep } }, /*Temp change long step*/ -{ NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE +{ (const char*) SettingsDescriptions[8], settings_setBoostTemp, + settings_displayBoostTemp }, /*Boost Temp*/ +{ (const char*) SettingsDescriptions[9], settings_setAutomaticStartMode, + settings_displayAutomaticStartMode }, /*Auto start*/ +{ (const char*) SettingsDescriptions[22], settings_setTempChangeShortStep, + settings_displayTempChangeShortStep }, /*Temp change short step*/ +{ (const char*) SettingsDescriptions[23], settings_setTempChangeLongStep, + settings_displayTempChangeLongStep }, /*Temp change long step*/ +{ NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem UIMenu[] = { /* @@ -176,21 +168,20 @@ const menuitem UIMenu[] = { * Reverse Temp change buttons + - */ #ifdef ENABLED_FAHRENHEIT_SUPPORT - { (const char*) SettingsDescriptions[5], { settings_setTempF }, { - settings_displayTempF } }, /* Temperature units*/ + { (const char*) SettingsDescriptions[5], settings_setTempF, + settings_displayTempF }, /* Temperature units*/ #endif - { (const char*) SettingsDescriptions[7], - { settings_setDisplayRotation }, { - settings_displayDisplayRotation } }, /*Display Rotation*/ - { (const char*) SettingsDescriptions[11], { - settings_setCoolingBlinkEnabled }, { - settings_displayCoolingBlinkEnabled } }, /*Cooling blink warning*/ - { (const char*) SettingsDescriptions[16], { settings_setScrollSpeed }, { - settings_displayScrollSpeed } }, /*Scroll Speed for descriptions*/ - { (const char*) SettingsDescriptions[23], { - settings_setReverseButtonTempChangeEnabled }, { - settings_displayReverseButtonTempChangeEnabled } }, /* Reverse Temp change buttons + - */ - { NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE + { (const char*) SettingsDescriptions[7], settings_setDisplayRotation, + settings_displayDisplayRotation }, /*Display Rotation*/ + { (const char*) SettingsDescriptions[10], + settings_setCoolingBlinkEnabled, + settings_displayCoolingBlinkEnabled }, /*Cooling blink warning*/ + { (const char*) SettingsDescriptions[15], settings_setScrollSpeed, + settings_displayScrollSpeed }, /*Scroll Speed for descriptions*/ + { (const char*) SettingsDescriptions[21], + settings_setReverseButtonTempChangeEnabled, + settings_displayReverseButtonTempChangeEnabled }, /* Reverse Temp change buttons + - */ + { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem PowerMenu[] = { /* @@ -199,20 +190,19 @@ const menuitem PowerMenu[] = { * Shutdown Time * Motion Sensitivity */ -{ (const char*) SettingsDescriptions[1], { settings_setSleepTemp }, { - settings_displaySleepTemp } }, /*Sleep Temp*/ -{ (const char*) SettingsDescriptions[2], { settings_setSleepTime }, { - settings_displaySleepTime } }, /*Sleep Time*/ -{ (const char*) SettingsDescriptions[3], { settings_setShutdownTime }, { - settings_displayShutdownTime } }, /*Shutdown Time*/ -{ (const char*) SettingsDescriptions[4], { settings_setSensitivity }, { - settings_displaySensitivity } }, /* Motion Sensitivity*/ -{ NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE +{ (const char*) SettingsDescriptions[1], settings_setSleepTemp, + settings_displaySleepTemp }, /*Sleep Temp*/ +{ (const char*) SettingsDescriptions[2], settings_setSleepTime, + settings_displaySleepTime }, /*Sleep Time*/ +{ (const char*) SettingsDescriptions[3], settings_setShutdownTime, + settings_displayShutdownTime }, /*Shutdown Time*/ +{ (const char*) SettingsDescriptions[4], settings_setSensitivity, + settings_displaySensitivity }, /* Motion Sensitivity*/ +{ NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem advancedMenu[] = { /* - * Power limit enable * Power limit * Detailed IDLE * Detailed Soldering @@ -221,34 +211,25 @@ const menuitem advancedMenu[] = { * Reset Settings * Power Pulse */ -{ (const char*) SettingsDescriptions[21], { settings_setPowerLimitEnable }, { - settings_displayPowerLimitEnable } }, /*Power limit enable*/ -{ (const char*) SettingsDescriptions[22], { settings_setPowerLimit }, { - settings_displayPowerLimit } }, /*Power limit*/ -{ (const char*) SettingsDescriptions[6], { settings_setAdvancedIDLEScreens }, { - settings_displayAdvancedIDLEScreens } }, /* Advanced idle screen*/ -{ (const char*) SettingsDescriptions[15], - { settings_setAdvancedSolderingScreens }, { - settings_displayAdvancedSolderingScreens } }, /* Advanced soldering screen*/ -{ (const char*) SettingsDescriptions[13], { settings_setResetSettings }, { - settings_displayResetSettings } }, /*Resets settings*/ -{ (const char*) SettingsDescriptions[12], { settings_setCalibrate }, { - settings_displayCalibrate } }, /*Calibrate tip*/ -{ (const char*) SettingsDescriptions[14], { settings_setCalibrateVIN }, { - settings_displayCalibrateVIN } }, /*Voltage input cal*/ -{ (const char*) SettingsDescriptions[26], { settings_setPowerPulse }, { - settings_displayPowerPulse } }, /*Power Pulse adjustment */ -{ (const char*) SettingsDescriptions[27], { settings_setTipGain }, { - settings_displayTipGain } }, /*TipGain*/ -{ NULL, { NULL }, { NULL } } // end of menu marker. DO NOT REMOVE +{ (const char*) SettingsDescriptions[20], settings_setPowerLimit, + settings_displayPowerLimit }, /*Power limit*/ +{ (const char*) SettingsDescriptions[6], settings_setAdvancedIDLEScreens, + settings_displayAdvancedIDLEScreens }, /* Advanced idle screen*/ +{ (const char*) SettingsDescriptions[14], settings_setAdvancedSolderingScreens, + settings_displayAdvancedSolderingScreens }, /* Advanced soldering screen*/ +{ (const char*) SettingsDescriptions[12], settings_setResetSettings, + settings_displayResetSettings }, /*Resets settings*/ +{ (const char*) SettingsDescriptions[11], settings_setCalibrate, + settings_displayCalibrate }, /*Calibrate tip*/ +{ (const char*) SettingsDescriptions[13], settings_setCalibrateVIN, + settings_displayCalibrateVIN }, /*Voltage input cal*/ +{ (const char*) SettingsDescriptions[24], settings_setPowerPulse, + settings_displayPowerPulse }, /*Power Pulse adjustment */ +{ (const char*) SettingsDescriptions[25], settings_setTipGain, + settings_displayTipGain }, /*TipGain*/ +{ NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; -static void printShortDescriptionSingleLine(uint32_t shortDescIndex) { - OLED::setFont(0); - OLED::setCharCursor(0, 0); - OLED::print(SettingsShortNames[shortDescIndex][0]); -} - static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) { OLED::setFont(1); OLED::setCharCursor(0, 0); @@ -267,11 +248,7 @@ static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) { static void printShortDescription(uint32_t shortDescIndex, uint16_t cursorCharPosition) { // print short description (default single line, explicit double line) - if (SettingsShortNameType == SHORT_NAME_DOUBLE_LINE) { - printShortDescriptionDoubleLine(shortDescIndex); - } else { - printShortDescriptionSingleLine(shortDescIndex); - } + printShortDescriptionDoubleLine(shortDescIndex); // prepare cursor for value OLED::setFont(0); @@ -329,10 +306,11 @@ static int userConfirmation(const char *message) { return 0; } #ifdef MODEL_TS100 -static void settings_setInputVRange(void) { +static bool settings_setInputVRange(void) { systemSettings.cutoutSetting = (systemSettings.cutoutSetting + 1) % 5; if (systemSettings.cutoutSetting) - systemSettings.powerLimitEnable = 0; // disable power limit if switching to a lipo power source + systemSettings.powerLimit = 0; // disable power limit if switching to a lipo power source + return systemSettings.cutoutSetting == 4; } static void settings_displayInputVRange(void) { @@ -346,14 +324,15 @@ static void settings_displayInputVRange(void) { } } #else -static void settings_setInputPRange(void) { +static bool settings_setInputPRange(void) { systemSettings.cutoutSetting = (systemSettings.cutoutSetting + 1) % 2; + return false; } static void settings_displayInputPRange(void) { printShortDescription(0, 5); //0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits) - /// TODO TS80P + // These are only used in QC3.0 modes switch (systemSettings.cutoutSetting) { case 0: OLED::printNumber(9, 2); @@ -370,19 +349,21 @@ static void settings_displayInputPRange(void) { } #endif -static void settings_setSleepTemp(void) { +static bool settings_setSleepTemp(void) { // If in C, 10 deg, if in F 20 deg #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { systemSettings.SleepTemp += 20; if (systemSettings.SleepTemp > 580) systemSettings.SleepTemp = 60; + return systemSettings.SleepTemp == 580; } else #endif { systemSettings.SleepTemp += 10; if (systemSettings.SleepTemp > 300) systemSettings.SleepTemp = 10; + return systemSettings.SleepTemp == 300; } } @@ -391,7 +372,7 @@ static void settings_displaySleepTemp(void) { OLED::printNumber(systemSettings.SleepTemp, 3); } -static void settings_setSleepTime(void) { +static bool settings_setSleepTime(void) { systemSettings.SleepTime++; // Go up 1 minute at a time if (systemSettings.SleepTime >= 16) { systemSettings.SleepTime = 0; // can't set time over 10 mins @@ -399,6 +380,7 @@ static void settings_setSleepTime(void) { // Remember that ^ is the time of no movement if (PCBVersion == 3) systemSettings.SleepTime = 0; // Disable sleep on no accel + return systemSettings.SleepTime == 15; } static void settings_displaySleepTime(void) { @@ -414,13 +396,14 @@ static void settings_displaySleepTime(void) { } } -static void settings_setShutdownTime(void) { +static bool settings_setShutdownTime(void) { systemSettings.ShutdownTime++; if (systemSettings.ShutdownTime > 60) { systemSettings.ShutdownTime = 0; // wrap to off } if (PCBVersion == 3) systemSettings.ShutdownTime = 0; // Disable shutdown on no accel + return systemSettings.ShutdownTime == 60; } static void settings_displayShutdownTime(void) { @@ -433,7 +416,7 @@ static void settings_displayShutdownTime(void) { } } #ifdef ENABLED_FAHRENHEIT_SUPPORT -static void settings_setTempF(void) { +static bool settings_setTempF(void) { systemSettings.temperatureInF = !systemSettings.temperatureInF; if (systemSettings.temperatureInF) { // Change sleep, boost and soldering temps to the F equiv @@ -457,6 +440,7 @@ static void settings_setTempF(void) { systemSettings.SolderingTemp *= 10; systemSettings.SleepTemp = systemSettings.SleepTemp / 10; systemSettings.SleepTemp *= 10; + return false; } static void settings_displayTempF(void) { @@ -466,9 +450,10 @@ static void settings_displayTempF(void) { } #endif -static void settings_setSensitivity(void) { +static bool settings_setSensitivity(void) { systemSettings.sensitivity++; systemSettings.sensitivity = systemSettings.sensitivity % 10; + return systemSettings.sensitivity == 9; } static void settings_displaySensitivity(void) { @@ -476,18 +461,20 @@ static void settings_displaySensitivity(void) { OLED::printNumber(systemSettings.sensitivity, 1, false); } -static void settings_setAdvancedSolderingScreens(void) { +static bool settings_setAdvancedSolderingScreens(void) { systemSettings.detailedSoldering = !systemSettings.detailedSoldering; + return false; } static void settings_displayAdvancedSolderingScreens(void) { - printShortDescription(15, 7); + printShortDescription(14, 7); OLED::drawCheckbox(systemSettings.detailedSoldering); } -static void settings_setAdvancedIDLEScreens(void) { +static bool settings_setAdvancedIDLEScreens(void) { systemSettings.detailedIDLE = !systemSettings.detailedIDLE; + return false; } static void settings_displayAdvancedIDLEScreens(void) { @@ -496,42 +483,39 @@ static void settings_displayAdvancedIDLEScreens(void) { OLED::drawCheckbox(systemSettings.detailedIDLE); } -static void settings_setPowerLimitEnable(void) { - systemSettings.powerLimitEnable = !systemSettings.powerLimitEnable; -} - -static void settings_displayPowerLimitEnable(void) { - printShortDescription(21, 7); - OLED::drawCheckbox(systemSettings.powerLimitEnable); -} - -static void settings_setPowerLimit(void) { - if (systemSettings.powerLimit >= MAX_POWER_LIMIT) - systemSettings.powerLimit = POWER_LIMIT_STEPS; - else - systemSettings.powerLimit += POWER_LIMIT_STEPS; +static bool settings_setPowerLimit(void) { + systemSettings.powerLimit += POWER_LIMIT_STEPS; + if (systemSettings.powerLimit > MAX_POWER_LIMIT) + systemSettings.powerLimit = 0; + return systemSettings.powerLimit + POWER_LIMIT_STEPS > MAX_POWER_LIMIT; } static void settings_displayPowerLimit(void) { - printShortDescription(22, 5); - OLED::printNumber(systemSettings.powerLimit, 2); - OLED::print(SymbolWatts); + printShortDescription(20, 5); + if (systemSettings.powerLimit == 0) { + OLED::print(OffString); + } else { + OLED::printNumber(systemSettings.powerLimit, 2); + OLED::print(SymbolWatts); + } } -static void settings_setScrollSpeed(void) { +static bool settings_setScrollSpeed(void) { if (systemSettings.descriptionScrollSpeed == 0) systemSettings.descriptionScrollSpeed = 1; else systemSettings.descriptionScrollSpeed = 0; + return false; } + static void settings_displayScrollSpeed(void) { - printShortDescription(16, 7); + printShortDescription(15, 7); OLED::print( (systemSettings.descriptionScrollSpeed) ? SettingFastChar : SettingSlowChar); } -static void settings_setDisplayRotation(void) { +static bool settings_setDisplayRotation(void) { systemSettings.OrientationMode++; systemSettings.OrientationMode = systemSettings.OrientationMode % 3; switch (systemSettings.OrientationMode) { @@ -547,6 +531,7 @@ static void settings_setDisplayRotation(void) { default: break; } + return systemSettings.OrientationMode == 2; } static void settings_displayDisplayRotation(void) { @@ -568,45 +553,53 @@ static void settings_displayDisplayRotation(void) { } } -static void settings_setBoostModeEnabled(void) { - systemSettings.boostModeEnabled = !systemSettings.boostModeEnabled; -} - -static void settings_displayBoostModeEnabled(void) { - printShortDescription(8, 7); - - OLED::drawCheckbox(systemSettings.boostModeEnabled); -} - -static void settings_setBoostTemp(void) { +static bool settings_setBoostTemp(void) { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { - systemSettings.BoostTemp += 20; // Go up 20F at a time - if (systemSettings.BoostTemp > 850) { - systemSettings.BoostTemp = 480; // loop back at 250 + if (systemSettings.BoostTemp == 0) { + systemSettings.BoostTemp = 480; // loop back at 480 + } else { + systemSettings.BoostTemp += 20; // Go up 20F at a time } + + if (systemSettings.BoostTemp > 850) { + systemSettings.BoostTemp = 0; // jump to off + } + return systemSettings.BoostTemp == 840; } else #endif { - systemSettings.BoostTemp += 10; // Go up 10C at a time - if (systemSettings.BoostTemp > 450) { + if (systemSettings.BoostTemp == 0) { systemSettings.BoostTemp = 250; // loop back at 250 + + } else { + systemSettings.BoostTemp += 10; // Go up 10C at a time } + if (systemSettings.BoostTemp > 450) { + systemSettings.BoostTemp = 0; //Go to off state + + } + return systemSettings.BoostTemp == 450; } } static void settings_displayBoostTemp(void) { - printShortDescription(9, 5); - OLED::printNumber(systemSettings.BoostTemp, 3); + printShortDescription(8, 5); + if (systemSettings.BoostTemp) { + OLED::printNumber(systemSettings.BoostTemp, 3); + } else { + OLED::print(OffString); + } } -static void settings_setAutomaticStartMode(void) { +static bool settings_setAutomaticStartMode(void) { systemSettings.autoStartMode++; systemSettings.autoStartMode %= 4; + return systemSettings.autoStartMode == 3; } static void settings_displayAutomaticStartMode(void) { - printShortDescription(10, 7); + printShortDescription(9, 7); switch (systemSettings.autoStartMode) { case 0: @@ -627,17 +620,18 @@ static void settings_displayAutomaticStartMode(void) { } } -static void settings_setCoolingBlinkEnabled(void) { +static bool settings_setCoolingBlinkEnabled(void) { systemSettings.coolingTempBlink = !systemSettings.coolingTempBlink; + return false; } static void settings_displayCoolingBlinkEnabled(void) { - printShortDescription(11, 7); + printShortDescription(10, 7); OLED::drawCheckbox(systemSettings.coolingTempBlink); } -static void settings_setResetSettings(void) { +static bool settings_setResetSettings(void) { if (userConfirmation(SettingsResetWarning)) { resetSettings(); @@ -648,10 +642,11 @@ static void settings_setResetSettings(void) { waitForButtonPressOrTimeout(2000); // 2 second timeout } + return false; } static void settings_displayResetSettings(void) { - printShortDescription(13, 7); + printShortDescription(12, 7); } static void setTipOffset() { @@ -686,20 +681,21 @@ static void setTipOffset() { //Provide the user the option to tune their own tip if custom is selected //If not only do single point tuning as per usual -static void settings_setCalibrate(void) { +static bool settings_setCalibrate(void) { if (userConfirmation(SettingsCalibrationWarning)) { // User confirmed // So we now perform the actual calculation setTipOffset(); } + return false; } static void settings_displayCalibrate(void) { - printShortDescription(12, 5); + printShortDescription(11, 5); } -static void settings_setCalibrateVIN(void) { +static bool settings_setCalibrateVIN(void) { // Jump to the voltage calibration subscreen OLED::setFont(0); OLED::clearScreen(); @@ -732,8 +728,7 @@ static void settings_setCalibrateVIN(void) { OLED::printNumber(systemSettings.voltageDiv, 3); OLED::refresh(); waitForButtonPressOrTimeout(1000); - return; - break; + return false; case BUTTON_NONE: default: break; @@ -757,9 +752,10 @@ static void settings_setCalibrateVIN(void) { } #endif } + return false; } -static void settings_setTipGain(void) { +static bool settings_setTipGain(void) { OLED::setFont(0); OLED::clearScreen(); @@ -783,8 +779,7 @@ static void settings_setTipGain(void) { case BUTTON_F_LONG: case BUTTON_B_LONG: saveSettings(); - return; - break; + return false; case BUTTON_NONE: default: break; @@ -800,57 +795,64 @@ static void settings_setTipGain(void) { systemSettings.TipGain = 300; } } + return false; } static void settings_displayTipGain(void) { - printShortDescription(27, 5); + printShortDescription(25, 5); } -static void settings_setReverseButtonTempChangeEnabled(void) { +static bool settings_setReverseButtonTempChangeEnabled(void) { systemSettings.ReverseButtonTempChangeEnabled = !systemSettings.ReverseButtonTempChangeEnabled; + return false; } static void settings_displayReverseButtonTempChangeEnabled(void) { - printShortDescription(23, 7); + printShortDescription(21, 7); OLED::drawCheckbox(systemSettings.ReverseButtonTempChangeEnabled); } -static void settings_setTempChangeShortStep(void) { +static bool settings_setTempChangeShortStep(void) { systemSettings.TempChangeShortStep += TEMP_CHANGE_SHORT_STEP; if (systemSettings.TempChangeShortStep > TEMP_CHANGE_SHORT_STEP_MAX) { systemSettings.TempChangeShortStep = TEMP_CHANGE_SHORT_STEP; // loop back at TEMP_CHANGE_SHORT_STEP_MAX } + return systemSettings.TempChangeShortStep == TEMP_CHANGE_SHORT_STEP_MAX; } + static void settings_displayTempChangeShortStep(void) { - printShortDescription(24, 6); + printShortDescription(22, 6); OLED::printNumber(systemSettings.TempChangeShortStep, 2); } -static void settings_setTempChangeLongStep(void) { +static bool settings_setTempChangeLongStep(void) { systemSettings.TempChangeLongStep += TEMP_CHANGE_LONG_STEP; if (systemSettings.TempChangeLongStep > TEMP_CHANGE_LONG_STEP_MAX) { systemSettings.TempChangeLongStep = TEMP_CHANGE_LONG_STEP; // loop back at TEMP_CHANGE_LONG_STEP_MAX } + return systemSettings.TempChangeLongStep == TEMP_CHANGE_LONG_STEP_MAX; } + static void settings_displayTempChangeLongStep(void) { - printShortDescription(25, 6); + printShortDescription(23, 6); OLED::printNumber(systemSettings.TempChangeLongStep, 2); } -static void settings_setPowerPulse(void) { +static bool settings_setPowerPulse(void) { systemSettings.KeepAwakePulse += POWER_PULSE_INCREMENT; systemSettings.KeepAwakePulse %= POWER_PULSE_MAX; + return systemSettings.KeepAwakePulse == POWER_PULSE_MAX - 1; } static void settings_displayPowerPulse(void) { - printShortDescription(26, 5); + printShortDescription(24, 5); if (systemSettings.KeepAwakePulse) { OLED::printNumber(systemSettings.KeepAwakePulse / 10, 1); OLED::print(SymbolDot); OLED::printNumber(systemSettings.KeepAwakePulse % 10, 1); } else { - OLED::drawCheckbox(false); + OLED::print(OffString); } } @@ -868,31 +870,35 @@ static void displayMenu(size_t index) { } static void settings_displayCalibrateVIN(void) { - printShortDescription(14, 5); + printShortDescription(13, 5); } static void settings_displaySolderingMenu(void) { displayMenu(0); } -static void settings_enterSolderingMenu(void) { +static bool settings_enterSolderingMenu(void) { gui_Menu(solderingMenu); + return false; } static void settings_displayPowerMenu(void) { displayMenu(1); } -static void settings_enterPowerMenu(void) { +static bool settings_enterPowerMenu(void) { gui_Menu(PowerMenu); + return false; } static void settings_displayUIMenu(void) { displayMenu(2); } -static void settings_enterUIMenu(void) { +static bool settings_enterUIMenu(void) { gui_Menu(UIMenu); + return false; } static void settings_displayAdvancedMenu(void) { displayMenu(3); } -static void settings_enterAdvancedMenu(void) { +static bool settings_enterAdvancedMenu(void) { gui_Menu(advancedMenu); + return false; } void gui_Menu(const menuitem *menu) { @@ -908,13 +914,15 @@ void gui_Menu(const menuitem *menu) { static bool enterGUIMenu = true; enterGUIMenu = true; uint8_t scrollContentSize = 0; + bool scrollBlink = false; + bool lastValue = false; - for (uint8_t i = 0; menu[i].draw.func != NULL; i++) { + for (uint8_t i = 0; menu[i].draw != NULL; i++) { scrollContentSize += 1; } // Animated menu opening. - if (menu[currentScreen].draw.func != NULL) { + if (menu[currentScreen].draw != NULL) { // This menu is drawn in a secondary framebuffer. // Then we play a transition from the current primary // framebuffer to the new buffer. @@ -923,12 +931,12 @@ void gui_Menu(const menuitem *menu) { OLED::setFont(0); OLED::setCursor(0, 0); OLED::clearScreen(); - menu[currentScreen].draw.func(); + menu[currentScreen].draw(); OLED::useSecondaryFramebuffer(false); OLED::transitionSecondaryFramebuffer(true); } - while ((menu[currentScreen].draw.func != NULL) && earlyExit == false) { + while ((menu[currentScreen].draw != NULL) && earlyExit == false) { OLED::setFont(0); OLED::setCursor(0, 0); // If the user has hesitated for >=3 seconds, show the long text @@ -936,10 +944,13 @@ void gui_Menu(const menuitem *menu) { if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) { OLED::clearScreen(); - menu[currentScreen].draw.func(); + menu[currentScreen].draw(); uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize; uint8_t position = OLED_HEIGHT * currentScreen / scrollContentSize; - OLED::drawScrollIndicator(position, indicatorHeight); + if (lastValue) + scrollBlink = !scrollBlink; + if (!lastValue || !scrollBlink) + OLED::drawScrollIndicator(position, indicatorHeight); lastOffset = -1; lcdRefresh = true; } else { @@ -978,16 +989,16 @@ void gui_Menu(const menuitem *menu) { case BUTTON_F_SHORT: // increment if (descriptionStart == 0) { - if (menu[currentScreen].incrementHandler.func != NULL) { + if (menu[currentScreen].incrementHandler != NULL) { enterGUIMenu = false; - menu[currentScreen].incrementHandler.func(); + lastValue = menu[currentScreen].incrementHandler(); if (enterGUIMenu) { OLED::useSecondaryFramebuffer(true); OLED::setFont(0); OLED::setCursor(0, 0); OLED::clearScreen(); - menu[currentScreen].draw.func(); + menu[currentScreen].draw(); OLED::useSecondaryFramebuffer(false); OLED::transitionSecondaryFramebuffer(false); } @@ -999,16 +1010,23 @@ void gui_Menu(const menuitem *menu) { descriptionStart = 0; break; case BUTTON_B_SHORT: - if (descriptionStart == 0) + if (descriptionStart == 0) { currentScreen++; - else + lastValue = false; + } else descriptionStart = 0; break; case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > + if ((int) (xTaskGetTickCount() - autoRepeatTimer + + autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { - menu[currentScreen].incrementHandler.func(); - autoRepeatTimer = xTaskGetTickCount(); + if ((lastValue = menu[currentScreen].incrementHandler())) + autoRepeatTimer = 1000; + else + autoRepeatTimer = 0; + + autoRepeatTimer += xTaskGetTickCount(); + descriptionStart = 0; autoRepeatAcceleration += PRESS_ACCEL_STEP; diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 89d2bc45..9c9da2dc 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -12,8 +12,6 @@ #include "Settings.h" #include "cmsis_os.h" uint8_t PCBVersion = 0; -// File local variables -bool usb_pd_available = false; bool settingsWereReset = false; // FreeRTOS variables @@ -32,44 +30,17 @@ uint32_t MOVTaskBuffer[MOVTaskStackSize]; osStaticThreadDef_t MOVTaskControlBlock; // End FreeRTOS - // Main sets up the hardware then hands over to the FreeRTOS kernel int main(void) { preRToSInit(); - setTipX10Watts(0); // force tip off resetWatchdog(); - OLED::initialize(); // start up the LCD OLED::setFont(0); // default to bigger font // Testing for which accelerometer is mounted - resetWatchdog(); - usb_pd_available = usb_pd_detect(); - resetWatchdog(); settingsWereReset = restoreSettings(); // load the settings from flash -#ifdef ACCEL_MMA - if (MMA8652FC::detect()) { - PCBVersion = 1; - MMA8652FC::initalize(); // this sets up the I2C registers - } else -#endif -#ifdef ACCEL_LIS - if (LIS2DH12::detect()) { - PCBVersion = 2; - // Setup the ST Accelerometer - LIS2DH12::initalize(); // startup the accelerometer - } else -#endif - { - PCBVersion = 3; - systemSettings.SleepTime = 0; - systemSettings.ShutdownTime = 0; // No accel -> disable sleep - systemSettings.sensitivity = 0; - } resetWatchdog(); - /* Create the thread(s) */ /* definition and creation of GUITask */ - osThreadStaticDef(GUITask, startGUITask, osPriorityBelowNormal, 0, GUITaskStackSize, GUITaskBuffer, &GUITaskControlBlock); GUITaskHandle = osThreadCreate(osThread(GUITask), NULL); diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index afeceeeb..280655b6 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -439,7 +439,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { break; case BUTTON_F_LONG: // if boost mode is enabled turn it on - if (systemSettings.boostModeEnabled) + if (systemSettings.BoostTemp) boostModeOn = true; break; case BUTTON_F_SHORT: @@ -632,6 +632,7 @@ void showDebugMenu(void) { uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { + OLED::initialize(); // start up the LCD uint8_t tempWarningState = 0; bool buttonLockout = false; diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 4ca5e54b..1fe57cd1 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -23,8 +23,34 @@ uint8_t accelInit = 0; uint32_t lastMovementTime = 0; void startMOVTask(void const *argument __unused) { - OLED::setRotation(systemSettings.OrientationMode & 1); +#ifdef ACCEL_MMA + if (MMA8652FC::detect()) { + PCBVersion = 1; + MMA8652FC::initalize(); // this sets up the I2C registers + } else +#endif +#ifdef ACCEL_LIS + if (LIS2DH12::detect()) { + PCBVersion = 2; + // Setup the ST Accelerometer + LIS2DH12::initalize(); // startup the accelerometer + } else +#endif + { + PCBVersion = 3; + systemSettings.SleepTime = 0; + systemSettings.ShutdownTime = 0; // No accel -> disable sleep + systemSettings.sensitivity = 0; + } postRToSInit(); + OLED::setRotation(systemSettings.OrientationMode & 1); + + if ((PCBVersion == 1 + || PCBVersion == 2) + && (systemSettings.autoStartMode == 2 + || systemSettings.autoStartMode == 3)) + osDelay(2000); + lastMovementTime = 0; int16_t datax[MOVFilter] = { 0 }; int16_t datay[MOVFilter] = { 0 }; diff --git a/workspace/TS100/Core/Threads/PIDThread.cpp b/workspace/TS100/Core/Threads/PIDThread.cpp index 95ffedd1..72f7606f 100644 --- a/workspace/TS100/Core/Threads/PIDThread.cpp +++ b/workspace/TS100/Core/Threads/PIDThread.cpp @@ -20,8 +20,7 @@ TaskHandle_t pidTaskNotification = NULL; uint32_t currentTempTargetDegC = 0; // Current temperature target in C /* StartPIDTask function */ -void startPIDTask(void const *argument __unused) -{ +void startPIDTask(void const *argument __unused) { /* * We take the current tip temperature & evaluate the next step for the tip * control PWM. @@ -30,32 +29,27 @@ void startPIDTask(void const *argument __unused) TickType_t lastPowerPulseStart = 0; TickType_t lastPowerPulseEnd = 0; - history tempError = {{0}, 0, 0}; + history tempError = { { 0 }, 0, 0 }; currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will // be over-ridden rapidly pidTaskNotification = xTaskGetCurrentTaskHandle(); uint32_t PIDTempTarget = 0; - for (;;) - { + for (;;) { - if (ulTaskNotifyTake(pdTRUE, 2000)) - { + if (ulTaskNotifyTake(pdTRUE, 2000)) { // This is a call to block this thread until the ADC does its samples int32_t x10WattsOut = 0; // Do the reading here to keep the temp calculations churning along uint32_t currentTipTempInC = TipThermoModel::getTipInC(true); PIDTempTarget = currentTempTargetDegC; - if (PIDTempTarget) - { + if (PIDTempTarget) { // Cap the max set point to 450C - if (PIDTempTarget > (450)) - { + if (PIDTempTarget > (450)) { //Maximum allowed output PIDTempTarget = (450); } //Safety check that not aiming higher than current tip can measure - if (PIDTempTarget > TipThermoModel::getTipMaxInC()) - { + if (PIDTempTarget > TipThermoModel::getTipMaxInC()) { PIDTempTarget = TipThermoModel::getTipMaxInC(); } // Convert the current tip to degree's C @@ -79,7 +73,7 @@ void startPIDTask(void const *argument __unused) // Once we have feed-forward temp estimation we should be able to better tune this. int32_t x10WattsNeeded = tempToX10Watts(tError); - // tempError.average()); +// tempError.average()); // note that milliWattsNeeded is sometimes negative, this counters overshoot // from I term's inertia. x10WattsOut += x10WattsNeeded; @@ -95,41 +89,38 @@ void startPIDTask(void const *argument __unused) // and counters extra power if the iron is no longer losing temp. // basically: temp - lastTemp // Unfortunately, our temp signal is too noisy to really help. + } //If the user turns on the option of using an occasional pulse to keep the power bank on - if (systemSettings.KeepAwakePulse) - { + if (systemSettings.KeepAwakePulse) { - if (xTaskGetTickCount() - lastPowerPulseStart > powerPulseRate) - { + if (xTaskGetTickCount() - lastPowerPulseStart + > powerPulseRate) { lastPowerPulseStart = xTaskGetTickCount(); - lastPowerPulseEnd = lastPowerPulseStart + powerPulseDuration; + lastPowerPulseEnd = lastPowerPulseStart + + powerPulseDuration; } //If current PID is less than the pulse level, check if we want to constrain to the pulse as the floor - if (x10WattsOut < systemSettings.KeepAwakePulse && xTaskGetTickCount() < lastPowerPulseEnd) - { + if (x10WattsOut < systemSettings.KeepAwakePulse + && xTaskGetTickCount() < lastPowerPulseEnd) { x10WattsOut = systemSettings.KeepAwakePulse; } } //Secondary safety check to forcefully disable header when within ADC noise of top of ADC - if (getTipRawTemp(0) > (0x7FFF - 150)) - { + if (getTipRawTemp(0) > (0x7FFF - 150)) { x10WattsOut = 0; } - if (systemSettings.powerLimitEnable && x10WattsOut > (systemSettings.powerLimit * 10)) - { + if (systemSettings.powerLimit + && x10WattsOut > (systemSettings.powerLimit * 10)) { setTipX10Watts(systemSettings.powerLimit * 10); - } - else - { + } else { setTipX10Watts(x10WattsOut); } + resetWatchdog(); - } - else - { + } else { //ADC interrupt timeout setTipPWM(0); } From 13a91594701252fe3f78e0e5ea5728065b09fa70 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 17 Sep 2020 19:38:40 +1000 Subject: [PATCH 10/72] . --- workspace/TS100/Core/BSP/Pine64/Pins.h | 6 +++--- workspace/TS100/Core/BSP/Pine64/Setup.c | 16 ++++++++-------- workspace/TS100/configuration.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/Pins.h b/workspace/TS100/Core/BSP/Pine64/Pins.h index 461ec9b8..371675da 100644 --- a/workspace/TS100/Core/BSP/Pine64/Pins.h +++ b/workspace/TS100/Core/BSP/Pine64/Pins.h @@ -13,17 +13,17 @@ #define KEY_B_GPIO_Port GPIOB #define TMP36_INPUT_Pin BIT(4) #define TMP36_INPUT_GPIO_Port GPIOA +#define TMP36_ADC0_CHANNEL ADC_CHANNEL_4 #define TMP36_ADC1_CHANNEL ADC_CHANNEL_4 -#define TMP36_ADC2_CHANNEL ADC_CHANNEL_4 #define TIP_TEMP_Pin BIT(1) #define TIP_TEMP_GPIO_Port GPIOA +#define TIP_TEMP_ADC0_CHANNEL ADC_CHANNEL_1 #define TIP_TEMP_ADC1_CHANNEL ADC_CHANNEL_1 -#define TIP_TEMP_ADC2_CHANNEL ADC_CHANNEL_1 #define VIN_Pin BIT(0) #define VIN_GPIO_Port GPIOA +#define VIN_ADC0_CHANNEL ADC_CHANNEL_0 #define VIN_ADC1_CHANNEL ADC_CHANNEL_0 -#define VIN_ADC2_CHANNEL ADC_CHANNEL_0 #define OLED_RESET_Pin BIT(9) #define OLED_RESET_GPIO_Port GPIOA #define KEY_A_Pin BIT(0) diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 0812d5ec..2126275e 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -146,22 +146,22 @@ void setup_adc() { adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2); adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 2); //Setup the two channels - adc_regular_channel_config(ADC0, 0, TMP36_ADC1_CHANNEL, + adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC1, 0, TMP36_ADC2_CHANNEL, + adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC0, 1, VIN_ADC1_CHANNEL, + adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage - adc_regular_channel_config(ADC1, 1, VIN_ADC2_CHANNEL, + adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage //Setup that we want all 4 inserted readings to be the tip temp adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); for (int rank = 0; rank < 4; rank++) { - adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC1_CHANNEL, - ADC_SAMPLETIME_1POINT5); - adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC2_CHANNEL, - ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, + ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, + ADC_SAMPLETIME_1POINT5); } // Enable triggers for the ADC adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index 1dac3961..24b4eb86 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -101,7 +101,7 @@ #define VOLTAGE_DIV 467 // 467 - Default divider from schematic #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV #define PID_POWER_LIMIT 70 // Sets the max pwm power limit -#define POWER_LIMIT 30 // 30 watts default limit +#define POWER_LIMIT 0 // 0 watts default limit #define MAX_POWER_LIMIT 65 // #define POWER_LIMIT_STEPS 5 // #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 @@ -111,7 +111,7 @@ #define VOLTAGE_DIV 467 // 467 - Default divider from schematic #define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV #define PID_POWER_LIMIT 70 // Sets the max pwm power limit -#define POWER_LIMIT 30 // 30 watts default limit +#define POWER_LIMIT 0 // 0 watts default limit #define MAX_POWER_LIMIT 65 // #define POWER_LIMIT_STEPS 5 // #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 From 65ae7c8b13fffa99e87e46041cf3323f0c673535 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 18 Sep 2020 19:09:59 +1000 Subject: [PATCH 11/72] Cleanup ADC --- workspace/TS100/Core/BSP/Pine64/Setup.c | 101 ++++++++---------- workspace/TS100/Core/Inc/configuration.h | 124 +++++++++++++++++++++++ 2 files changed, 168 insertions(+), 57 deletions(-) create mode 100644 workspace/TS100/Core/Inc/configuration.h diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 2126275e..a7763dbf 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -8,8 +8,11 @@ #include "BSP.h" #include "Pins.h" #include "gd32vf103.h" +#include #include "systick.h" -uint16_t ADCReadings[64]; // room for 32 lots of the pair of readings +#define ADC_NORM_CHANNELS 2 +#define ADC_NORM_SAMPLES 32 +uint16_t ADCReadings[ADC_NORM_SAMPLES * ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings // Functions void setup_gpio(); @@ -42,8 +45,8 @@ void hardware_init() { // channel 0 -> temperature sensor, 1-> VIN uint16_t getADC(uint8_t channel) { uint32_t sum = 0; - for (uint8_t i = 0; i < 32; i++) - sum += ADCReadings[channel + (i * 2)]; + for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) + sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)]; return sum >> 2; } @@ -67,13 +70,12 @@ void setup_gpio() { gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); //Analog Inputs ... as analog inputs - gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, + gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, TMP36_INPUT_Pin); - gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, + gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, TIP_TEMP_Pin); - gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, VIN_Pin); - //Timer 2 remap to move timer 2 ch0 to pin PB4 -// gpio_pin_remap_config(GPIO_TIMER2_PARTIAL_REMAP, ENABLE); + gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, VIN_Pin); + //Remap PB4 away from JTAG NJRST gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); //TODO - rest of pins as floating @@ -83,6 +85,7 @@ void setup_dma() { { /* enable DMA0 clock */ rcu_periph_clock_enable(RCU_DMA0); + rcu_periph_clock_enable(RCU_DMA1); /* ADC_DMA_channel configuration */ dma_parameter_struct dma_data_parameter; @@ -92,12 +95,12 @@ void setup_dma() { /* initialize DMA data mode */ dma_data_parameter.periph_addr = (uint32_t) (&ADC_RDATA(ADC0)); dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_data_parameter.memory_addr = (uint32_t) (&ADCReadings); + dma_data_parameter.memory_addr = (uint32_t) (ADCReadings); dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_32BIT; + dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_data_parameter.number = 64; + dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS; dma_data_parameter.priority = DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH0, &dma_data_parameter); @@ -123,88 +126,72 @@ void setup_adc() { //Setup ADC in normal + injected mode //Want it to sample handle temp and input voltage normally via dma //Then injected trigger to sample tip temp - - /* enable ADC0 clock */ + memset(ADCReadings, 0, sizeof(ADCReadings)); rcu_periph_clock_enable(RCU_ADC0); - /* enable ADC1 clock */ rcu_periph_clock_enable(RCU_ADC1); - /* config ADC clock */ - rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8); - /* reset ADC */ adc_deinit(ADC0); adc_deinit(ADC1); + /* config ADC clock */ + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16); //Run in normal parallel + inserted parallel adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); - adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE | ADC_SCAN_MODE, - ENABLE); - adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE | ADC_SCAN_MODE, - ENABLE); + adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE); //Align right adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); - //Setup reading 2 channels on regular mode (Handle Temp + ) - adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 2); - adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 2); + //Setup reading 2 channels on regular mode (Handle Temp + dc in) + adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); + adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); //Setup the two channels - adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, - ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, - ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, - ADC_SAMPLETIME_71POINT5); //DC Input voltage - adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, - ADC_SAMPLETIME_71POINT5); //DC Input voltage + adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor + adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor + adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage + adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage //Setup that we want all 4 inserted readings to be the tip temp adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); for (int rank = 0; rank < 4; rank++) { - adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, - ADC_SAMPLETIME_1POINT5); - adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, - ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, ADC_SAMPLETIME_1POINT5); } + //Setup timer 1 channel 0 to trigger injected measurements + adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0); + adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0); + + adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); + adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); // Enable triggers for the ADC adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); - adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); - adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); - //Setup timer 1 channel 0 to trigger injected measurements - adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, - ADC0_1_EXTTRIG_INSERTED_T1_CH0); - adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, - ADC0_1_EXTTRIG_INSERTED_T1_CH0); + adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE); - adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, - ADC0_1_EXTTRIG_REGULAR_NONE); - adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, - ADC0_1_EXTTRIG_REGULAR_NONE); - - adc_tempsensor_vrefint_disable(); adc_watchdog_disable(ADC0); adc_watchdog_disable(ADC1); adc_resolution_config(ADC0, ADC_RESOLUTION_12B); adc_resolution_config(ADC1, ADC_RESOLUTION_12B); /* clear the ADC flag */ - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); adc_oversample_mode_disable(ADC0); adc_oversample_mode_disable(ADC1); adc_enable(ADC0); - adc_enable(ADC1); delay_1ms(1); adc_calibration_enable(ADC0); + adc_enable(ADC1); delay_1ms(1); adc_calibration_enable(ADC1); delay_1ms(1); - //Enable DMA mode adc_dma_mode_enable(ADC0); //Enable interrupt on end of injected readings + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); adc_interrupt_enable(ADC0, ADC_INT_EOIC); eclic_irq_enable(ADC0_1_IRQn, 2, 0); - adc_dma_mode_enable(ADC0); - adc_dma_mode_enable(ADC1); - adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); - adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); +// adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); +// adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); + adc_tempsensor_vrefint_disable(); } void setup_timers() { //Setup timer 1 to run the actual PWM level diff --git a/workspace/TS100/Core/Inc/configuration.h b/workspace/TS100/Core/Inc/configuration.h new file mode 100644 index 00000000..a6ad04b1 --- /dev/null +++ b/workspace/TS100/Core/Inc/configuration.h @@ -0,0 +1,124 @@ +#pragma once +/** + * Configuration.h + * Define here your default pre settings for TS80 or TS100 + * + */ + +//=========================================================================== +//============================= Default Settings ============================ +//=========================================================================== +/** + * Default soldering temp is 320.0 C + * Temperature the iron sleeps at - default 150.0 C + */ +#define SOLDERING_TEMP 320 // Default soldering temp is 320.0 °C +#define SLEEP_TEMP 150 // Default sleep temperature +#define BOOST_TEMP 420 // Default boost temp. +#define BOOST_MODE_ENABLED 1 // 0: Disable 1: Enable + +/** + * Blink the temperature on the cooling screen when its > 50C + */ +#define COOLING_TEMP_BLINK 0 // 0: Disable 1: Enable + +/** + * How many seconds/minutes we wait until going to sleep/shutdown. + * Values -> SLEEP_TIME * 10; i.e. 5*10 = 50 Seconds! + */ +#define SLEEP_TIME 5 // x10 Seconds +#define SHUTDOWN_TIME 10 // Minutes + +/** + * Auto start off for safety. + * Pissible values are: + * 0 - none + * 1 - Soldering Temperature + * 2 - Sleep Temperature + * 3 - Sleep Off Temperature + */ +#define AUTO_START_MODE 0 // Default to none + +/** + * OLED Orientation + * + */ +#define ORIENTATION_MODE 0 // 0: Right 1:Left 2:Automatic - Default right +#define REVERSE_BUTTON_TEMP_CHANGE 0 // 0:Default 1:Reverse - Reverse the plus and minus button assigment for temperatur change + +/** + * Temp change settings + */ +#define TEMP_CHANGE_SHORT_STEP 1 // Default temp change short step +1 +#define TEMP_CHANGE_LONG_STEP 10 // Default temp change long step +10 +#define TEMP_CHANGE_SHORT_STEP_MAX 50 // Temp change short step MAX value +#define TEMP_CHANGE_LONG_STEP_MAX 100 // Temp change long step MAX value + +/* Power pulse for keeping power banks awake*/ +#define POWER_PULSE_INCREMENT 1 +#define POWER_PULSE_MAX 50 // x10 max watts +#ifdef MODEL_TS100 +#define POWER_PULSE_DEFAULT 0 +#else +#define POWER_PULSE_DEFAULT 5 +#endif + +/** + * OLED Orientation Sensitivity on Automatic mode! + * Motion Sensitivity <0=Off 1=Least Sensitive 9=Most Sensitive> + */ +#define SENSITIVITY 7 // Default 7 + +/** + * Detailed soldering screen + * Detailed idle screen (off for first time users) + */ +#define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 +#define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 + +#define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) +#define TEMPERATURE_INF 0 // default to 0 +#define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow +#define POWER_LIMIT_ENABLE 0 // 0: Disable 1: Enable - Default disabled power limit + +#define TIP_GAIN 210 // 21 uV/C * 10, uV per deg C constant of the tip, Tip uV * 10 / coeff = tip temp + +#define OP_AMP_Rf_TS100 750 * 1000 // 750 Kilo-ohms -> From schematic, R1 +#define OP_AMP_Rin_TS100 2370 // 2.37 Kilo-ohms -> From schematic, R2 + +#define OP_AMP_GAIN_STAGE_TS100 (1 + (OP_AMP_Rf_TS100 / OP_AMP_Rin_TS100)) + +#define OP_AMP_Rf_TS80 180 * 1000 // 180 Kilo-ohms -> From schematic, R6 +#define OP_AMP_Rin_TS80 2000 // 2.0 Kilo-ohms -> From schematic, R3 + +#define OP_AMP_GAIN_STAGE_TS80 (1 + (OP_AMP_Rf_TS80 / OP_AMP_Rin_TS80)) + +#ifdef MODEL_TS100 +#define VOLTAGE_DIV 467 // 467 - Default divider from schematic +#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV +#define PID_POWER_LIMIT 70 // Sets the max pwm power limit +#define POWER_LIMIT 30 // 30 watts default limit +#define MAX_POWER_LIMIT 65 // +#define POWER_LIMIT_STEPS 5 // +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 +#endif + +#ifdef MODEL_TS80 +#define VOLTAGE_DIV 780 // Default divider from schematic +#define PID_POWER_LIMIT 24 // Sets the max pwm power limit +#define CALIBRATION_OFFSET 900 // the adc offset in uV +#define POWER_LIMIT 24 // 24 watts default power limit +#define MAX_POWER_LIMIT 30 // +#define POWER_LIMIT_STEPS 2 +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS80 +#endif + +#ifdef MODEL_Pinecil +#define VOLTAGE_DIV 467 // 467 - Default divider from schematic +#define CALIBRATION_OFFSET 900 // 900 - Default adc offset in uV +#define PID_POWER_LIMIT 70 // Sets the max pwm power limit +#define POWER_LIMIT 30 // 30 watts default limit +#define MAX_POWER_LIMIT 65 // +#define POWER_LIMIT_STEPS 5 // +#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_TS100 +#endif \ No newline at end of file From f3747875647352e2742b56d711f2e318a947aaca Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 18 Sep 2020 19:50:50 +1000 Subject: [PATCH 12/72] Simplify I2C initalisation --- .../TS100/Core/BSP/Miniware/Model_Config.h | 4 +- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 23 ++++--- workspace/TS100/Core/Drivers/BMA223.cpp | 18 ++++++ workspace/TS100/Core/Drivers/BMA223.hpp | 42 +++++++++++++ workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 16 +++-- workspace/TS100/Core/Drivers/LIS2DH12.cpp | 37 +++++------ workspace/TS100/Core/Drivers/LIS2DH12.hpp | 3 +- workspace/TS100/Core/Drivers/MMA8652FC.cpp | 61 ++++++------------- 8 files changed, 120 insertions(+), 84 deletions(-) create mode 100644 workspace/TS100/Core/Drivers/BMA223.cpp create mode 100644 workspace/TS100/Core/Drivers/BMA223.hpp diff --git a/workspace/TS100/Core/BSP/Miniware/Model_Config.h b/workspace/TS100/Core/BSP/Miniware/Model_Config.h index 6cb69a94..0ed53702 100644 --- a/workspace/TS100/Core/BSP/Miniware/Model_Config.h +++ b/workspace/TS100/Core/BSP/Miniware/Model_Config.h @@ -27,7 +27,7 @@ #define ACCEL_LIS #define POW_QC #define TEMP_TMP36 -#define LIS_ORI_FLIP +#define ACCEL_ORI_FLIP #define OLED_FLIP #endif @@ -37,7 +37,7 @@ #define POW_QC #define TEMP_NTC #define I2C_SOFT -#define LIS_ORI_FLIP +#define ACCEL_ORI_FLIP #define OLED_FLIP #endif diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 6d62cee2..2fba6154 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -121,8 +121,7 @@ int i2c_byte_write(int data) { /* wait until the byte is transmitted */ timeout = FLAG_TIMEOUT; - while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) - || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { + while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { if ((timeout--) == 0) { return 2; } @@ -131,8 +130,7 @@ int i2c_byte_write(int data) { return 1; } -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { if (!lock()) return false; @@ -253,8 +251,7 @@ uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { Mem_Read(add, reg, &temp, 1); return temp; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { if (!lock()) return false; @@ -397,8 +394,7 @@ bool FRToSI2C::probe(uint16_t DevAddress) { /* wait until ADDSEND bit is set */ int timeout = FLAG_TIMEOUT; while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - if (i2c_flag_get(I2C0, I2C_FLAG_AERR) - || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { + if (i2c_flag_get(I2C0, I2C_FLAG_AERR) || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { i2c_stop(); unlock(); return false; @@ -451,3 +447,14 @@ void FRToSI2C::unlock2() { return; xSemaphoreGive(I2CSemaphore2); } + +bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) + delay_ms(registers[index].pause_ms); + } + return true; +} diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp new file mode 100644 index 00000000..9b415f28 --- /dev/null +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -0,0 +1,18 @@ +/* + * BMA223.cpp + * + * Created on: 18 Sep. 2020 + * Author: Ralim + */ + +#include + + +bool BMA223::detect() { +} + +void BMA223::initalize() { +} + +void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) { +} diff --git a/workspace/TS100/Core/Drivers/BMA223.hpp b/workspace/TS100/Core/Drivers/BMA223.hpp new file mode 100644 index 00000000..5578d89a --- /dev/null +++ b/workspace/TS100/Core/Drivers/BMA223.hpp @@ -0,0 +1,42 @@ +/* + * BMA223.hpp + * + * Created on: 18 Sep. 2020 + * Author: Ralim + */ + +#ifndef CORE_DRIVERS_BMA223_HPP_ +#define CORE_DRIVERS_BMA223_HPP_ +#include "I2C_Wrapper.hpp" +#include "LIS2DH12_defines.hpp" +#include "BSP.h" + + +class BMA223 { +public: + static bool detect(); + static void initalize(); + //1 = rh, 2,=lh, 8=flat + static Orientation getOrientation() { +#ifdef ACCEL_ORI_FLIP + uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, + LIS_INT2_SRC) >> 2); + if (val == 8) + val = 3; + else if (val == 1) + val = 1; + else if (val == 2) + val = 0; + else + val = 3; + return static_cast(val); +#else + return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1); +#endif + } + static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z); + +private: +}; + +#endif /* CORE_DRIVERS_BMA223_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index d7ed3e66..88be5e62 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -30,22 +30,26 @@ public: static void CpltCallback(); //Normal Tx Callback - static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); - static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size); + static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size); + static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size); //Returns true if device ACK's being addressed static bool probe(uint16_t DevAddress); static bool Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); - static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, - uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); + static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); static bool I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); static void unlock2(); static bool lock2(); + + typedef struct { + const uint8_t reg; // The register to write to + const uint8_t val; // The value to write to this register + const uint8_t pause_ms; //How many ms to pause _after_ writing this reg + } I2C_REG; + static bool writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength); private: static void unlock(); static bool lock(); diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.cpp b/workspace/TS100/Core/Drivers/LIS2DH12.cpp index 888e1231..89cdd9a6 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.cpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.cpp @@ -10,37 +10,28 @@ #include "LIS2DH12.hpp" #include "cmsis_os.h" -typedef struct { - const uint8_t reg; - const uint8_t value; -} LIS_REG; - -static const LIS_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17 }, // 25Hz - { LIS_CTRL_REG2, 0b00001000 }, // Highpass filter off - { LIS_CTRL_REG3, 0b01100000 }, // Setup interrupt pins - { LIS_CTRL_REG4, 0b00001000 }, // Block update mode off, HR on - { LIS_CTRL_REG5, 0b00000010 }, { LIS_CTRL_REG6, 0b01100010 }, +static const FRToSI2C::I2C_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17, 0 }, // 25Hz + { LIS_CTRL_REG2, 0b00001000, 0 }, // Highpass filter off + { LIS_CTRL_REG3, 0b01100000, 0 }, // Setup interrupt pins + { LIS_CTRL_REG4, 0b00001000, 0 }, // Block update mode off, HR on + { LIS_CTRL_REG5, 0b00000010, 0 }, // + { LIS_CTRL_REG6, 0b01100010, 0 }, //Basically setup the unit to run, and enable 4D orientation detection - { LIS_INT2_CFG, 0b01111110 }, //setup for movement detection - { LIS_INT2_THS, 0x28 }, { LIS_INT2_DURATION, 64 }, { - LIS_INT1_CFG, 0b01111110 }, { LIS_INT1_THS, 0x28 }, { - LIS_INT1_DURATION, 64 } }; + { LIS_INT2_CFG, 0b01111110, 0 }, //setup for movement detection + { LIS_INT2_THS, 0x28, 0 }, // + { LIS_INT2_DURATION, 64, 0 }, // + { LIS_INT1_CFG, 0b01111110, 0 }, // + { LIS_INT1_THS, 0x28, 0 }, // + { LIS_INT1_DURATION, 64, 0 } }; void LIS2DH12::initalize() { - for (size_t index = 0; - index < (sizeof(i2c_registers) / sizeof(i2c_registers[0])); - index++) { - FRToSI2C::I2C_RegisterWrite(LIS2DH_I2C_ADDRESS, - i2c_registers[index].reg, i2c_registers[index].value); - } + FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { std::array sensorData; - FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8, - reinterpret_cast(sensorData.begin()), - sensorData.size() * sizeof(int16_t)); + FRToSI2C::Mem_Read(LIS2DH_I2C_ADDRESS, 0xA8, reinterpret_cast(sensorData.begin()), sensorData.size() * sizeof(int16_t)); x = sensorData[0]; y = sensorData[1]; diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.hpp b/workspace/TS100/Core/Drivers/LIS2DH12.hpp index 79346e98..8586ec21 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.hpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.hpp @@ -29,8 +29,7 @@ public: else val = 3; return static_cast(val); -#endif -#ifdef MODEL_TS100 +#else return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1); #endif } diff --git a/workspace/TS100/Core/Drivers/MMA8652FC.cpp b/workspace/TS100/Core/Drivers/MMA8652FC.cpp index cd41488a..83e922e1 100644 --- a/workspace/TS100/Core/Drivers/MMA8652FC.cpp +++ b/workspace/TS100/Core/Drivers/MMA8652FC.cpp @@ -10,45 +10,25 @@ #include "MMA8652FC.hpp" #include "cmsis_os.h" -typedef struct { - const uint8_t reg; - const uint8_t val; -} MMA_REG; -static const MMA_REG i2c_registers[] = { { CTRL_REG2, 0 }, //Normal mode - { CTRL_REG2, 0x40 }, // Reset all registers to POR values - { FF_MT_CFG_REG, 0x78 }, // Enable motion detection for X, Y, Z axis, latch disabled - { PL_CFG_REG, 0x40 }, //Enable the orientation detection - { PL_COUNT_REG, 200 }, //200 count debounce - { PL_BF_ZCOMP_REG, 0b01000111 }, //Set the threshold to 42 degrees - { P_L_THS_REG, 0b10011100 }, //Up the trip angles - { CTRL_REG4, 0x01 | (1 << 4) }, // Enable dataready interrupt & orientation interrupt - { CTRL_REG5, 0x01 }, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 - { CTRL_REG2, 0x12 }, //Set maximum resolution oversampling - { XYZ_DATA_CFG_REG, (1 << 4) }, //select high pass filtered data - { HP_FILTER_CUTOFF_REG, 0x03 }, //select high pass filtered data - { CTRL_REG1, 0x19 } // ODR=12 Hz, Active mode +static const FRToSI2C::I2C_REG i2c_registers[] = { { CTRL_REG2, 0, 0 }, //Normal mode + { CTRL_REG2, 0x40, 2 }, // Reset all registers to POR values + { FF_MT_CFG_REG, 0x78, 0 }, // Enable motion detection for X, Y, Z axis, latch disabled + { PL_CFG_REG, 0x40, 0 }, //Enable the orientation detection + { PL_COUNT_REG, 200, 0 }, //200 count debounce + { PL_BF_ZCOMP_REG, 0b01000111, 0 }, //Set the threshold to 42 degrees + { P_L_THS_REG, 0b10011100, 0 }, //Up the trip angles + { CTRL_REG4, 0x01 | (1 << 4), 0 }, // Enable dataready interrupt & orientation interrupt + { CTRL_REG5, 0x01, 0 }, // Route data ready interrupts to INT1 ->PB5 ->EXTI5, leaving orientation routed to INT2 + { CTRL_REG2, 0x12, 0 }, //Set maximum resolution oversampling + { XYZ_DATA_CFG_REG, (1 << 4), 0 }, //select high pass filtered data + { HP_FILTER_CUTOFF_REG, 0x03, 0 }, //select high pass filtered data + { CTRL_REG1, 0x19, 0 } // ODR=12 Hz, Active mode }; void MMA8652FC::initalize() { - size_t index = 0; + FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); - //send all the init commands to the unit - - FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS, i2c_registers[index].reg, - i2c_registers[index].val); - index++; - FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS, i2c_registers[index].reg, - i2c_registers[index].val); - index++; - - delay_ms(2); // ~1ms delay - - while (index < (sizeof(i2c_registers) / sizeof(i2c_registers[0]))) { - FRToSI2C::I2C_RegisterWrite(MMA8652FC_I2C_ADDRESS, - i2c_registers[index].reg, i2c_registers[index].val); - index++; - } } Orientation MMA8652FC::getOrientation() { @@ -71,16 +51,11 @@ Orientation MMA8652FC::getOrientation() { void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { std::array sensorData; - FRToSI2C::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, - reinterpret_cast(sensorData.begin()), - sensorData.size() * sizeof(int16_t)); + FRToSI2C::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, reinterpret_cast(sensorData.begin()), sensorData.size() * sizeof(int16_t)); - x = static_cast(__builtin_bswap16( - *reinterpret_cast(&sensorData[0]))); - y = static_cast(__builtin_bswap16( - *reinterpret_cast(&sensorData[1]))); - z = static_cast(__builtin_bswap16( - *reinterpret_cast(&sensorData[2]))); + x = static_cast(__builtin_bswap16(*reinterpret_cast(&sensorData[0]))); + y = static_cast(__builtin_bswap16(*reinterpret_cast(&sensorData[1]))); + z = static_cast(__builtin_bswap16(*reinterpret_cast(&sensorData[2]))); } bool MMA8652FC::detect() { From ad8df08bb8f21cbd0386720ee1acc4f77f193625 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 18 Sep 2020 21:58:36 +1000 Subject: [PATCH 13/72] Rough pass updating to add BMA223 support --- .../TS100/Core/BSP/Pine64/Model_Config.h | 1 + workspace/TS100/Core/Drivers/BMA223.cpp | 37 +++++++++- workspace/TS100/Core/Drivers/BMA223_defines.h | 67 +++++++++++++++++++ workspace/TS100/Core/Threads/MOVThread.cpp | 64 +++++++++++------- 4 files changed, 145 insertions(+), 24 deletions(-) create mode 100644 workspace/TS100/Core/Drivers/BMA223_defines.h diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 3a3e0afd..6a64a04f 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -19,6 +19,7 @@ #define POW_PD #define POW_QC #define TEMP_TMP36 +#define ACCEL_BMA #endif #endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp index 9b415f28..b15161b3 100644 --- a/workspace/TS100/Core/Drivers/BMA223.cpp +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -6,13 +6,48 @@ */ #include - +#include "BMA223_defines.h" +#include +#define BMA223_ADDRESS 0b00110000 bool BMA223::detect() { + return FRToSI2C::probe(BMA223_ADDRESS); } +static const FRToSI2C::I2C_REG i2c_registers[] = { // + // + { BMA223_PMU_RANGE, 0b0011, 0 }, //2G range + { BMA223_PMU_BW, 0b1101, 0 }, //250Hz filter + { BMA223_PMU_LPW, 0x00, 0 }, //Full power + { BMA223_ACCD_HBW, 0b01000000, 0 }, //filtered data out + { BMA223_INT_OUT_CTRL, 0b1111, 0 }, //interrupt active high and OD to get it hi-z + { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en + + // + }; void BMA223::initalize() { + //Setup acceleration readings + //2G range + //bandwidth = 250Hz + //High pass filter on (Slow compensation) + //Turn off IRQ output pins + //Orientation recognition in symmetrical mode + // Hysteresis is set to ~ 16 counts + //Theta blocking is set to 0b10 + + FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); + } void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) { + //The BMA is odd in that its output data width is only 8 bits + //And yet there are MSB and LSB registers _sigh_. + uint8_t sensorData[6]; + + FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6); + + x = sensorData[1] << 2; + y = sensorData[3] << 2; + z = sensorData[5] << 2; + } diff --git a/workspace/TS100/Core/Drivers/BMA223_defines.h b/workspace/TS100/Core/Drivers/BMA223_defines.h new file mode 100644 index 00000000..12481300 --- /dev/null +++ b/workspace/TS100/Core/Drivers/BMA223_defines.h @@ -0,0 +1,67 @@ +/* + * BMA223_defines.h + * + * Created on: 18 Sep. 2020 + * Author: Ralim + */ + +#ifndef CORE_DRIVERS_BMA223_DEFINES_H_ +#define CORE_DRIVERS_BMA223_DEFINES_H_ + +#define BMA223_BGW_CHIPID 0x00 +#define BMA223_ACCD_X_LSB 0x02 +#define BMA223_ACCD_X_MSB 0x03 +#define BMA223_ACCD_Y_LSB 0x04 +#define BMA223_ACCD_Y_MSB 0x05 +#define BMA223_ACCD_Z_LSB 0x06 +#define BMA223_ACCD_Z_MSB 0x07 +#define BMA223_ACCD_TEMP 0x08 +#define BMA223_INT_STATUS_0 0x09 +#define BMA223_INT_STATUS_1 0x0A +#define BMA223_INT_STATUS_2 0x0B +#define BMA223_INT_STATUS_3 0x0C +#define BMA223_FIFO_STATUS 0x0E +#define BMA223_PMU_RANGE 0x0F +#define BMA223_PMU_BW 0x10 +#define BMA223_PMU_LPW 0x11 +#define BMA223_PMU_LOW_POWER 0x012 +#define BMA223_ACCD_HBW 0x13 +#define BMA223_BGW_SOFTRESET 0x14 +#define BMA223_INT_EN_0 0x16 +#define BMA223_INT_EN_1 0x17 +#define BMA223_INT_EN_2 0x18 +#define BMA223_INT_MAP_0 0x19 +#define BMA223_INT_MAP_1 0x1A +#define BMA223_INT_MAP_2 0x1B +#define BMA223_INT_SRC 0x1E +#define BMA223_INT_OUT_CTRL 0x20 +#define BMA223_INT_RST_LATCH 0x21 +#define BMA223_INT_0 0x22 +#define BMA223_INT_1 0x23 +#define BMA223_INT_2 0x24 +#define BMA223_INT_3 0x25 +#define BMA223_INT_4 0x26 +#define BMA223_INT_5 0x27 +#define BMA223_INT_6 0x28 +#define BMA223_INT_7 0x29 +#define BMA223_INT_8 0x2A +#define BMA223_INT_9 0x2B +#define BMA223_INT_A 0x2C +#define BMA223_INT_B 0x2D +#define BMA223_INT_C 0x2E +#define BMA223_INT_D 0x2F +#define BMA223_FIFO_CONFIG_0 0x30 +#define BMA223_PMU_SELF_TEST 0x32 +#define BMA223_TRIM_NVM_CTRL 0x33 +#define BMA223_BGW_SPI3_WDT 0x34 +#define BMA223_OFC_CTRL 0x36 +#define BMA223_OFC_SETTING 0x37 +#define BMA223_OFC_OFFSET_X 0x38 +#define BMA223_OFC_OFFSET_Y 0x39 +#define BMA223_OFC_OFFSET_Z 0x3A +#define BMA223_TRIM_GP0 0x3B +#define BMA223_TRIM_GP1 0x3C +#define BMA223_FIFO_CONFIG_1 0x3E +#define BMA223_FIFO_DATA 0x3F + +#endif /* CORE_DRIVERS_BMA223_DEFINES_H_ */ diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 1fe57cd1..01a36b2e 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -18,11 +18,12 @@ #include "main.hpp" #include "power.hpp" #include "stdlib.h" +#include "BMA223.hpp" #include "task.h" #define MOVFilter 8 uint8_t accelInit = 0; uint32_t lastMovementTime = 0; -void startMOVTask(void const *argument __unused) { +void detectAccelerometerVersion() { #ifdef ACCEL_MMA if (MMA8652FC::detect()) { PCBVersion = 1; @@ -33,22 +34,53 @@ void startMOVTask(void const *argument __unused) { if (LIS2DH12::detect()) { PCBVersion = 2; // Setup the ST Accelerometer - LIS2DH12::initalize(); // startup the accelerometer + LIS2DH12::initalize();// startup the accelerometer + } else +#endif +#ifdef ACCEL_BMA + if (BMA223::detect()) { + PCBVersion = 3; + // Setup the ST Accelerometer + BMA223::initalize(); // startup the accelerometer } else #endif { - PCBVersion = 3; + PCBVersion = 99; systemSettings.SleepTime = 0; systemSettings.ShutdownTime = 0; // No accel -> disable sleep systemSettings.sensitivity = 0; } + +} +inline void readAccelerometer(int16_t& tx, int16_t& ty, int16_t& tz, Orientation &rotation) { +#ifdef ACCEL_LIS + if (PCBVersion == 2) { + LIS2DH12::getAxisReadings(tx, ty, tz); + rotation = LIS2DH12::getOrientation(); + } else +#endif +#ifdef ACCEL_MMA + if (PCBVersion == 1) { + MMA8652FC::getAxisReadings(tx, ty, tz); + rotation = MMA8652FC::getOrientation(); + } else +#endif +#ifdef ACCEL_BMA + if (PCBVersion == 3) { + BMA223::getAxisReadings(tx, ty, tz); + rotation = BMA223::getOrientation(); + } else +#endif + { + //do nothing :( + } +} +void startMOVTask(void const *argument __unused) { + postRToSInit(); OLED::setRotation(systemSettings.OrientationMode & 1); - - if ((PCBVersion == 1 - || PCBVersion == 2) - && (systemSettings.autoStartMode == 2 - || systemSettings.autoStartMode == 3)) + detectAccelerometerVersion(); + if ((systemSettings.autoStartMode == 2 || systemSettings.autoStartMode == 3)) osDelay(2000); lastMovementTime = 0; @@ -64,21 +96,7 @@ void startMOVTask(void const *argument __unused) { for (;;) { int32_t threshold = 1500 + (9 * 200); threshold -= systemSettings.sensitivity * 200; // 200 is the step size -#ifdef ACCEL_LIS - if (PCBVersion == 2) { - LIS2DH12::getAxisReadings(tx, ty, tz); - rotation = LIS2DH12::getOrientation(); - } else -#endif -#ifdef ACCEL_MMA - if (PCBVersion == 1) { - MMA8652FC::getAxisReadings(tx, ty, tz); - rotation = MMA8652FC::getOrientation(); - }else -#endif - { - //do nothing :( - } + readAccelerometer(tx, ty, tz, rotation); if (systemSettings.OrientationMode == 2) { if (rotation != ORIENTATION_FLAT) { OLED::setRotation(rotation == ORIENTATION_LEFT_HAND); // link the data through From 23b54526703b5c23a8c42a08073ff88624b7f5b8 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 18 Sep 2020 21:59:38 +1000 Subject: [PATCH 14/72] Port across init reg helper --- .../TS100/Core/BSP/Miniware/I2C_Wrapper.cpp | 44 +++++++++++++------ .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 4 +- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp index 5eb60c81..95ae98b1 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp @@ -9,6 +9,8 @@ #include "Setup.h" SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; +SemaphoreHandle_t FRToSI2C::I2CSemaphore2 = nullptr; +StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2; void FRToSI2C::CpltCallback() { hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) @@ -17,13 +19,11 @@ void FRToSI2C::CpltCallback() { } } -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { if (!lock()) return false; - if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, - I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { I2C_Unstick(); unlock(); @@ -43,13 +43,11 @@ uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { Mem_Read(add, reg, tx_data, 1); return tx_data[0]; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, - uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { if (!lock()) return false; - if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, - I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { I2C_Unstick(); unlock(); @@ -63,8 +61,7 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { if (!lock()) return false; - if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) - != HAL_OK) { + if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) { I2C_Unstick(); unlock(); return false; @@ -76,8 +73,7 @@ bool FRToSI2C::probe(uint16_t DevAddress) { if (!lock()) return false; uint8_t buffer[1]; - bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, - I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; + bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; unlock(); return worked; } @@ -87,11 +83,31 @@ void FRToSI2C::I2C_Unstick() { } void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); } bool FRToSI2C::lock() { - return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; } +bool FRToSI2C::lock2() { + if (I2CSemaphore2 == nullptr) + return true; + return xSemaphoreTake(I2CSemaphore2,1000) == pdTRUE; +} + +void FRToSI2C::unlock2() { + if (I2CSemaphore2 == nullptr) + return; + xSemaphoreGive(I2CSemaphore2); +} + +bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) + delay_ms(registers[index].pause_ms); + } + return true; +} diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 2fba6154..2588c008 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -7,9 +7,9 @@ #include "BSP.h" #include "Setup.h" #include -SemaphoreHandle_t FRToSI2C::I2CSemaphore; +SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; -SemaphoreHandle_t FRToSI2C::I2CSemaphore2; +SemaphoreHandle_t FRToSI2C::I2CSemaphore2 = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2; #define FLAG_TIMEOUT 1000 From e6445491bb34ec1cd54ee9cdedbe863936fd374a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 20 Sep 2020 16:09:59 +1000 Subject: [PATCH 15/72] Move OLED to use bulk setup --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 46 +++------- workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 1 - workspace/TS100/Core/BSP/Pine64/preRTOS.cpp | 5 +- workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 15 ++-- workspace/TS100/Core/Drivers/OLED.cpp | 89 +++++++++---------- 5 files changed, 62 insertions(+), 94 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 2588c008..a407f21e 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -9,8 +9,6 @@ #include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; -SemaphoreHandle_t FRToSI2C::I2CSemaphore2 = nullptr; -StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2; #define FLAG_TIMEOUT 1000 void FRToSI2C::CpltCallback() { @@ -28,8 +26,7 @@ int i2c_start() { i2c_flag_clear(I2C0, I2C_FLAG_AERR); /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { if ((timeout--) == 0) { @@ -38,8 +35,7 @@ int i2c_start() { } /* ensure the i2c has been stopped */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { if ((timeout--) == 0) { return (int) -1; @@ -50,8 +46,7 @@ int i2c_start() { i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { if ((timeout--) == 0) { return (int) -1; @@ -154,8 +149,7 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { if ((timeout--) == 0) { i2c_stop(); @@ -200,8 +194,7 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { if ((timeout--) == 0) { i2c_stop(); @@ -259,8 +252,7 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pDat int timeout = 0; /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { if ((timeout--) == 0) { i2c_stop(); @@ -276,8 +268,7 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pDat i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { if ((timeout--) == 0) { i2c_stop(); @@ -342,8 +333,7 @@ bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { i2c_start_on_bus(I2C0); /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT - ; + timeout = FLAG_TIMEOUT; while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { if ((timeout--) == 0) { i2c_stop(); @@ -426,8 +416,10 @@ void FRToSI2C::I2C_Unstick() { } bool FRToSI2C::lock() { - if (I2CSemaphore == nullptr) - return true; + if (I2CSemaphore == nullptr) { + for (;;) { // + } + } return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; } @@ -436,25 +428,15 @@ void FRToSI2C::unlock() { return; xSemaphoreGive(I2CSemaphore); } -bool FRToSI2C::lock2() { - if (I2CSemaphore2 == nullptr) - return true; - return xSemaphoreTake(I2CSemaphore2,1000) == pdTRUE; -} - -void FRToSI2C::unlock2() { - if (I2CSemaphore2 == nullptr) - return; - xSemaphoreGive(I2CSemaphore2); -} bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength) { for (int index = 0; index < registersLength; index++) { if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { return false; } - if (registers[index].pause_ms) + if (registers[index].pause_ms) { delay_ms(registers[index].pause_ms); + } } return true; } diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp index fa55ab11..d0022011 100644 --- a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -11,7 +11,6 @@ #include "fusbpd.h" void postRToSInit() { // Any after RTos setup - FRToSI2C::FRToSInit(); #ifdef POW_PD //Spawn all of the USB-C processors fusb302_start_processing(); diff --git a/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp index 222cc096..e2ddee6a 100644 --- a/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/preRTOS.cpp @@ -11,11 +11,10 @@ #include void preRToSInit() { //Normal system bringup -- GPIO etc - eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); - eclic_global_interrupt_enable(); + hardware_init(); - FRToSI2C::FRToSInit(); gpio_bit_reset(OLED_RESET_GPIO_Port, OLED_RESET_Pin); + FRToSI2C::FRToSInit(); delay_ms(50); gpio_bit_set(OLED_RESET_GPIO_Port, OLED_RESET_Pin); } diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index 88be5e62..ca4a50a4 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -22,10 +22,10 @@ class FRToSI2C { public: static void FRToSInit() { - I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); - xSemaphoreGive(I2CSemaphore); - I2CSemaphore2 = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer2); - xSemaphoreGive(I2CSemaphore2); + if (I2CSemaphore == nullptr) { + I2CSemaphore = xSemaphoreCreateBinaryStatic(&xSemaphoreBuffer); + xSemaphoreGive(I2CSemaphore); + } } static void CpltCallback(); //Normal Tx Callback @@ -41,12 +41,9 @@ public: static bool I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data); static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg); - static void unlock2(); - static bool lock2(); - typedef struct { const uint8_t reg; // The register to write to - const uint8_t val; // The value to write to this register + uint8_t val; // The value to write to this register const uint8_t pause_ms; //How many ms to pause _after_ writing this reg } I2C_REG; static bool writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength); @@ -56,8 +53,6 @@ private: static void I2C_Unstick(); static SemaphoreHandle_t I2CSemaphore; static StaticSemaphore_t xSemaphoreBuffer; - static SemaphoreHandle_t I2CSemaphore2; - static StaticSemaphore_t xSemaphoreBuffer2; }; #endif /* FRTOSI2C_HPP_ */ diff --git a/workspace/TS100/Core/Drivers/OLED.cpp b/workspace/TS100/Core/Drivers/OLED.cpp index 7d5eb0b2..4a8906df 100644 --- a/workspace/TS100/Core/Drivers/OLED.cpp +++ b/workspace/TS100/Core/Drivers/OLED.cpp @@ -30,38 +30,37 @@ uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2]; /*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/ /*All commands are prefixed with 0x80*/ /*Data packets are prefixed with 0x40*/ -uint8_t OLED_Setup_Array[] = { +FRToSI2C::I2C_REG OLED_Setup_Array[] = { /**/ -0x80, 0xAE, /*Display off*/ -0x80, 0xD5, /*Set display clock divide ratio / osc freq*/ -0x80, 0x52, /*Divide ratios*/ -0x80, 0xA8, /*Set Multiplex Ratio*/ -0x80, 0x0F, /*16 == max brightness,39==dimmest*/ -0x80, 0xC0, /*Set COM Scan direction*/ -0x80, 0xD3, /*Set vertical Display offset*/ -0x80, 0x00, /*0 Offset*/ -0x80, 0x40, /*Set Display start line to 0*/ -0x80, 0xA0, /*Set Segment remap to normal*/ -0x80, 0x8D, /*Charge Pump*/ -0x80, 0x14, /*Charge Pump settings*/ -0x80, 0xDA, /*Set VCOM Pins hardware config*/ -0x80, 0x02, /*Combination 2*/ -0x80, 0x81, /*Contrast*/ -0x80, 0x33, /*^51*/ -0x80, 0xD9, /*Set pre-charge period*/ -0x80, 0xF1, /*Pre charge period*/ -0x80, 0xDB, /*Adjust VCOMH regulator ouput*/ -0x80, 0x30, /*VCOM level*/ -0x80, 0xA4, /*Enable the display GDDR*/ -0x80, 0XA6, /*Normal display*/ -0x80, 0x20, /*Memory Mode*/ -0x80, 0x00, /*Wrap memory*/ -0x80, 0xAF /*Display on*/ +{ 0x80, 0xAE, 0 }, /*Display off*/ +{ 0x80, 0xD5, 0 }, /*Set display clock divide ratio / osc freq*/ +{ 0x80, 0x52, 0 }, /*Divide ratios*/ +{ 0x80, 0xA8, 0 }, /*Set Multiplex Ratio*/ +{ 0x80, 0x0F, 0 }, /*16 == max brightness,39==dimmest*/ +{ 0x80, 0xC0, 0 }, /*Set COM Scan direction*/ +{ 0x80, 0xD3, 0 }, /*Set vertical Display offset*/ +{ 0x80, 0x00, 0 }, /*0 Offset*/ +{ 0x80, 0x40, 0 }, /*Set Display start line to 0*/ +{ 0x80, 0xA0, 0 }, /*Set Segment remap to normal*/ +{ 0x80, 0x8D, 0 }, /*Charge Pump*/ +{ 0x80, 0x14, 0 }, /*Charge Pump settings*/ +{ 0x80, 0xDA, 0 }, /*Set VCOM Pins hardware config*/ +{ 0x80, 0x02, 0 }, /*Combination 2*/ +{ 0x80, 0x81, 0 }, /*Contrast*/ +{ 0x80, 0x33, 0 }, /*^51*/ +{ 0x80, 0xD9, 0 }, /*Set pre-charge period*/ +{ 0x80, 0xF1, 0 }, /*Pre charge period*/ +{ 0x80, 0xDB, 0 }, /*Adjust VCOMH regulator ouput*/ +{ 0x80, 0x30, 0 }, /*VCOM level*/ +{ 0x80, 0xA4, 0 }, /*Enable the display GDDR*/ +{ 0x80, 0XA6, 0 }, /*Normal display*/ +{ 0x80, 0x20, 0 }, /*Memory Mode*/ +{ 0x80, 0x00, 0 }, /*Wrap memory*/ +{ 0x80, 0xAF, 0 }, /*Display on*/ }; // Setup based on the SSD1307 and modified for the SSD1306 -const uint8_t REFRESH_COMMANDS[17] = { 0x80, 0xAF, 0x80, 0x21, 0x80, 0x20, 0x80, - 0x7F, 0x80, 0xC0, 0x80, 0x22, 0x80, 0x00, 0x80, 0x01, 0x40 }; +const uint8_t REFRESH_COMMANDS[17] = { 0x80, 0xAF, 0x80, 0x21, 0x80, 0x20, 0x80, 0x7F, 0x80, 0xC0, 0x80, 0x22, 0x80, 0x00, 0x80, 0x01, 0x40 }; /* * Animation timing function that follows a bezier curve. @@ -98,8 +97,8 @@ void OLED::initialize() { // initialisation data to the OLED. setDisplayState(DisplayState::ON); - FRToSI2C::Transmit(DEVICEADDR_OLED, &OLED_Setup_Array[0], - sizeof(OLED_Setup_Array)); + FRToSI2C::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0])); + } void OLED::setFramebuffer(uint8_t *buffer) { @@ -128,8 +127,7 @@ void OLED::drawChar(char c) { } uint16_t index = c - 2; //First index is \x02 uint8_t *charPointer; - charPointer = ((uint8_t*) currentFont) - + ((fontWidth * (fontHeight / 8)) * index); + charPointer = ((uint8_t*) currentFont) + ((fontWidth * (fontHeight / 8)) * index); drawArea(cursor_x, cursor_y, fontWidth, fontHeight, charPointer); cursor_x += fontWidth; } @@ -196,8 +194,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) { OLED_WIDTH - progress); memmove(&firstStripPtr[newStart], &firstBackStripPtr[newEnd], progress); - memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], - progress); + memmove(&secondStripPtr[newStart], &secondBackStripPtr[newEnd], progress); refresh(); osDelay(40); @@ -222,14 +219,14 @@ void OLED::setRotation(bool leftHanded) { // send command struct again with changes if (leftHanded) { - OLED_Setup_Array[11] = 0xC8; // c1? - OLED_Setup_Array[19] = 0xA1; + OLED_Setup_Array[5].val = 0xC8; // c1? + OLED_Setup_Array[9].val = 0xA1; } else { - OLED_Setup_Array[11] = 0xC0; - OLED_Setup_Array[19] = 0xA0; + OLED_Setup_Array[5].val = 0xC0; + OLED_Setup_Array[9].val = 0xA0; } - FRToSI2C::Transmit(DEVICEADDR_OLED, (uint8_t*) OLED_Setup_Array, - sizeof(OLED_Setup_Array)); + FRToSI2C::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0])); + inLeftHandedMode = leftHanded; screenBuffer[5] = inLeftHandedMode ? 0 : 32; // display is shifted by 32 in left handed @@ -337,8 +334,7 @@ void OLED::drawSymbol(uint8_t symbolID) { } // Draw an area, but y must be aligned on 0/8 offset -void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, - const uint8_t *ptr) { +void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) { // Splat this from x->x+wide in two strides if (x <= -wide) return; // cutoffleft @@ -372,8 +368,7 @@ void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, // Draw an area, but y must be aligned on 0/8 offset // For data which has octets swapped in a 16-bit word. -void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, - const uint8_t *ptr) { +void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) { // Splat this from x->x+wide in two strides if (x <= -wide) return; // cutoffleft @@ -407,8 +402,7 @@ void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, } } -void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, - const uint8_t value) { +void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t value) { // Splat this from x->x+wide in two strides if (x <= -wide) return; // cutoffleft @@ -440,8 +434,7 @@ void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, } } -void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, - bool clear) { +void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool clear) { // Draw this in 3 sections // This is basically a N wide version of vertical line From 470cae2459954203cdf84f90f4640edcb33fbd7c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 20 Sep 2020 16:11:19 +1000 Subject: [PATCH 16/72] Remove I2C lock2 --- .../TS100/Core/BSP/Miniware/Model_Config.h | 3 + workspace/TS100/Core/BSP/Pine64/BSP.cpp | 62 ++++++++----------- .../TS100/Core/BSP/Pine64/Model_Config.h | 6 +- workspace/TS100/Core/BSP/Pine64/fusb302b.cpp | 56 +++-------------- .../TS100/Core/Drivers/FUSB302/int_n.cpp | 18 ++---- 5 files changed, 46 insertions(+), 99 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Model_Config.h b/workspace/TS100/Core/BSP/Miniware/Model_Config.h index 0ed53702..d2732c6a 100644 --- a/workspace/TS100/Core/BSP/Miniware/Model_Config.h +++ b/workspace/TS100/Core/BSP/Miniware/Model_Config.h @@ -21,6 +21,7 @@ #define ACCEL_MMA #define ACCEL_LIS #define TEMP_TMP36 +#define BATTFILTERDEPTH 32 #endif #ifdef MODEL_TS80 @@ -29,6 +30,7 @@ #define TEMP_TMP36 #define ACCEL_ORI_FLIP #define OLED_FLIP +#define BATTFILTERDEPTH 8 #endif #ifdef MODEL_TS80P @@ -39,6 +41,7 @@ #define I2C_SOFT #define ACCEL_ORI_FLIP #define OLED_FLIP +#define BATTFILTERDEPTH 8 #endif #endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index e1632cfb..e027635f 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -11,37 +11,32 @@ #include //2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = {{0}, 0, 0}; +history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { - //TODO + //TODO } uint16_t getTipInstantTemperature() { - uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits + uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits - for (int i = 0; i < 4; i++) { - sum += adc_inserted_data_read(ADC0, i); - sum += adc_inserted_data_read(ADC1, i); - } - return sum; // 8x over sample + for (int i = 0; i < 4; i++) { + sum += adc_inserted_data_read(ADC0, i); + sum += adc_inserted_data_read(ADC1, i); + } + return sum; // 8x over sample } -uint16_t getTipRawTemp(uint8_t refresh) -{ - if (refresh) - { +uint16_t getTipRawTemp(uint8_t refresh) { + if (refresh) { uint16_t lastSample = getTipInstantTemperature(); rawTempFilter.update(lastSample); return lastSample; - } - else - { + } else { return rawTempFilter.average(); } } -uint16_t getHandleTemperature() -{ +uint16_t getHandleTemperature() { #ifdef TEMP_TMP36 // We return the current handle temperature in X10 C // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for @@ -61,29 +56,21 @@ uint16_t getHandleTemperature() #error #endif } -uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) -{ +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN // Therefore we can divide down from there // Multiplying ADC max by 4 for additional calibration options, // ideal term is 467 -#ifdef MODEL_TS100 -#define BATTFILTERDEPTH 32 -#else -#define BATTFILTERDEPTH 8 -#endif static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; static uint8_t index = 0; - if (preFillneeded) - { + if (preFillneeded) { for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) samples[i] = getADC(1); preFillneeded--; } - if (sample) - { + if (sample) { samples[index] = getADC(1); index = (index + 1) % BATTFILTERDEPTH; } @@ -93,28 +80,29 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) sum += samples[i]; sum /= BATTFILTERDEPTH; - if (divisor == 0) - { + if (divisor == 0) { divisor = 1; } return sum * 4 / divisor; } void unstick_I2C() { - // TODO + // TODO } uint8_t getButtonA() { - return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; } uint8_t getButtonB() { - return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; } void reboot() { - // TODO - for (;;) { - } + // TODO + for (;;) { + } } -void delay_ms(uint16_t count) { delay_1ms(count); } +void delay_ms(uint16_t count) { + delay_1ms(count); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 6a64a04f..e2aff5d7 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -17,9 +17,11 @@ #ifdef MODEL_Pinecil #define POW_PD -#define POW_QC +//#define POW_QC #define TEMP_TMP36 -#define ACCEL_BMA +//#define ACCEL_BMA + +#define BATTFILTERDEPTH 32 #endif #endif /* BSP_MINIWARE_MODEL_CONFIG_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp index 6d35bb57..fae5882a 100644 --- a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -70,14 +70,12 @@ static bool fusb_write_byte(uint8_t addr, uint8_t byte) { * buf: The buffer to write */ static bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf) { - FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*)buf, size); + FRToSI2C::Mem_Write(FUSB302B_ADDR, addr, (uint8_t*) buf, size); return true; //TODO } void fusb_send_message(const union pd_msg *msg) { - if (!FRToSI2C::lock2()) { - return; - } + /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { FUSB_FIFO_TX_SOP1, @@ -104,14 +102,10 @@ void fusb_send_message(const union pd_msg *msg) { fusb_write_buf( FUSB_FIFOS, msg_len, msg->bytes); fusb_write_buf( FUSB_FIFOS, 4, eop_seq); - FRToSI2C::unlock2(); - } uint8_t fusb_read_message(union pd_msg *msg) { - if (!FRToSI2C::lock2()) { - return 1; - } + static uint8_t garbage[4]; uint8_t numobj; @@ -129,33 +123,23 @@ uint8_t fusb_read_message(union pd_msg *msg) { /* Throw the CRC32 in the garbage, since the PHY already checked it. */ fusb_read_buf( FUSB_FIFOS, 4, garbage); - FRToSI2C::unlock2(); return 0; } void fusb_send_hardrst() { - if (!FRToSI2C::lock2()) { - return; - } /* Send a hard reset */ fusb_write_byte( FUSB_CONTROL3, 0x07 | FUSB_CONTROL3_SEND_HARD_RESET); - FRToSI2C::unlock2(); } void fusb_setup() { - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - if (!FRToSI2C::lock2()) { - return; - } - } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); osDelay(2); - if (!fusb_read_id()) { - return; + while (!fusb_read_id()) { + osDelay(10); } /* Turn on all power */ @@ -194,48 +178,27 @@ void fusb_setup() { fusb_write_byte( FUSB_SWITCHES1, 0x26); fusb_write_byte( FUSB_SWITCHES0, 0x0B); } - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - FRToSI2C::unlock2(); - } + fusb_reset(); } void fusb_get_status(union fusb_status *status) { - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - if (!FRToSI2C::lock2()) { - return; - } - } /* Read the interrupt and status flags into status */ fusb_read_buf( FUSB_STATUS0A, 7, status->bytes); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - FRToSI2C::unlock2(); - } } enum fusb_typec_current fusb_get_typec_current() { - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - if (!FRToSI2C::lock2()) { - return fusb_tcc_none; - } - } + /* Read the BC_LVL into a variable */ enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - FRToSI2C::unlock2(); - } + return bc_lvl; } void fusb_reset() { - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - if (!FRToSI2C::lock2()) { - return; - } - } /* Flush the TX buffer */ fusb_write_byte( FUSB_CONTROL0, 0x44); @@ -243,9 +206,6 @@ void fusb_reset() { fusb_write_byte( FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH); /* Reset the PD logic */ // fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET); - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - FRToSI2C::unlock2(); - } } bool fusb_read_id() { diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index a94e21b7..addd92e3 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -32,8 +32,7 @@ uint32_t InterruptHandler::TaskBuffer[InterruptHandler::TaskStackSize]; osStaticThreadDef_t InterruptHandler::TaskControlBlock; void InterruptHandler::init() { - osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, - TaskBuffer, &TaskControlBlock); + osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock); TaskHandle = osThreadCreate(osThread(intTask), NULL); } @@ -42,8 +41,7 @@ void InterruptHandler::Thread(const void *arg) { union fusb_status status; while (true) { /* If the INT_N line is low */ - if (xTaskNotifyWait(0x00, 0x0F, NULL, - PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) { + if (xTaskNotifyWait(0x00, 0x0F, NULL, PolicyEngine::setupCompleteOrTimedOut() ? 1000 : 10) == pdPASS) { //delay slightly so we catch the crc with better timing osDelay(1); } @@ -52,12 +50,10 @@ void InterruptHandler::Thread(const void *arg) { /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX * thread */ if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) { - ProtocolTransmit::notify( - ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT); + ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT); } if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) { - ProtocolTransmit::notify( - ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); + ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL); } /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */ @@ -68,8 +64,7 @@ void InterruptHandler::Thread(const void *arg) { /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy * Engine thread */ - if (status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP - && status.status1 & FUSB_STATUS1_OVRTEMP) { + if ((status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP) && (status.status1 & FUSB_STATUS1_OVRTEMP)) { PolicyEngine::notify(PDB_EVT_PE_I_OVRTEMP); } } @@ -77,8 +72,7 @@ void InterruptHandler::Thread(const void *arg) { void InterruptHandler::irqCallback() { if (TaskHandle != NULL) { BaseType_t taskWoke = pdFALSE; - xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, - &taskWoke); + xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); portYIELD_FROM_ISR(taskWoke); } } From 60e3616c7992d07ccb59f41f9fbd5b891488adaa Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 20 Sep 2020 16:15:55 +1000 Subject: [PATCH 17/72] Fix PD IRQ --- workspace/TS100/Core/BSP/Pine64/BSP_PD.c | 9 ++++--- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 17 ++++++++++++- workspace/TS100/Core/BSP/Pine64/IRQ.h | 1 + workspace/TS100/Core/BSP/Pine64/Pins.h | 3 +++ workspace/TS100/Core/BSP/Pine64/Setup.c | 24 +++++++++++++------ .../TS100/Core/Drivers/FUSB302/int_n.cpp | 10 ++++---- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP_PD.c b/workspace/TS100/Core/BSP/Pine64/BSP_PD.c index 0b3c2af9..7796ed51 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP_PD.c +++ b/workspace/TS100/Core/BSP/Pine64/BSP_PD.c @@ -13,10 +13,13 @@ */ const uint16_t USB_PD_Desired_Levels[] = { //mV desired input, mA minimum required current - 12000, 2400, //12V @ 2.4A - 9000, 2000, //9V @ 2A + //Tip is ~ 7.5 ohms + 20000, 2666, // 20V, 2.6A + 15000, 2000, // 15V 2A + 12000, 1600, //12V @ 1.6A + 9000, 1200, //9V @ 1.2A 5000, 100, //5V @ whatever }; -const uint8_t USB_PD_Desired_Levels_Len = 3; +const uint8_t USB_PD_Desired_Levels_Len = 5; #endif diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index eb2c8885..380f51e6 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -6,7 +6,8 @@ */ #include "IRQ.h" - +#include "Pins.h" +#include "int_n.h" void ADC0_1_IRQHandler(void) { adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); @@ -51,3 +52,17 @@ void setTipPWM(uint8_t pulse) { pendingPWM = pulse; } + + +void EXTI5_9_IRQHandler(void) +{ +#ifdef POW_PD + if (RESET != exti_interrupt_flag_get(EXTI_5)){ + exti_interrupt_flag_clear(EXTI_5); + + if(RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)){ + InterruptHandler::irqCallback(); + } + } +#endif +} diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.h b/workspace/TS100/Core/BSP/Pine64/IRQ.h index 8c6c7325..f1490828 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.h +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.h @@ -19,6 +19,7 @@ extern "C" { #endif void ADC0_1_IRQHandler(void); void TIMER1_IRQHandler(void); +void EXTI5_9_IRQHandler(void); #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Pine64/Pins.h b/workspace/TS100/Core/BSP/Pine64/Pins.h index 371675da..42cae4c3 100644 --- a/workspace/TS100/Core/BSP/Pine64/Pins.h +++ b/workspace/TS100/Core/BSP/Pine64/Pins.h @@ -35,4 +35,7 @@ #define SDA_Pin BIT(7) #define SDA_GPIO_Port GPIOB +#define FUSB302_IRQ_Pin BIT(5) +#define FUSB302_IRQ_GPIO_Port GPIOB + #endif /* BSP_MINIWARE_PINS_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index a7763dbf..f202d302 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -35,11 +35,12 @@ void hardware_init() { //Timers setup_timers(); //Watchdog - // setup_iwdg(); + setup_iwdg(); /* enable TIMER1 - PWM control timing*/ timer_enable(TIMER1); timer_enable(TIMER2); + eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); eclic_global_interrupt_enable(); } // channel 0 -> temperature sensor, 1-> VIN @@ -64,8 +65,8 @@ void setup_gpio() { gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin); //I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ, SDA_Pin); - gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_2MHZ, SCL_Pin); + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin); + gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SCL_Pin); //PWM output as AF Push Pull gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); @@ -78,6 +79,16 @@ void setup_gpio() { //Remap PB4 away from JTAG NJRST gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); + //Setup IRQ for USB-PD + gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, FUSB302_IRQ_Pin); + eclic_irq_enable(EXTI5_9_IRQn, 1, 1); + /* connect key EXTI line to key GPIO pin */ + gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); + + /* configure key EXTI line */ + exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); + exti_interrupt_flag_clear(EXTI_5); + //TODO - rest of pins as floating } void setup_dma() { @@ -114,7 +125,7 @@ void setup_i2c() { //TODO - DMA /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); - //Setup I20 at 100kHz with DMA? + //Setup I20 at 400kHz i2c_clock_config(I2C0, 100 * 1000, I2C_DTCY_16_9); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); @@ -189,8 +200,8 @@ void setup_adc() { adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); adc_interrupt_enable(ADC0, ADC_INT_EOIC); eclic_irq_enable(ADC0_1_IRQn, 2, 0); -// adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); -// adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); adc_tempsensor_vrefint_disable(); } void setup_timers() { @@ -266,7 +277,6 @@ void setup_timers() { timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); -//todo timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0); diff --git a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp index addd92e3..9250b4a0 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/int_n.cpp @@ -70,9 +70,11 @@ void InterruptHandler::Thread(const void *arg) { } } void InterruptHandler::irqCallback() { - if (TaskHandle != NULL) { - BaseType_t taskWoke = pdFALSE; - xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); - portYIELD_FROM_ISR(taskWoke); + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + if (TaskHandle != NULL) { + BaseType_t taskWoke = pdFALSE; + xTaskNotifyFromISR(TaskHandle, 0x01, eNotifyAction::eSetBits, &taskWoke); + portYIELD_FROM_ISR(taskWoke); + } } } From 89522027b7b79681c761bc276c751445f9b9c93d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 20 Sep 2020 16:24:39 +1000 Subject: [PATCH 18/72] Fix voltage on home screen --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 5 +- .../TS100/Core/BSP/Pine64/Model_Config.h | 5 +- workspace/TS100/Core/Threads/GUIThread.cpp | 198 +++++++----------- 3 files changed, 84 insertions(+), 124 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index e027635f..ebe57772 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -57,10 +57,7 @@ uint16_t getHandleTemperature() { #endif } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { -// ADC maximum is 32767 == 3.3V at input == 28.05V at VIN -// Therefore we can divide down from there -// Multiplying ADC max by 4 for additional calibration options, -// ideal term is 467 + static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index e2aff5d7..d45fd4e7 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -17,10 +17,9 @@ #ifdef MODEL_Pinecil #define POW_PD -//#define POW_QC +#define POW_QC #define TEMP_TMP36 -//#define ACCEL_BMA - +#define ACCEL_BMA #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 280655b6..e04340a9 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -59,9 +59,9 @@ void gui_drawTipTemp(bool symbol) { // Draw tip temp handling unit conversion & tolerance near setpoint uint16_t Temp = 0; #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF){ - Temp = TipThermoModel::getTipInF(); - }else + if (systemSettings.temperatureInF) { + Temp = TipThermoModel::getTipInF(); + } else #endif { Temp = TipThermoModel::getTipInC(); @@ -72,17 +72,17 @@ void gui_drawTipTemp(bool symbol) { if (OLED::getFont() == 0) { // Big font, can draw nice symbols #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else #endif OLED::drawSymbol(1); } else { // Otherwise fall back to chars #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - OLED::print(SymbolDegF); - else + if (systemSettings.temperatureInF) + OLED::print(SymbolDegF); + else #endif OLED::print(SymbolDegC); } @@ -123,24 +123,8 @@ static bool checkVoltageForExit() { } #endif static void gui_drawBatteryIcon() { -#ifdef MODEL_TS100 - if (systemSettings.cutoutSetting) { - // User is on a lithium battery - // we need to calculate which of the 10 levels they are on - uint8_t cellCount = systemSettings.cutoutSetting + 2; - uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) - / cellCount; - // Should give us approx cell voltage X10 - // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 - if (cellV < 33) - cellV = 33; - cellV -= 33; // Should leave us a number of 0-9 - if (cellV > 9) - cellV = 9; - OLED::drawBattery(cellV + 1); - } else - OLED::drawSymbol(15); // Draw the DC Logo -#else +#if defined(POW_PD) || defined(POW_QC) + // On TS80 we replace this symbol with the voltage we are operating on // If <9V then show single digit, if not show duals uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); @@ -151,7 +135,7 @@ static void gui_drawBatteryIcon() { if (V >= 10) { int16_t xPos = OLED::getCursorX(); OLED::setFont(1); - OLED::printNumber(1, 1); + OLED::printNumber(V / 10, 1); OLED::setCursor(xPos, 8); OLED::printNumber(V % 10, 1); OLED::setFont(0); @@ -159,7 +143,25 @@ static void gui_drawBatteryIcon() { } else { OLED::printNumber(V, 1); } +#else + if (systemSettings.cutoutSetting) { + // User is on a lithium battery + // we need to calculate which of the 10 levels they are on + uint8_t cellCount = systemSettings.cutoutSetting + 2; + uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) + / cellCount; + // Should give us approx cell voltage X10 + // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 + if (cellV < 33) + cellV = 33; + cellV -= 33;// Should leave us a number of 0-9 + if (cellV > 9) + cellV = 9; + OLED::drawBattery(cellV + 1); + } else + OLED::drawSymbol(15); // Draw the DC Logo #endif + } static void gui_solderingTempAdjust() { uint32_t lastChange = xTaskGetTickCount(); @@ -182,14 +184,11 @@ static void gui_solderingTempAdjust() { return; break; case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer - + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += - systemSettings.TempChangeLongStep; + systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; } else - systemSettings.SolderingTemp -= - systemSettings.TempChangeLongStep; + systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; autoRepeatTimer = xTaskGetTickCount(); autoRepeatAcceleration += PRESS_ACCEL_STEP; @@ -197,47 +196,38 @@ static void gui_solderingTempAdjust() { break; case BUTTON_B_SHORT: if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp += - systemSettings.TempChangeShortStep; + systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; } else - systemSettings.SolderingTemp -= - systemSettings.TempChangeShortStep; + systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; break; case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer - + autoRepeatAcceleration> PRESS_ACCEL_INTERVAL_MAX) { + if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= - systemSettings.TempChangeLongStep; + systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; } else - systemSettings.SolderingTemp += - systemSettings.TempChangeLongStep; + systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; autoRepeatTimer = xTaskGetTickCount(); autoRepeatAcceleration += PRESS_ACCEL_STEP; } break; case BUTTON_F_SHORT: if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= - systemSettings.TempChangeShortStep; // add 10 + systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 } else - systemSettings.SolderingTemp += - systemSettings.TempChangeShortStep; // add 10 + systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 break; default: break; } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) - < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - - PRESS_ACCEL_INTERVAL_MIN; + if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { + autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; } // constrain between 10-450 C #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) { - if (systemSettings.SolderingTemp > 850) systemSettings.SolderingTemp = 850; - if (systemSettings.SolderingTemp < 60) systemSettings.SolderingTemp = 60; - } else + if (systemSettings.temperatureInF) { + if (systemSettings.SolderingTemp > 850) systemSettings.SolderingTemp = 850; + if (systemSettings.SolderingTemp < 60) systemSettings.SolderingTemp = 60; + } else #endif { if (systemSettings.SolderingTemp > 450) @@ -254,21 +244,17 @@ static void gui_solderingTempAdjust() { #else if (OLED::getRotation()) { #endif - OLED::print( - systemSettings.ReverseButtonTempChangeEnabled ? - SymbolPlus : SymbolMinus); + OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); } else { - OLED::print( - systemSettings.ReverseButtonTempChangeEnabled ? - SymbolMinus : SymbolPlus); + OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); } OLED::print(SymbolSpace); OLED::printNumber(systemSettings.SolderingTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else #endif { OLED::drawSymbol(1); @@ -279,13 +265,9 @@ static void gui_solderingTempAdjust() { #else if (OLED::getRotation()) { #endif - OLED::print( - systemSettings.ReverseButtonTempChangeEnabled ? - SymbolMinus : SymbolPlus); + OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolMinus : SymbolPlus); } else { - OLED::print( - systemSettings.ReverseButtonTempChangeEnabled ? - SymbolPlus : SymbolMinus); + OLED::print(systemSettings.ReverseButtonTempChangeEnabled ? SymbolPlus : SymbolMinus); } OLED::refresh(); GUIDelay(); @@ -299,33 +281,26 @@ static int gui_SolderingSleepingMode(bool stayOff) { ButtonState buttons = getButtonState(); if (buttons) return 0; - if ((xTaskGetTickCount() > 1000) - && ((accelInit - && (xTaskGetTickCount() - lastMovementTime < 1000)) - || (xTaskGetTickCount() - lastButtonTime < 1000))) + if ((xTaskGetTickCount() > 1000) && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 1000)) || (xTaskGetTickCount() - lastButtonTime < 1000))) return 0; // user moved or pressed a button, go back to soldering #ifdef MODEL_TS100 - if (checkVoltageForExit()) + if (checkVoltageForExit()) return 1; // return non-zero on error #endif #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) { - currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); - } else + if (systemSettings.temperatureInF) { + currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); + } else #endif { - currentTempTargetDegC = - stayOff ? - 0 : - min(systemSettings.SleepTemp, - systemSettings.SolderingTemp); + currentTempTargetDegC = stayOff ? 0 : min(systemSettings.SleepTemp, systemSettings.SolderingTemp); } // draw the lcd uint16_t tipTemp; #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - tipTemp = TipThermoModel::getTipInF(); - else + if (systemSettings.temperatureInF) + tipTemp = TipThermoModel::getTipInF(); + else #endif { tipTemp = TipThermoModel::getTipInC(); @@ -340,9 +315,9 @@ static int gui_SolderingSleepingMode(bool stayOff) { OLED::print(SleepingTipAdvancedString); OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - OLED::print(SymbolDegF); - else + if (systemSettings.temperatureInF) + OLED::print(SymbolDegF); + else #endif { OLED::print(SymbolDegC); @@ -356,9 +331,9 @@ static int gui_SolderingSleepingMode(bool stayOff) { OLED::print(SleepingSimpleString); OLED::printNumber(tipTemp, 3); #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - OLED::drawSymbol(0); - else + if (systemSettings.temperatureInF) + OLED::drawSymbol(0); + else #endif { OLED::drawSymbol(1); @@ -366,8 +341,7 @@ static int gui_SolderingSleepingMode(bool stayOff) { } if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 if (lastMovementTime) - if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) - > (uint32_t) (systemSettings.ShutdownTime * 60 * 1000)) { + if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) > (uint32_t) (systemSettings.ShutdownTime * 60 * 1000)) { // shutdown currentTempTargetDegC = 0; return 1; // we want to exit soldering mode @@ -383,9 +357,7 @@ static void display_countdown(int sleepThres) { * Print seconds or minutes (if > 99 seconds) until sleep * mode is triggered. */ - int lastEventTime = - lastButtonTime < lastMovementTime ? - lastMovementTime : lastButtonTime; + int lastEventTime = lastButtonTime < lastMovementTime ? lastMovementTime : lastButtonTime; int downCount = sleepThres - xTaskGetTickCount() + lastEventTime; if (downCount > 99000) { OLED::printNumber(downCount / 60000 + 1, 2); @@ -517,18 +489,18 @@ static void gui_solderingMode(uint8_t jumpToSleep) { // Update the setpoints for the temperature if (boostModeOn) { #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); - else + if (systemSettings.temperatureInF) + currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); + else #endif { currentTempTargetDegC = (systemSettings.BoostTemp); } } else { #ifdef ENABLED_FAHRENHEIT_SUPPORT - if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); - else + if (systemSettings.temperatureInF) + currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); + else #endif { currentTempTargetDegC = (systemSettings.SolderingTemp); @@ -544,8 +516,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { #endif if (systemSettings.sensitivity && systemSettings.SleepTime) - if (xTaskGetTickCount() - lastMovementTime > sleepThres - && xTaskGetTickCount() - lastButtonTime > sleepThres) { + if (xTaskGetTickCount() - lastMovementTime > sleepThres && xTaskGetTickCount() - lastButtonTime > sleepThres) { if (gui_SolderingSleepingMode(false)) { return; // If the function returns non-0 then exit } @@ -593,8 +564,7 @@ void showDebugMenu(void) { { uint32_t temp = systemSettings.CalibrationOffset; systemSettings.CalibrationOffset = 0; - OLED::printNumber( - TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); + OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); systemSettings.CalibrationOffset = temp; } break; @@ -642,8 +612,7 @@ void startGUITask(void const *argument __unused) { //flipped is generated by flipping each row for (int row = 0; row < 2; row++) { for (int x = 0; x < 84; x++) { - idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) - + (83 - x)]; + idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + (83 - x)]; } } } @@ -736,11 +705,7 @@ void startGUITask(void const *argument __unused) { // button presses) in a while. OLED::setDisplayState(OLED::DisplayState::ON); - if ((tipTemp < 50) && systemSettings.sensitivity - && (((xTaskGetTickCount() - lastMovementTime) - > MOVEMENT_INACTIVITY_TIME) - && ((xTaskGetTickCount() - lastButtonTime) - > BUTTON_INACTIVITY_TIME))) { + if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { OLED::setDisplayState(OLED::DisplayState::OFF); } @@ -799,8 +764,7 @@ void startGUITask(void const *argument __unused) { OLED::setCursor(0, 0); } // draw in the temp - if (!(systemSettings.coolingTempBlink - && (xTaskGetTickCount() % 25 < 16))) + if (!(systemSettings.coolingTempBlink && (xTaskGetTickCount() % 25 < 16))) gui_drawTipTemp(false); // draw in the temp } } From 42f643c40fea2f690da5ab2f4509eeaf47435108 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 20 Sep 2020 17:05:36 +1000 Subject: [PATCH 19/72] Update I2C_Wrapper.cpp --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 39 ++----------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index a407f21e..8834944b 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -228,9 +228,7 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData for (count = 0; count < Size; count++) { pData[count] = i2c_byte_read(count == (Size - 1)); } - - /* if not sequential write, then send stop */ - + //Have nacked last data, so have to generate the stop sequence i2c_stop(); unlock(); return true; @@ -376,39 +374,8 @@ bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { } bool FRToSI2C::probe(uint16_t DevAddress) { - if (!lock()) - return false; - i2c_start(); - /* send slave address to I2C bus */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - /* wait until ADDSEND bit is set */ - int timeout = FLAG_TIMEOUT; - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - if (i2c_flag_get(I2C0, I2C_FLAG_AERR) || i2c_flag_get(I2C0, I2C_FLAG_BERR)) { - i2c_stop(); - unlock(); - return false; - } - if (timeout-- == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* clear ADDSEND bit */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - /* wait until the transmit data buffer is empty */ - while (!i2c_flag_get(I2C0, I2C_FLAG_TBE)) - ; - bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* wait until stop condition generate */ - while (I2C_CTL0(I2C0) & 0x0200) - ; - unlock(); - return !no_ack; + uint8_t temp = 0; + return Mem_Read(DevAddress, 0x00, &temp, 1); } void FRToSI2C::I2C_Unstick() { From e38da13306cc259acdd723792f303ecbb0f0f9bf Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 22 Sep 2020 21:03:09 +1000 Subject: [PATCH 20/72] Rework _all_ of the I2C This moves all of the I2C code to IRQ based (not DMA _yet_). But it does drastically improve reliability, especially of reads. --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 19 +- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 425 ++---- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 236 +++- workspace/TS100/Core/BSP/Pine64/IRQ.h | 25 + .../TS100/Core/BSP/Pine64/Model_Config.h | 2 + workspace/TS100/Core/BSP/Pine64/Setup.c | 7 +- .../Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c | 117 -- .../Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c | 112 -- .../TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h | 65 - .../BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c | 1144 ++++++++--------- workspace/TS100/Core/BSP/Pine64/fusb302b.cpp | 9 +- workspace/TS100/Core/Drivers/BMA223.cpp | 32 +- workspace/TS100/Core/Drivers/BMA223.hpp | 2 +- workspace/TS100/Core/Drivers/LIS2DH12.cpp | 4 +- workspace/TS100/Core/Drivers/LIS2DH12.hpp | 2 +- workspace/TS100/Core/Drivers/MMA8652FC.cpp | 4 +- workspace/TS100/Core/Drivers/MMA8652FC.hpp | 2 +- workspace/TS100/Core/Src/main.cpp | 2 +- workspace/TS100/Core/Threads/GUIThread.cpp | 4 +- workspace/TS100/Core/Threads/MOVThread.cpp | 25 +- 20 files changed, 978 insertions(+), 1260 deletions(-) delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index ebe57772..7eef4672 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -84,7 +84,24 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { } void unstick_I2C() { - // TODO + /* configure SDA/SCL for GPIO */ + GPIO_BC(GPIOB) |= SDA_Pin|SCL_Pin; + gpio_init(SDA_GPIO_Port,GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SCL_Pin; + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SDA_Pin; + /* connect PB6 to I2C0_SCL */ + /* connect PB7 to I2C0_SDA */ + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); } uint8_t getButtonA() { diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 8834944b..57cd78c2 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -6,233 +6,15 @@ */ #include "BSP.h" #include "Setup.h" +#include "IRQ.h" #include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; #define FLAG_TIMEOUT 1000 - void FRToSI2C::CpltCallback() { //TODO } -/** Send START command - * - * @param obj The I2C object - */ -int i2c_start() { - int timeout; - - /* clear I2C_FLAG_AERR Flag */ - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - - return (int) -1; - } - } - - /* ensure the i2c has been stopped */ - timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP) == I2C_CTL0_STOP) { - if ((timeout--) == 0) { - return (int) -1; - } - } - - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - return (int) -1; - } - } - - return (int) 0; -} - -/** Send STOP command - * - * @param obj The I2C object - */ -int i2c_stop() { - - /* generate a STOP condition */ - i2c_stop_on_bus(I2C0); - - /* wait for STOP bit reset */ - int timeout = FLAG_TIMEOUT; - while ((I2C_CTL0(I2C0) & I2C_CTL0_STOP)) { - if ((timeout--) == 0) { - return -1; - } - } - - return 0; -} - -/** Read one byte - * - * @param obj The I2C object - * @param last Acknoledge - * @return The read byte - */ -int i2c_byte_read(int last) { - int timeout; - - if (last) { - /* disable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } else { - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - } - - /* wait until the byte is received */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_RBNE)) == RESET) { - if ((timeout--) == 0) { - return -1; - } - } - - return (int) i2c_data_receive(I2C0); -} - -/** Write one byte - * - * @param obj The I2C object - * @param data Byte to be written - * @return 0 if NAK was received, 1 if ACK was received, 2 for timeout. - */ -int i2c_byte_write(int data) { - int timeout; - i2c_data_transmit(I2C0, data); - - /* wait until the byte is transmitted */ - timeout = FLAG_TIMEOUT; - while (((i2c_flag_get(I2C0, I2C_FLAG_TBE)) == RESET) || ((i2c_flag_get(I2C0, I2C_FLAG_BTC)) == RESET)) { - if ((timeout--) == 0) { - return 2; - } - } - - return 1; -} - -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - bool no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - if (no_ack) { - i2c_stop(); - unlock(); - return false; - } - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - int status = i2c_byte_write(MemAddress); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_BERR); - no_ack |= i2c_flag_get(I2C0, I2C_FLAG_LOSTARB); - if (status == 2 || no_ack) { - i2c_stop(); - unlock(); - return false; - } -//////////////////////////// //Restart into read - - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - no_ack = i2c_flag_get(I2C0, I2C_FLAG_AERR); - if (no_ack) { - i2c_stop(); - unlock(); - return false; - } - for (count = 0; count < Size; count++) { - pData[count] = i2c_byte_read(count == (Size - 1)); - } - //Have nacked last data, so have to generate the stop sequence - i2c_stop(); - unlock(); - return true; -} bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); } @@ -242,140 +24,114 @@ uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { Mem_Read(add, reg, &temp, 1); return temp; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { + +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) { + if (!lock()) + return false; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + /* wait until I2C bus is idle */ + uint8_t timeout = 0; + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { + timeout++; + osDelay(1); + if (timeout > 20) { + unlock(); + return false; + } + } + i2c_slave_address = DevAddress; + i2c_read = p_buffer; + i2c_read_dress = read_address; + i2c_nbytes = number_of_byte; + i2c_error_code = 0; + i2c_process_flag = 1; + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + i2c_read_process = I2C_SEND_ADDRESS_FIRST; + +// if (2 == number_of_byte) { +// i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT); +// } + /* enable the I2C0 interrupt */ + i2c_interrupt_enable(I2C0, I2C_INT_ERR); + i2c_interrupt_enable(I2C0, I2C_INT_EV); + i2c_interrupt_enable(I2C0, I2C_INT_BUF); + /* send a start condition to I2C bus */ + i2c_start_on_bus(I2C0); + while ((i2c_nbytes > 0)) { + osDelay(1); + if (i2c_error_code != 0) { + unlock(); + return false; + } + } + unlock(); + return true; +} + +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) { if (!lock()) return false; - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { + i2c_slave_address = DevAddress; + i2c_write = p_buffer; + i2c_write_dress = MemAddress; + i2c_nbytes = number_of_byte; + i2c_error_code = 0; + i2c_process_flag = 0; + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + i2c_read_process = I2C_SEND_ADDRESS_FIRST; + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + /* enable the I2C0 interrupt */ + i2c_interrupt_enable(I2C0, I2C_INT_ERR); + i2c_interrupt_enable(I2C0, I2C_INT_EV); + i2c_interrupt_enable(I2C0, I2C_INT_BUF); + /* wait until I2C bus is idle */ + uint8_t timeout = 0; + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { timeout++; - if (timeout > 100000) { - i2c_stop(); + osDelay(1); + if (timeout > 20) { unlock(); return false; } } - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - int status = i2c_byte_write(MemAddress); - for (count = 0; count < Size; count++) { - status = i2c_byte_write(pData[count]); - if (status != 1) { - i2c_stop(); + /* send a start condition to I2C bus */ + //This sending will kickoff the IRQ's + i2c_start_on_bus(I2C0); + while ((i2c_nbytes > 0)) { + osDelay(1); + if (i2c_error_code != 0) { unlock(); return false; } } - - /* if not sequential write, then send stop */ - - i2c_stop(); unlock(); return true; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - uint32_t count = 0; - int timeout = 0; - - /* wait until I2C_FLAG_I2CBSY flag is reset */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) == SET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } else { - if (timeout % 5 == 0) { - i2c_stop(); - } - } - } - /* generate a START condition */ - i2c_start_on_bus(I2C0); - - /* ensure the i2c has been started successfully */ - timeout = FLAG_TIMEOUT; - while ((i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) == RESET) { - if ((timeout--) == 0) { - i2c_stop(); - unlock(); - return false; - } - } - - /* send slave address */ - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - - timeout = 0; - /* wait until I2C_FLAG_ADDSEND flag is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) { - timeout++; - if (timeout > 100000) { - i2c_stop(); - unlock(); - return false; - } - } - - /* clear ADDSEND */ - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - - for (count = 0; count < Size; count++) { - int status = i2c_byte_write(pData[count]); - if (status != 1) { - i2c_stop(); - unlock(); - return false; - } - } - - /* if not sequential write, then send stop */ - - i2c_stop(); - unlock(); - return true; + return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); } bool FRToSI2C::probe(uint16_t DevAddress) { - uint8_t temp = 0; - return Mem_Read(DevAddress, 0x00, &temp, 1); + uint8_t temp[1]; + return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); } void FRToSI2C::I2C_Unstick() { @@ -384,15 +140,12 @@ void FRToSI2C::I2C_Unstick() { bool FRToSI2C::lock() { if (I2CSemaphore == nullptr) { - for (;;) { // - } + return false; } return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; } void FRToSI2C::unlock() { - if (I2CSemaphore == nullptr) - return; xSemaphoreGive(I2CSemaphore); } diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index 380f51e6..60ef5f8b 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -8,6 +8,16 @@ #include "IRQ.h" #include "Pins.h" #include "int_n.h" +volatile uint8_t i2c_read_process = 0; +volatile uint8_t i2c_write_process = 0; +volatile uint8_t i2c_slave_address = 0; +volatile uint8_t i2c_error_code = 0; +volatile uint8_t* i2c_write; +volatile uint8_t* i2c_read; +volatile uint16_t i2c_nbytes; +volatile uint16_t i2c_write_dress; +volatile uint16_t i2c_read_dress; +volatile uint8_t i2c_process_flag = 0; void ADC0_1_IRQHandler(void) { adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); @@ -39,8 +49,7 @@ void TIMER1_IRQHandler(void) { timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); if (pendingPWM) { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, - pendingPWM); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); } } } @@ -53,16 +62,221 @@ void setTipPWM(uint8_t pulse) { pendingPWM = pulse; } - -void EXTI5_9_IRQHandler(void) -{ +void EXTI5_9_IRQHandler(void) { #ifdef POW_PD - if (RESET != exti_interrupt_flag_get(EXTI_5)){ - exti_interrupt_flag_clear(EXTI_5); + if (RESET != exti_interrupt_flag_get(EXTI_5)) { + exti_interrupt_flag_clear(EXTI_5); - if(RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)){ - InterruptHandler::irqCallback(); - } - } + if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) { + InterruptHandler::irqCallback(); + } + } #endif } + +/*! + \brief handle I2C0 event interrupt request + \param[in] none + \param[out] none + \retval none + */ +void I2C0_EV_IRQHandler(void) { + if (RESET == i2c_process_flag) { + switch (i2c_write_process) { + case I2C_SEND_ADDRESS_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + /* send slave address */ + i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); + i2c_write_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_write_process = I2C_TRANSMIT_WRITE_READ_ADD; + } + break; + case I2C_TRANSMIT_WRITE_READ_ADD: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + i2c_data_transmit(I2C0, i2c_write_dress); + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + i2c_write_process = I2C_TRANSMIT_DATA; + } + break; + case I2C_TRANSMIT_DATA: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + /* the master sends a data byte */ + i2c_data_transmit(I2C0, *i2c_write++); + i2c_nbytes--; + if (RESET == i2c_nbytes) { + i2c_write_process = I2C_STOP; + } + } + break; + case I2C_STOP: + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_write_process = I2C_SEND_ADDRESS_FIRST; + break; + default: + break; + } + } else if (SET == i2c_process_flag) { + switch (i2c_read_process) { + case I2C_SEND_ADDRESS_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + /* send slave address */ + i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); + i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_FIRST: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_read_process = I2C_TRANSMIT_WRITE_READ_ADD; + } + break; + case I2C_TRANSMIT_WRITE_READ_ADD: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + i2c_data_transmit(I2C0, i2c_read_dress); + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + /* send a start condition to I2C bus */ + i2c_start_on_bus(I2C0); + i2c_read_process = I2C_SEND_ADDRESS_SECOND; + } + break; + case I2C_SEND_ADDRESS_SECOND: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { + i2c_master_addressing(I2C0, i2c_slave_address, I2C_RECEIVER); + if ((1 == i2c_nbytes) || (2 == i2c_nbytes)) { + i2c_ackpos_config(I2C0, i2c_nbytes == 1 ? I2C_ACKPOS_CURRENT : I2C_ACKPOS_NEXT); + /* clear the ACKEN before the ADDSEND is cleared */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } else { + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + + } + i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_SECOND; + } + break; + case I2C_CLEAR_ADDRESS_FLAG_SECOND: + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { + + /*clear ADDSEND bit */ + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); + i2c_read_process = I2C_TRANSMIT_DATA; + + } + break; + case I2C_TRANSMIT_DATA: + if (i2c_nbytes > 0) { + /* read a byte from the EEPROM */ + if (i2c_nbytes == 2) { + /* wait until BTC bit is set */ + i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); + /* clear the ACKEN before the ADDSEND is cleared */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } + *i2c_read = i2c_data_receive(I2C0); + i2c_read++; + i2c_nbytes--; + if (i2c_nbytes == 0) { + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + } + } else { + i2c_read_process = I2C_STOP; + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + } + break; + case I2C_STOP: + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + break; + default: + break; + } + } +} + +/*! + \brief handle I2C0 error interrupt request + \param[in] none + \param[out] none + \retval none + */ +void I2C0_ER_IRQHandler(void) { + /* no acknowledge received */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); + i2c_error_code = 1; //NAK + } + + /* SMBus alert */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); + i2c_error_code = 2; //SMB Alert + } + + /* bus timeout in SMBus mode */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); + i2c_error_code = 3; //SMB Timeout + } + + /* over-run or under-run when SCL stretch is disabled */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); + i2c_error_code = 4; //OverRun + } + + /* arbitration lost */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); + i2c_error_code = 5; //Lost ARB -- multi master -- shouldnt happen + } + + /* bus error */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); + i2c_error_code = 6; //Bus Error + } + + /* CRC value doesn't match */ + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { + i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); + i2c_error_code = 7; //CRC Fail -- Shouldnt Happen + } + + i2c_stop_on_bus(I2C0); + +} diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.h b/workspace/TS100/Core/BSP/Pine64/IRQ.h index f1490828..354a8d6a 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.h +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.h @@ -20,6 +20,31 @@ extern "C" { void ADC0_1_IRQHandler(void); void TIMER1_IRQHandler(void); void EXTI5_9_IRQHandler(void); +/* handle I2C0 event interrupt request */ +void I2C0_EV_IRQHandler(void); +/* handle I2C0 error interrupt request */ +void I2C0_ER_IRQHandler(void); +typedef enum { + I2C_SEND_ADDRESS_FIRST = 0, //Sending slave address + I2C_CLEAR_ADDRESS_FLAG_FIRST, // Clear address send + I2C_TRANSMIT_WRITE_READ_ADD, //Transmit the memory address to read/write from + I2C_SEND_ADDRESS_SECOND, //Send address again for read + I2C_CLEAR_ADDRESS_FLAG_SECOND, //Clear address again + I2C_TRANSMIT_DATA, //Transmit recieve data + I2C_STOP, //Send stop + I2C_ABORTED, // + I2C_DONE,// I2C transfer is complete +} i2c_process_enum; +extern volatile uint8_t i2c_slave_address; +extern volatile uint8_t i2c_read_process; +extern volatile uint8_t i2c_write_process; +extern volatile uint8_t i2c_error_code; +extern volatile uint8_t* i2c_write; +extern volatile uint8_t* i2c_read; +extern volatile uint16_t i2c_nbytes; +extern volatile uint16_t i2c_write_dress; +extern volatile uint16_t i2c_read_dress; +extern volatile uint8_t i2c_process_flag; #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index d45fd4e7..2abb9142 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -20,6 +20,8 @@ #define POW_QC #define TEMP_TMP36 #define ACCEL_BMA + + #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index f202d302..08a2c7d4 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -65,8 +65,7 @@ void setup_gpio() { gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin); //I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin); - gpio_init(SCL_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SCL_Pin); + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); //PWM output as AF Push Pull gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); @@ -126,11 +125,13 @@ void setup_i2c() { /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 400kHz - i2c_clock_config(I2C0, 100 * 1000, I2C_DTCY_16_9); + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); /* enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); + eclic_irq_enable(I2C0_EV_IRQn,1,0); + eclic_irq_enable(I2C0_ER_IRQn,2,0); } void setup_adc() { diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c deleted file mode 100644 index f48da3d2..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C0_IE.c +++ /dev/null @@ -1,117 +0,0 @@ -/*! - \file I2C0_IE.c - \brief I2C0 master transmitter interrupt program - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#include "gd32vf103_i2c.h" - -#include "I2C_IE.h" - -uint32_t event1; - -/*! - \brief handle I2C0 event interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C0_EventIRQ_Handler(void) { - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { - /* send slave address */ - i2c_master_addressing(I2C0, I2C1_SLAVE_ADDRESS7, I2C_TRANSMITTER); - } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { - /*clear ADDSEND bit */ - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); - } else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - if (I2C_nBytes > 0) { - /* the master sends a data byte */ - i2c_data_transmit(I2C0, *i2c_txbuffer++); - I2C_nBytes--; - } else { - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - } - } -} - -/*! - \brief handle I2C0 error interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C0_ErrorIRQ_Handler(void) { - /* no acknowledge received */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); - } - - /* SMBus alert */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); - } - - /* bus timeout in SMBus mode */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); - } - - /* over-run or under-run when SCL stretch is disabled */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); - } - - /* arbitration lost */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); - } - - /* bus error */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); - } - - /* CRC value doesn't match */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); - } - - /* disable the error interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); -} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c deleted file mode 100644 index 096d771b..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C1_IE.c +++ /dev/null @@ -1,112 +0,0 @@ -/*! - \file I2C1_IE.c - \brief I2C1 slave receiver interrupt program - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#include "gd32vf103_i2c.h" - -#include "I2C_IE.h" - -uint32_t event2; - -/*! - \brief handle I2C1 event interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C1_EventIRQ_Handler(void) { - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) { - /* clear the ADDSEND bit */ - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ADDSEND); - } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)) { - /* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */ - *i2c_rxbuffer++ = i2c_data_receive(I2C1); - } else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_STPDET)) { - status = SUCCESS; - /* clear the STPDET bit */ - i2c_enable(I2C1); - /* disable I2C1 interrupt */ - i2c_interrupt_disable(I2C1, I2C_INT_ERR); - i2c_interrupt_disable(I2C1, I2C_INT_BUF); - i2c_interrupt_disable(I2C1, I2C_INT_EV); - } -} - -/*! - \brief handle I2C1 error interrupt request - \param[in] none - \param[out] none - \retval none -*/ -void I2C1_ErrorIRQ_Handler(void) { - /* no acknowledge received */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_AERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_AERR); - } - - /* SMBus alert */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBALT)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBALT); - } - - /* bus timeout in SMBus mode */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SMBTO)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_SMBTO); - } - - /* over-run or under-run when SCL stretch is disabled */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_OUERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_OUERR); - } - - /* arbitration lost */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_LOSTARB)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_LOSTARB); - } - - /* bus error */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR); - } - - /* CRC value doesn't match */ - if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_PECERR)) { - i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_PECERR); - } - - /* disable the error interrupt */ - i2c_interrupt_disable(I2C1, I2C_INT_ERR); - i2c_interrupt_disable(I2C1, I2C_INT_BUF); - i2c_interrupt_disable(I2C1, I2C_INT_EV); -} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h deleted file mode 100644 index 09eb5ea9..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/I2C_IE.h +++ /dev/null @@ -1,65 +0,0 @@ -/*! - \file I2C1_IE.c - \brief The header file of I2C0 and I2C1 interrupt - - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - -*/ - -/* - Copyright (c) 2019, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ -#ifdef __cplusplus -extern "C" { -#endif -#ifndef I2C_IE_H -#define I2C_IE_H - -#include "gd32vf103.h" - -#define I2C0_SLAVE_ADDRESS7 0x82 -#define I2C1_SLAVE_ADDRESS7 0x72 - -extern volatile ErrStatus status; -extern volatile uint8_t *i2c_txbuffer; -extern volatile uint8_t *i2c_rxbuffer; -extern volatile uint16_t I2C_nBytes; - -/* function declarations */ -/* handle I2C0 event interrupt request */ -void I2C0_EventIRQ_Handler(void); -/* handle I2C0 error interrupt request */ -void I2C0_ErrorIRQ_Handler(void); -/* handle I2C1 event interrupt request */ -void I2C1_EventIRQ_Handler(void); -/* handle I2C1 error interrupt request */ -void I2C1_ErrorIRQ_Handler(void); - -#endif /* I2C_IE_H */ - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c index 04cf7be5..6dca26be 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_i2c.c @@ -1,37 +1,37 @@ /*! - \file gd32vf103_i2c.c - \brief I2C driver + \file gd32vf103_i2c.c + \brief I2C driver - \version 2019-06-05, V1.0.0, firmware for GD32VF103 - \version 2019-09-18, V1.0.1, firmware for GD32VF103 -*/ + \version 2019-06-05, V1.0.0, firmware for GD32VF103 + \version 2019-09-18, V1.0.1, firmware for GD32VF103 + */ /* - Copyright (c) 2019, GigaDevice Semiconductor Inc. + Copyright (c) 2019, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + OF SUCH DAMAGE. + */ #include "gd32vf103_i2c.h" @@ -46,685 +46,655 @@ OF SUCH DAMAGE. #define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ /*! - \brief reset I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_deinit(uint32_t i2c_periph) -{ - switch (i2c_periph) { - case I2C0: - /* reset I2C0 */ - rcu_periph_reset_enable(RCU_I2C0RST); - rcu_periph_reset_disable(RCU_I2C0RST); - break; - case I2C1: - /* reset I2C1 */ - rcu_periph_reset_enable(RCU_I2C1RST); - rcu_periph_reset_disable(RCU_I2C1RST); - break; - default: - break; - } +void i2c_deinit(uint32_t i2c_periph) { + switch (i2c_periph) { + case I2C0: + /* reset I2C0 */ + rcu_periph_reset_enable(RCU_I2C0RST); + rcu_periph_reset_disable(RCU_I2C0RST); + break; + case I2C1: + /* reset I2C1 */ + rcu_periph_reset_enable(RCU_I2C1RST); + rcu_periph_reset_disable(RCU_I2C1RST); + break; + default: + break; + } } /*! - \brief configure I2C clock - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) - and fast mode plus (up to 1MHz) - \param[in] dutycyc: duty cycle in fast mode or fast mode plus - only one parameter can be selected which is shown as below: - \arg I2C_DTCY_2: T_low/T_high=2 - \arg I2C_DTCY_16_9: T_low/T_high=16/9 - \param[out] none - \retval none + \brief configure I2C clock + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) + and fast mode plus (up to 1MHz) + \param[in] dutycyc: duty cycle in fast mode or fast mode plus + only one parameter can be selected which is shown as below: + \arg I2C_DTCY_2: T_low/T_high=2 + \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \param[out] none + \retval none */ -void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) -{ - uint32_t pclk1, clkc, freq, risetime; - uint32_t temp; - - pclk1 = rcu_clock_freq_get(CK_APB1); - /* I2C peripheral clock frequency */ - freq = (uint32_t) (pclk1 / 1000000U); - if (freq >= I2CCLK_MAX) { - freq = I2CCLK_MAX; - } - temp = I2C_CTL1(i2c_periph); - temp &= ~I2C_CTL1_I2CCLK; - temp |= freq; - - I2C_CTL1(i2c_periph) = temp; - - if (100000U >= clkspeed) { - /* the maximum SCL rise time is 1000ns in standard mode */ - risetime = (uint32_t) ((pclk1 / 1000000U) + 1U); - if (risetime >= I2CCLK_MAX) { - I2C_RT(i2c_periph) = I2CCLK_MAX; - } else if (risetime <= I2CCLK_MIN) { - I2C_RT(i2c_periph) = I2CCLK_MIN; - } else { - I2C_RT(i2c_periph) = risetime; - } - clkc = (uint32_t) (pclk1 / (clkspeed * 2U)); - if (clkc < 0x04U) { - /* the CLKC in standard mode minmum value is 4 */ - clkc = 0x04U; - } - I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) { + uint32_t pclk1, clkc, freq, risetime; + uint32_t temp; - } else if (400000U >= clkspeed) { - /* the maximum SCL rise time is 300ns in fast mode */ - I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U)/(uint32_t)1000U)+(uint32_t)1U); - if (I2C_DTCY_2 == dutycyc){ - /* I2C duty cycle is 2 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); - I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; - } else { - /* I2C duty cycle is 16/9 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; - } - if (0U == (clkc & I2C_CKCFG_CLKC)) { - /* the CLKC in fast mode minmum value is 1 */ - clkc |= 0x0001U; - } - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; - I2C_CKCFG(i2c_periph) |= clkc; - } else { - /* fast mode plus, the maximum SCL rise time is 120ns */ - I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U)+(uint32_t) 1U); - if (I2C_DTCY_2 == dutycyc) { - /* I2C duty cycle is 2 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); - I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; - } else { - /* I2C duty cycle is 16/9 */ - clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; - } - /* enable fast mode */ - I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; - I2C_CKCFG(i2c_periph) |= clkc; - /* enable I2C fast mode plus */ - I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN; - } + pclk1 = rcu_clock_freq_get(CK_APB1); + /* I2C peripheral clock frequency */ + freq = (uint32_t) (pclk1 / 1000000U); + if (freq >= I2CCLK_MAX) { + freq = I2CCLK_MAX; + } + temp = I2C_CTL1(i2c_periph); + temp &= ~I2C_CTL1_I2CCLK; + temp |= freq; + + I2C_CTL1(i2c_periph) = temp; + + if (100000U >= clkspeed) { + /* the maximum SCL rise time is 1000ns in standard mode */ + risetime = (uint32_t) ((pclk1 / 1000000U) + 1U); + if (risetime >= I2CCLK_MAX) { + I2C_RT(i2c_periph) = I2CCLK_MAX; + } else if (risetime <= I2CCLK_MIN) { + I2C_RT(i2c_periph) = I2CCLK_MIN; + } else { + I2C_RT(i2c_periph) = risetime; + } + clkc = (uint32_t) (pclk1 / (clkspeed * 2U)); + if (clkc < 0x04U) { + /* the CLKC in standard mode minmum value is 4 */ + clkc = 0x04U; + } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); + + } else if (400000U >= clkspeed) { + /* the maximum SCL rise time is 300ns in fast mode */ + I2C_RT(i2c_periph) = (uint32_t) (((freq * (uint32_t) 300U) / (uint32_t) 1000U) + (uint32_t) 1U); + if (I2C_DTCY_2 == dutycyc) { + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + if (0U == (clkc & I2C_CKCFG_CLKC)) { + /* the CLKC in fast mode minmum value is 1 */ + clkc |= 0x0001U; + } + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + } else { + /* fast mode plus, the maximum SCL rise time is 120ns */ + I2C_RT (i2c_periph) = (uint32_t) (((freq * (uint32_t) 120U) / (uint32_t) 1000U) + (uint32_t) 1U); + if (I2C_DTCY_2 == dutycyc) { + /* I2C duty cycle is 2 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 3U)); + I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; + } else { + /* I2C duty cycle is 16/9 */ + clkc = (uint32_t) (pclk1 / (clkspeed * 25U)); + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; + } + /* enable fast mode */ + I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; + I2C_CKCFG(i2c_periph) |= clkc; + /* enable I2C fast mode plus */ + I2C_FMPCFG(i2c_periph) |= I2C_FMPCFG_FMPEN; + } } /*! - \brief configure I2C address - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] mode: - only one parameter can be selected which is shown as below: - \arg I2C_I2CMODE_ENABLE: I2C mode - \arg I2C_SMBUSMODE_ENABLE: SMBus mode - \param[in] addformat: 7bits or 10bits - only one parameter can be selected which is shown as below: - \arg I2C_ADDFORMAT_7BITS: 7bits - \arg I2C_ADDFORMAT_10BITS: 10bits - \param[in] addr: I2C address - \param[out] none - \retval none + \brief configure I2C address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] mode: + only one parameter can be selected which is shown as below: + \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_SMBUSMODE_ENABLE: SMBus mode + \param[in] addformat: 7bits or 10bits + only one parameter can be selected which is shown as below: + \arg I2C_ADDFORMAT_7BITS: 7bits + \arg I2C_ADDFORMAT_10BITS: 10bits + \param[in] addr: I2C address + \param[out] none + \retval none */ -void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode,uint32_t addformat, uint32_t addr) -{ - /* SMBus/I2C mode selected */ - uint32_t ctl = 0U; +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) { + /* SMBus/I2C mode selected */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SMBEN); - ctl |= mode; - I2C_CTL0(i2c_periph) = ctl; - /* configure address */ - addr = addr & I2C_ADDRESS_MASK; - I2C_SADDR0(i2c_periph) = (addformat | addr); + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SMBEN); + ctl |= mode; + I2C_CTL0(i2c_periph) = ctl; + /* configure address */ + addr = addr & I2C_ADDRESS_MASK; + I2C_SADDR0(i2c_periph) = (addformat | addr); } /*! - \brief SMBus type selection - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] type: - only one parameter can be selected which is shown as below: - \arg I2C_SMBUS_DEVICE: device - \arg I2C_SMBUS_HOST: host - \param[out] none - \retval none + \brief SMBus type selection + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] type: + only one parameter can be selected which is shown as below: + \arg I2C_SMBUS_DEVICE: device + \arg I2C_SMBUS_HOST: host + \param[out] none + \retval none */ -void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) -{ - if (I2C_SMBUS_HOST == type) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); - } +void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) { + if (I2C_SMBUS_HOST == type) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); + } } /*! - \brief whether or not to send an ACK - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] ack: - only one parameter can be selected which is shown as below: - \arg I2C_ACK_ENABLE: ACK will be sent - \arg I2C_ACK_DISABLE: ACK will not be sent - \param[out] none - \retval none + \brief whether or not to send an ACK + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] ack: + only one parameter can be selected which is shown as below: + \arg I2C_ACK_ENABLE: ACK will be sent + \arg I2C_ACK_DISABLE: ACK will not be sent + \param[out] none + \retval none */ -void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) -{ - if (I2C_ACK_ENABLE == ack) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); - } +void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) { + if (I2C_ACK_ENABLE == ack) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); + } } /*! - \brief configure I2C POAP position - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pos: - only one parameter can be selected which is shown as below: - \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current - \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte - \param[out] none - \retval none + \brief configure I2C POAP position + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pos: + only one parameter can be selected which is shown as below: + \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current + \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \param[out] none + \retval none */ -void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) -{ - /* configure I2C POAP position */ - if (I2C_ACKPOS_NEXT == pos) { - I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; - } else { - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); - } +void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) { + /* configure I2C POAP position */ + if (I2C_ACKPOS_NEXT == pos) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; + } else { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); + } } /*! - \brief master sends slave address - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] addr: slave address - \param[in] trandirection: transmitter or receiver - only one parameter can be selected which is shown as below: - \arg I2C_TRANSMITTER: transmitter - \arg I2C_RECEIVER: receiver - \param[out] none - \retval none + \brief master sends slave address + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: slave address + \param[in] trandirection: transmitter or receiver + only one parameter can be selected which is shown as below: + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver + \param[out] none + \retval none */ -void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr,uint32_t trandirection) -{ - /* master is a transmitter or a receiver */ - if (I2C_TRANSMITTER == trandirection) { - addr = addr & I2C_TRANSMITTER; - } else { - addr = addr | I2C_RECEIVER; - } - /* send slave address */ - I2C_DATA(i2c_periph) = addr; +void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) { + /* master is a transmitter or a receiver */ + if (I2C_TRANSMITTER == trandirection) { + addr = addr & I2C_TRANSMITTER; + } else { + addr = addr | I2C_RECEIVER; + } + /* send slave address */ + I2C_DATA(i2c_periph) = addr; } /*! - \brief enable dual-address mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] addr: the second address in dual-address mode - \param[out] none - \retval none -*/ -void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) -{ - /* configure address */ - addr = addr & I2C_ADDRESS2_MASK; - I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); -} - -/*! - \brief disable dual-address mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none -*/ -void i2c_dualaddr_disable(uint32_t i2c_periph) -{ - I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); -} - -/*! - \brief enable I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief enable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] addr: the second address in dual-address mode + \param[out] none + \retval none */ -void i2c_enable(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; +void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) { + /* configure address */ + addr = addr & I2C_ADDRESS2_MASK; + I2C_SADDR1(i2c_periph) = (I2C_SADDR1_DUADEN | addr); } /*! - \brief disable I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief disable dual-address mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_disable(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); +void i2c_dualaddr_disable(uint32_t i2c_periph) { + I2C_SADDR1(i2c_periph) &= ~(I2C_SADDR1_DUADEN); } /*! - \brief generate a START condition on I2C bus - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief enable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_start_on_bus(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_START; +void i2c_enable(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_I2CEN; } /*! - \brief generate a STOP condition on I2C bus - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval none + \brief disable I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_stop_on_bus(uint32_t i2c_periph) -{ - I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; +void i2c_disable(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_I2CEN); } /*! - \brief I2C transmit data function - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] data: data of transmission - \param[out] none - \retval none + \brief generate a START condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) -{ - I2C_DATA(i2c_periph) = DATA_TRANS(data); +void i2c_start_on_bus(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_START; } /*! - \brief I2C receive data function - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval data of received + \brief generate a STOP condition on I2C bus + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval none */ -uint8_t i2c_data_receive(uint32_t i2c_periph) -{ - return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph)); +void i2c_stop_on_bus(uint32_t i2c_periph) { + I2C_CTL0(i2c_periph) |= I2C_CTL0_STOP; } /*! - \brief enable I2C DMA mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] dmastate: - only one parameter can be selected which is shown as below: - \arg I2C_DMA_ON: DMA mode enable - \arg I2C_DMA_OFF: DMA mode disable - \param[out] none - \retval none + \brief I2C transmit data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] data: data of transmission + \param[out] none + \retval none */ -void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) -{ - /* configure I2C DMA function */ - uint32_t ctl = 0U; - - ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMAON); - ctl |= dmastate; - I2C_CTL1(i2c_periph) = ctl; +void i2c_data_transmit(uint32_t i2c_periph, uint8_t data) { + I2C_DATA(i2c_periph) = DATA_TRANS(data); } /*! - \brief configure whether next DMA EOT is DMA last transfer or not - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] dmalast: - only one parameter can be selected which is shown as below: - \arg I2C_DMALST_ON: next DMA EOT is the last transfer - \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer - \param[out] none - \retval none + \brief I2C receive data function + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval data of received */ -void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) -{ - /* configure DMA last transfer */ - uint32_t ctl = 0U; - - ctl = I2C_CTL1(i2c_periph); - ctl &= ~(I2C_CTL1_DMALST); - ctl |= dmalast; - I2C_CTL1(i2c_periph) = ctl; +uint8_t i2c_data_receive(uint32_t i2c_periph) { + return (uint8_t) DATA_RECV(I2C_DATA(i2c_periph)); } /*! - \brief whether to stretch SCL low when data is not ready in slave mode - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] stretchpara: - only one parameter can be selected which is shown as below: - \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled - \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled - \param[out] none - \retval none + \brief enable I2C DMA mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmastate: + only one parameter can be selected which is shown as below: + \arg I2C_DMA_ON: DMA mode enable + \arg I2C_DMA_OFF: DMA mode disable + \param[out] none + \retval none */ -void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) -{ - /* configure I2C SCL strerching enable or disable */ - uint32_t ctl = 0U; +void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) { + /* configure I2C DMA function */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SS); - ctl |= stretchpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMAON); + ctl |= dmastate; + I2C_CTL1(i2c_periph) = ctl; } /*! - \brief whether or not to response to a general call - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] gcallpara: - only one parameter can be selected which is shown as below: - \arg I2C_GCEN_ENABLE: slave will response to a general call - \arg I2C_GCEN_DISABLE: slave will not response to a general call - \param[out] none - \retval none + \brief configure whether next DMA EOT is DMA last transfer or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] dmalast: + only one parameter can be selected which is shown as below: + \arg I2C_DMALST_ON: next DMA EOT is the last transfer + \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer + \param[out] none + \retval none */ -void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) -{ - /* configure slave response to a general call enable or disable */ - uint32_t ctl = 0U; +void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) { + /* configure DMA last transfer */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_GCEN); - ctl |= gcallpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL1(i2c_periph); + ctl &= ~(I2C_CTL1_DMALST); + ctl |= dmalast; + I2C_CTL1(i2c_periph) = ctl; } /*! - \brief software reset I2C - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] sreset: - only one parameter can be selected which is shown as below: - \arg I2C_SRESET_SET: I2C is under reset - \arg I2C_SRESET_RESET: I2C is not under reset - \param[out] none - \retval none + \brief whether to stretch SCL low when data is not ready in slave mode + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] stretchpara: + only one parameter can be selected which is shown as below: + \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled + \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \param[out] none + \retval none */ -void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) -{ - /* modify CTL0 and configure software reset I2C state */ - uint32_t ctl = 0U; +void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) { + /* configure I2C SCL strerching enable or disable */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SRESET); - ctl |= sreset; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SS); + ctl |= stretchpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C PEC calculation on or off - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pecpara: - only one parameter can be selected which is shown as below: - \arg I2C_PEC_ENABLE: PEC calculation on - \arg I2C_PEC_DISABLE: PEC calculation off - \param[out] none - \retval none + \brief whether or not to response to a general call + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] gcallpara: + only one parameter can be selected which is shown as below: + \arg I2C_GCEN_ENABLE: slave will response to a general call + \arg I2C_GCEN_DISABLE: slave will not response to a general call + \param[out] none + \retval none */ -void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) -{ - /* on/off PEC calculation */ - uint32_t ctl = 0U; +void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) { + /* configure slave response to a general call enable or disable */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECEN); - ctl |= pecstate; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_GCEN); + ctl |= gcallpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C whether to transfer PEC value - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] pecpara: - only one parameter can be selected which is shown as below: - \arg I2C_PECTRANS_ENABLE: transfer PEC - \arg I2C_PECTRANS_DISABLE: not transfer PEC - \param[out] none - \retval none + \brief software reset I2C + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] sreset: + only one parameter can be selected which is shown as below: + \arg I2C_SRESET_SET: I2C is under reset + \arg I2C_SRESET_RESET: I2C is not under reset + \param[out] none + \retval none */ -void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) -{ - /* whether to transfer PEC */ - uint32_t ctl = 0U; +void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) { + /* modify CTL0 and configure software reset I2C state */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_PECTRANS); - ctl |= pecpara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SRESET); + ctl |= sreset; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief get packet error checking value - \param[in] i2c_periph: I2Cx(x=0,1) - \param[out] none - \retval PEC value + \brief I2C PEC calculation on or off + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off + \param[out] none + \retval none */ -uint8_t i2c_pec_value_get(uint32_t i2c_periph) -{ - return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV)>> STAT1_PECV_OFFSET); +void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate) { + /* on/off PEC calculation */ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECEN); + ctl |= pecstate; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief I2C issue alert through SMBA pin - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] smbuspara: - only one parameter can be selected which is shown as below: - \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin - \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin - \param[out] none - \retval none + \brief I2C whether to transfer PEC value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] pecpara: + only one parameter can be selected which is shown as below: + \arg I2C_PECTRANS_ENABLE: transfer PEC + \arg I2C_PECTRANS_DISABLE: not transfer PEC + \param[out] none + \retval none */ -void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) -{ - /* issue alert through SMBA pin configure*/ - uint32_t ctl = 0U; +void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara) { + /* whether to transfer PEC */ + uint32_t ctl = 0U; - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SALT); - ctl |= smbuspara; - I2C_CTL0(i2c_periph) = ctl; + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_PECTRANS); + ctl |= pecpara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief enable or disable I2C ARP protocol in SMBus switch - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] arpstate: - only one parameter can be selected which is shown as below: - \arg I2C_ARP_ENABLE: enable ARP - \arg I2C_ARP_DISABLE: disable ARP - \param[out] none - \retval none + \brief get packet error checking value + \param[in] i2c_periph: I2Cx(x=0,1) + \param[out] none + \retval PEC value */ -void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) -{ - /* enable or disable I2C ARP protocol*/ - uint32_t ctl = 0U; - - ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_ARPEN); - ctl |= arpstate; - I2C_CTL0(i2c_periph) = ctl; +uint8_t i2c_pec_value_get(uint32_t i2c_periph) { + return (uint8_t) ((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET); } /*! - \brief check I2C flag is set or not - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] flag: I2C flags, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SBSEND: start condition send out - \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode - \arg I2C_FLAG_BTC: byte transmission finishes - \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode - \arg I2C_FLAG_STPDET: stop condition detected in slave mode - \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving - \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting - \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus - \arg I2C_FLAG_LOSTARB: arbitration lost in master mode - \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode - \arg I2C_FLAG_PECERR: PEC error when receiving data - \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode - \arg I2C_FLAG_SMBALT: SMBus alert status - \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode - \arg I2C_FLAG_I2CBSY: busy flag - \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver - \arg I2C_FLAG_RXGC: general call address (00h) received - \arg I2C_FLAG_DEFSMB: default address of SMBus device - \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode - \arg I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode - \param[out] none - \retval FlagStatus: SET or RESET + \brief I2C issue alert through SMBA pin + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] smbuspara: + only one parameter can be selected which is shown as below: + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \param[out] none + \retval none */ -FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) -{ - if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { - return SET; - } else { - return RESET; - } +void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) { + /* issue alert through SMBA pin configure*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_SALT); + ctl |= smbuspara; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief clear I2C flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] flag: I2C flags, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SMBALT: SMBus Alert status - \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode - \arg I2C_FLAG_PECERR: PEC error when receiving data - \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode - \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_LOSTARB: arbitration lost in master mode - \arg I2C_FLAG_BERR: a bus error - \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 - \param[out] none - \retval none + \brief enable or disable I2C ARP protocol in SMBus switch + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] arpstate: + only one parameter can be selected which is shown as below: + \arg I2C_ARP_ENABLE: enable ARP + \arg I2C_ARP_DISABLE: disable ARP + \param[out] none + \retval none */ -void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) -{ - uint32_t temp; - if (I2C_FLAG_ADDSEND == flag) { - /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ - temp = I2C_STAT0(i2c_periph); - temp = I2C_STAT1(i2c_periph); - } else { - I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); - } +void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate) { + /* enable or disable I2C ARP protocol*/ + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ARPEN); + ctl |= arpstate; + I2C_CTL0(i2c_periph) = ctl; } /*! - \brief enable I2C interrupt - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable - \param[out] none - \retval none + \brief check I2C flag is set or not + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode + \arg I2C_FLAG_BTC: byte transmission finishes + \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode + \arg I2C_FLAG_STPDET: stop condition detected in slave mode + \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_SMBALT: SMBus alert status + \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode + \arg I2C_FLAG_I2CBSY: busy flag + \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_RXGC: general call address (00h) received + \arg I2C_FLAG_DEFSMB: default address of SMBus device + \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode + \arg I2C_FLAG_DUMODF: dual flag in slave mode indicating which address is matched in dual-address mode + \param[out] none + \retval FlagStatus: SET or RESET */ -void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) -{ - I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); +FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) { + if (RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { + return SET; + } else { + return RESET; + } } /*! - \brief disable I2C interrupt - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable - \param[out] none - \retval none + \brief clear I2C flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] flag: I2C flags, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode + \arg I2C_FLAG_PECERR: PEC error when receiving data + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_AERR: acknowledge error + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error + \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \param[out] none + \retval none */ -void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) -{ - I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) { + uint32_t temp; + if (I2C_FLAG_ADDSEND == flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); + } } /*! - \brief check I2C interrupt flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag - \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag - \arg I2C_INT_FLAG_BTC: byte transmission finishes - \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag - \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag - \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag - \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag - \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag - \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag - \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag - \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag - \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag - \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET + \brief enable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none */ -FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) -{ - uint32_t intenable = 0U, flagstatus = 0U, bufie; - - /* check BUFIE */ - bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE; - - /* get the interrupt enable bit status */ - intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); - /* get the corresponding flag bit status */ - flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag)& BIT(I2C_BIT_POS2(int_flag))); - - if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { - if (intenable && bufie) { - intenable = 1U; - } else { - intenable = 0U; - } - } - if ((0U != flagstatus) && (0U != intenable)) { - return SET; - } else { - return RESET; - } +void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { + I2C_REG_VAL(i2c_periph, interrupt) |= BIT(I2C_BIT_POS(interrupt)); } /*! - \brief clear I2C interrupt flag - \param[in] i2c_periph: I2Cx(x=0,1) - \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum - only one parameter can be selected which is shown as below: - \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag - \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag - \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag - \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag - \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag - \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag - \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag - \param[out] none - \retval none + \brief disable I2C interrupt + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_ERR: error interrupt enable + \arg I2C_INT_EV: event interrupt enable + \arg I2C_INT_BUF: buffer interrupt enable + \param[out] none + \retval none */ -void i2c_interrupt_flag_clear(uint32_t i2c_periph,i2c_interrupt_flag_enum int_flag) -{ - uint32_t temp; - if (I2C_INT_FLAG_ADDSEND == int_flag) { - /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ - temp = I2C_STAT0(i2c_periph); - temp = I2C_STAT1(i2c_periph); - } else { - I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); - } +void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) { + I2C_REG_VAL(i2c_periph, interrupt) &= ~BIT(I2C_BIT_POS(interrupt)); +} + +/*! + \brief check I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag + \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag + \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET + */ +FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { + uint32_t intenable = 0U, flagstatus = 0U, bufie; + + /* check BUFIE */ + bufie = I2C_CTL1(i2c_periph) & I2C_CTL1_BUFIE; + + /* get the interrupt enable bit status */ + intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); + /* get the corresponding flag bit status */ + volatile uint32_t reg = I2C_REG_VAL2(i2c_periph, int_flag); + flagstatus = (reg & BIT(I2C_BIT_POS2(int_flag))); + + if ((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { + if (intenable && bufie) { + intenable = 1U; + } else { + intenable = 0U; + } + } + if ((0U != flagstatus) && (0U != intenable)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear I2C interrupt flag + \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + only one parameter can be selected which is shown as below: + \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag + \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag + \arg I2C_INT_FLAG_LOSTARB: arbitration lost in master mode interrupt flag + \arg I2C_INT_FLAG_AERR: acknowledge error interrupt flag + \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag + \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag + \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \param[out] none + \retval none + */ +void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { + uint32_t temp; + if (I2C_INT_FLAG_ADDSEND == int_flag) { + /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ + temp = I2C_STAT0(i2c_periph); + temp = I2C_STAT1(i2c_periph); + } else { + I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); + } } diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp index fae5882a..2d1a89b8 100644 --- a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -134,12 +134,19 @@ void fusb_send_hardrst() { } void fusb_setup() { - + if (!FRToSI2C::probe(FUSB302B_ADDR)) { + return; + } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); osDelay(2); + uint8_t tries = 0; while (!fusb_read_id()) { osDelay(10); + tries++; + if (tries > 5) { + return; //Welp :( + } } /* Turn on all power */ diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp index b15161b3..8abe543f 100644 --- a/workspace/TS100/Core/Drivers/BMA223.cpp +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -8,7 +8,7 @@ #include #include "BMA223_defines.h" #include -#define BMA223_ADDRESS 0b00110000 +#define BMA223_ADDRESS 0x18<<1 bool BMA223::detect() { return FRToSI2C::probe(BMA223_ADDRESS); @@ -16,16 +16,17 @@ bool BMA223::detect() { static const FRToSI2C::I2C_REG i2c_registers[] = { // // - { BMA223_PMU_RANGE, 0b0011, 0 }, //2G range - { BMA223_PMU_BW, 0b1101, 0 }, //250Hz filter - { BMA223_PMU_LPW, 0x00, 0 }, //Full power - { BMA223_ACCD_HBW, 0b01000000, 0 }, //filtered data out - { BMA223_INT_OUT_CTRL, 0b1111, 0 }, //interrupt active high and OD to get it hi-z - { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en + { BMA223_PMU_RANGE, 0b00000011, 0 }, //2G range + { BMA223_PMU_BW, 0b00001101, 0 }, //250Hz filter + { BMA223_PMU_LPW, 0b00000000, 0 }, //Full power + { BMA223_ACCD_HBW, 0b00000000, 0 }, //filtered data out + { BMA223_INT_OUT_CTRL, 0b00001010, 0 }, //interrupt active low and OD to get it hi-z + { BMA223_INT_RST_LATCH, 0b10000000, 0 }, //interrupt active low and OD to get it hi-z +// { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en // }; -void BMA223::initalize() { +bool BMA223::initalize() { //Setup acceleration readings //2G range //bandwidth = 250Hz @@ -35,19 +36,22 @@ void BMA223::initalize() { // Hysteresis is set to ~ 16 counts //Theta blocking is set to 0b10 - FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); + return FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) { //The BMA is odd in that its output data width is only 8 bits //And yet there are MSB and LSB registers _sigh_. - uint8_t sensorData[6]; + uint8_t sensorData[6] = { 0, 0, 0, 0, 0, 0 }; - FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6); + if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) { + x = 0xAAFF; + return; + } - x = sensorData[1] << 2; - y = sensorData[3] << 2; - z = sensorData[5] << 2; + x = sensorData[1] << 4; + y = sensorData[3] << 4; + z = sensorData[5] << 4; } diff --git a/workspace/TS100/Core/Drivers/BMA223.hpp b/workspace/TS100/Core/Drivers/BMA223.hpp index 5578d89a..06af2436 100644 --- a/workspace/TS100/Core/Drivers/BMA223.hpp +++ b/workspace/TS100/Core/Drivers/BMA223.hpp @@ -15,7 +15,7 @@ class BMA223 { public: static bool detect(); - static void initalize(); + static bool initalize(); //1 = rh, 2,=lh, 8=flat static Orientation getOrientation() { #ifdef ACCEL_ORI_FLIP diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.cpp b/workspace/TS100/Core/Drivers/LIS2DH12.cpp index 89cdd9a6..02aad5b6 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.cpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.cpp @@ -24,8 +24,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { LIS_CTRL_REG1, 0x17, 0 }, / { LIS_INT1_THS, 0x28, 0 }, // { LIS_INT1_DURATION, 64, 0 } }; -void LIS2DH12::initalize() { - FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); +bool LIS2DH12::initalize() { + return FRToSI2C::writeRegistersBulk(LIS2DH_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } void LIS2DH12::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) { diff --git a/workspace/TS100/Core/Drivers/LIS2DH12.hpp b/workspace/TS100/Core/Drivers/LIS2DH12.hpp index 8586ec21..e4cccd48 100644 --- a/workspace/TS100/Core/Drivers/LIS2DH12.hpp +++ b/workspace/TS100/Core/Drivers/LIS2DH12.hpp @@ -14,7 +14,7 @@ class LIS2DH12 { public: static bool detect(); - static void initalize(); + static bool initalize(); //1 = rh, 2,=lh, 8=flat static Orientation getOrientation() { #ifdef LIS_ORI_FLIP diff --git a/workspace/TS100/Core/Drivers/MMA8652FC.cpp b/workspace/TS100/Core/Drivers/MMA8652FC.cpp index 83e922e1..fa8b91fe 100644 --- a/workspace/TS100/Core/Drivers/MMA8652FC.cpp +++ b/workspace/TS100/Core/Drivers/MMA8652FC.cpp @@ -26,8 +26,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { { CTRL_REG2, 0, 0 }, //Nor { CTRL_REG1, 0x19, 0 } // ODR=12 Hz, Active mode }; -void MMA8652FC::initalize() { - FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); +bool MMA8652FC::initalize() { + return FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); } diff --git a/workspace/TS100/Core/Drivers/MMA8652FC.hpp b/workspace/TS100/Core/Drivers/MMA8652FC.hpp index ec160ab5..9b5f44d1 100644 --- a/workspace/TS100/Core/Drivers/MMA8652FC.hpp +++ b/workspace/TS100/Core/Drivers/MMA8652FC.hpp @@ -17,7 +17,7 @@ public: //Returns true if this accelerometer is detected static bool detect(); //Init any internal state - static void initalize(); + static bool initalize(); static Orientation getOrientation(); // Reads the I2C register and returns the orientation (true == left) static void getAxisReadings(int16_t &x, int16_t &y, int16_t &z); diff --git a/workspace/TS100/Core/Src/main.cpp b/workspace/TS100/Core/Src/main.cpp index 9c9da2dc..e9e3d62f 100644 --- a/workspace/TS100/Core/Src/main.cpp +++ b/workspace/TS100/Core/Src/main.cpp @@ -25,7 +25,7 @@ static const size_t PIDTaskStackSize = 512 / 4; uint32_t PIDTaskBuffer[PIDTaskStackSize]; osStaticThreadDef_t PIDTaskControlBlock; osThreadId MOVTaskHandle; -static const size_t MOVTaskStackSize = 512 / 4; +static const size_t MOVTaskStackSize = 1024 / 4; uint32_t MOVTaskBuffer[MOVTaskStackSize]; osStaticThreadDef_t MOVTaskControlBlock; diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index e04340a9..e24663fe 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -603,7 +603,9 @@ uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { OLED::initialize(); // start up the LCD - +// for (;;) { +// osDelay(2000); +// } uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 01a36b2e..7c09d17b 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -27,21 +27,27 @@ void detectAccelerometerVersion() { #ifdef ACCEL_MMA if (MMA8652FC::detect()) { PCBVersion = 1; - MMA8652FC::initalize(); // this sets up the I2C registers + if(!MMA8652FC::initalize()) { + PCBVersion = 99; + } } else #endif #ifdef ACCEL_LIS if (LIS2DH12::detect()) { PCBVersion = 2; // Setup the ST Accelerometer - LIS2DH12::initalize();// startup the accelerometer + if(!LIS2DH12::initalize()) { + PCBVersion = 99; + } } else #endif #ifdef ACCEL_BMA if (BMA223::detect()) { PCBVersion = 3; // Setup the ST Accelerometer - BMA223::initalize(); // startup the accelerometer + if (!BMA223::initalize()) { + PCBVersion = 99; + } } else #endif { @@ -76,7 +82,7 @@ inline void readAccelerometer(int16_t& tx, int16_t& ty, int16_t& tz, Orientation } } void startMOVTask(void const *argument __unused) { - + osDelay(10);//Make oled init happen first postRToSInit(); OLED::setRotation(systemSettings.OrientationMode & 1); detectAccelerometerVersion(); @@ -93,6 +99,17 @@ void startMOVTask(void const *argument __unused) { if (systemSettings.sensitivity > 9) systemSettings.sensitivity = 9; Orientation rotation = ORIENTATION_FLAT; +// OLED::setFont(1); +// for (;;) { +// OLED::clearScreen(); +// OLED::setCursor(0, 0); +// readAccelerometer(tx, ty, tz, rotation); +// OLED::printNumber(tx, 5, 0); +// OLED::setCursor(0, 8); +// OLED::printNumber(xTaskGetTickCount() / 10, 5, 1); +// OLED::refresh(); +// osDelay(50); +// } for (;;) { int32_t threshold = 1500 + (9 * 200); threshold -= systemSettings.sensitivity * 200; // 200 is the step size From 088516acea76b22dda13fd0000c66149c0cb8bca Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 24 Sep 2020 18:06:20 +1000 Subject: [PATCH 21/72] Working auto orientation --- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 56 ++++++++++--------- workspace/TS100/Core/Drivers/BMA223.cpp | 5 +- workspace/TS100/Core/Drivers/BMA223.hpp | 31 +++++----- workspace/TS100/Core/Drivers/BMA223_defines.h | 1 + 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index 60ef5f8b..1049fc18 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -107,13 +107,17 @@ void I2C0_EV_IRQHandler(void) { } break; case I2C_TRANSMIT_DATA: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - /* the master sends a data byte */ - i2c_data_transmit(I2C0, *i2c_write++); - i2c_nbytes--; - if (RESET == i2c_nbytes) { - i2c_write_process = I2C_STOP; + if (i2c_nbytes) { + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { + /* the master sends a data byte */ + i2c_data_transmit(I2C0, *i2c_write++); + i2c_nbytes--; + if (0 == i2c_nbytes) { + i2c_write_process = I2C_STOP; + } } + } else { + i2c_write_process = I2C_STOP; } break; case I2C_STOP: @@ -180,25 +184,27 @@ void I2C0_EV_IRQHandler(void) { break; case I2C_TRANSMIT_DATA: if (i2c_nbytes > 0) { - /* read a byte from the EEPROM */ - if (i2c_nbytes == 2) { - /* wait until BTC bit is set */ - i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); - /* clear the ACKEN before the ADDSEND is cleared */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } - *i2c_read = i2c_data_receive(I2C0); - i2c_read++; - i2c_nbytes--; - if (i2c_nbytes == 0) { - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_process_flag = RESET; - i2c_read_process = I2C_DONE; + if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) { + /* read a byte from the EEPROM */ + if (i2c_nbytes == 2) { + /* wait until BTC bit is set */ + i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); + /* clear the ACKEN before the ADDSEND is cleared */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + } + *i2c_read = i2c_data_receive(I2C0); + i2c_read++; + i2c_nbytes--; + if (i2c_nbytes == 0) { + /* the master sends a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* disable the I2C0 interrupt */ + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_process_flag = RESET; + i2c_read_process = I2C_DONE; + } } } else { i2c_read_process = I2C_STOP; diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp index 8abe543f..939b3d31 100644 --- a/workspace/TS100/Core/Drivers/BMA223.cpp +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -6,9 +6,7 @@ */ #include -#include "BMA223_defines.h" #include -#define BMA223_ADDRESS 0x18<<1 bool BMA223::detect() { return FRToSI2C::probe(BMA223_ADDRESS); @@ -22,7 +20,8 @@ static const FRToSI2C::I2C_REG i2c_registers[] = { // { BMA223_ACCD_HBW, 0b00000000, 0 }, //filtered data out { BMA223_INT_OUT_CTRL, 0b00001010, 0 }, //interrupt active low and OD to get it hi-z { BMA223_INT_RST_LATCH, 0b10000000, 0 }, //interrupt active low and OD to get it hi-z -// { BMA223_OFC_CTRL, 0b00000111, 0 }, //High pass en + { BMA223_INT_EN_0, 0b01000000, 0 }, //Enable orientation + { BMA223_INT_A, 0b00100111, 0 }, //Setup orientation detection // }; diff --git a/workspace/TS100/Core/Drivers/BMA223.hpp b/workspace/TS100/Core/Drivers/BMA223.hpp index 06af2436..85fa8576 100644 --- a/workspace/TS100/Core/Drivers/BMA223.hpp +++ b/workspace/TS100/Core/Drivers/BMA223.hpp @@ -8,9 +8,8 @@ #ifndef CORE_DRIVERS_BMA223_HPP_ #define CORE_DRIVERS_BMA223_HPP_ #include "I2C_Wrapper.hpp" -#include "LIS2DH12_defines.hpp" #include "BSP.h" - +#include "BMA223_defines.h" class BMA223 { public: @@ -18,21 +17,19 @@ public: static bool initalize(); //1 = rh, 2,=lh, 8=flat static Orientation getOrientation() { -#ifdef ACCEL_ORI_FLIP - uint8_t val = (FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS, - LIS_INT2_SRC) >> 2); - if (val == 8) - val = 3; - else if (val == 1) - val = 1; - else if (val == 2) - val = 0; - else - val = 3; - return static_cast(val); -#else - return static_cast((FRToSI2C::I2C_RegisterRead(LIS2DH_I2C_ADDRESS,LIS_INT2_SRC) >> 2) - 1); -#endif + uint8_t val = FRToSI2C::I2C_RegisterRead(BMA223_ADDRESS, + BMA223_INT_STATUS_3); + val >>= 4; //we dont need high values + val &= 0b11; + if(val &0b10){ + return ORIENTATION_FLAT; + }else{ + return static_cast(!val); + } + //0 = rhs + //1 =lhs + //2 & 3 == ignore + } static void getAxisReadings(int16_t& x, int16_t& y, int16_t& z); diff --git a/workspace/TS100/Core/Drivers/BMA223_defines.h b/workspace/TS100/Core/Drivers/BMA223_defines.h index 12481300..c7322a56 100644 --- a/workspace/TS100/Core/Drivers/BMA223_defines.h +++ b/workspace/TS100/Core/Drivers/BMA223_defines.h @@ -8,6 +8,7 @@ #ifndef CORE_DRIVERS_BMA223_DEFINES_H_ #define CORE_DRIVERS_BMA223_DEFINES_H_ +#define BMA223_ADDRESS 0x18<<1 #define BMA223_BGW_CHIPID 0x00 #define BMA223_ACCD_X_LSB 0x02 #define BMA223_ACCD_X_MSB 0x03 From cd69dc1e4c4c5df33d091670baaf7986697af8d1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Thu, 24 Sep 2020 19:20:51 +1000 Subject: [PATCH 22/72] Save and restore settings --- workspace/TS100/Core/BSP/Pine64/flash.c | 36 ++++++++++++++++++---- workspace/TS100/Core/BSP/Pine64/logo.cpp | 5 ++- workspace/TS100/Core/Threads/GUIThread.cpp | 1 - 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/flash.c b/workspace/TS100/Core/BSP/Pine64/flash.c index f00e132b..46a18bcf 100644 --- a/workspace/TS100/Core/BSP/Pine64/flash.c +++ b/workspace/TS100/Core/BSP/Pine64/flash.c @@ -9,15 +9,39 @@ #include "BSP_Flash.h" #include "gd32vf103_libopt.h" #include "string.h" -/*Flash start OR'ed with the maximum amount of flash - 1024 bytes*/ -/*We use the last 1024 byte page*/ -#define FLASH_ADDR (0x8000000 | 0xFC00) +#define FMC_PAGE_SIZE ((uint16_t)0x400U) +//static uint16_t settings_page[FMC_PAGE_SIZE] __attribute__ ((section (".settings_page"))); +//Linker script doesnt want to play, so for now its hard coded +#define SETTINGS_START_PAGE (0x08000000 +(63*1024)) uint8_t flash_save_buffer(const uint8_t *buffer, const uint16_t length) { - //TODO - return 1; + + /* unlock the flash program/erase controller */ + fmc_unlock(); + + /* clear all pending flags */ + fmc_flag_clear(FMC_FLAG_END); + fmc_flag_clear(FMC_FLAG_WPERR); + fmc_flag_clear(FMC_FLAG_PGERR); + resetWatchdog(); + fmc_page_erase((uint32_t) SETTINGS_START_PAGE); + resetWatchdog(); + uint16_t *data = (uint16_t*) buffer; + for (uint8_t i = 0; i < (length / 2); i++) { + fmc_halfword_program((uint32_t) SETTINGS_START_PAGE + (i * 2), data[i]); + fmc_flag_clear(FMC_FLAG_END); + fmc_flag_clear(FMC_FLAG_WPERR); + fmc_flag_clear(FMC_FLAG_PGERR); + resetWatchdog(); + } + fmc_lock(); + return 1; } void flash_read_buffer(uint8_t *buffer, const uint16_t length) { + uint32_t* b = (uint32_t*) buffer; + uint32_t* b2 = (uint32_t*) SETTINGS_START_PAGE; + for (int i = 0; i < length / 4; i++) { + b[i] = b2[i]; + } - //TODO } diff --git a/workspace/TS100/Core/BSP/Pine64/logo.cpp b/workspace/TS100/Core/BSP/Pine64/logo.cpp index f71df93d..1001e712 100644 --- a/workspace/TS100/Core/BSP/Pine64/logo.cpp +++ b/workspace/TS100/Core/BSP/Pine64/logo.cpp @@ -9,14 +9,13 @@ #include "OLED.hpp" // Second last page of flash set aside for logo image. #define FLASH_LOGOADDR (0x8000000 | 0xF800) - +//TODO // Logo header signature. #define LOGO_HEADER_VALUE 0xF00DAA55 uint8_t showBootLogoIfavailable() { // Do not show logo data if signature is not found. - if (LOGO_HEADER_VALUE - != *(reinterpret_cast(FLASH_LOGOADDR))) { + if (LOGO_HEADER_VALUE != *(reinterpret_cast(FLASH_LOGOADDR))) { return 0; } diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index e24663fe..b06bb3e7 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -27,7 +27,6 @@ extern "C" { extern uint32_t currentTempTargetDegC; extern uint8_t accelInit; extern uint32_t lastMovementTime; -extern int16_t idealQCVoltage; extern osThreadId GUITaskHandle; extern osThreadId MOVTaskHandle; extern osThreadId PIDTaskHandle; From c9172f0f9b4034ca7a4ef3807654fc1f9004028a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Fri, 25 Sep 2020 18:50:41 +1000 Subject: [PATCH 23/72] Move to basic DMA I2C | handle poll FUSB better --- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 31 +- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 401 ++++++++++++++---- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 206 +-------- workspace/TS100/Core/BSP/Pine64/IRQ.h | 5 + workspace/TS100/Core/BSP/Pine64/Setup.c | 30 +- workspace/TS100/Core/BSP/Pine64/Setup.h | 1 + workspace/TS100/Core/BSP/Pine64/fusb302b.cpp | 9 +- .../TS100/Core/Drivers/FUSB302/fusb302b.h | 2 +- .../TS100/Core/Drivers/FUSB302/fusbpd.cpp | 11 +- 9 files changed, 375 insertions(+), 321 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index ac1c5e83..7ff579f6 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -78,16 +78,16 @@ void fusb_send_message(const union pd_msg *msg) { } /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP2, - FUSB_FIFO_TX_PACKSYM }; + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP2, + FUSB_FIFO_TX_PACKSYM}; static const uint8_t eop_seq[4] = { - FUSB_FIFO_TX_JAM_CRC, - FUSB_FIFO_TX_EOP, - FUSB_FIFO_TX_TXOFF, - FUSB_FIFO_TX_TXON }; + FUSB_FIFO_TX_JAM_CRC, + FUSB_FIFO_TX_EOP, + FUSB_FIFO_TX_TXOFF, + FUSB_FIFO_TX_TXON}; /* Take the I2C2 mutex now so there can't be a race condition on sop_seq */ /* Get the length of the message: a two-octet header plus NUMOBJ four-octet @@ -142,16 +142,16 @@ void fusb_send_hardrst() { I2CBB::unlock2(); } -void fusb_setup() { +bool fusb_setup() { if (!I2CBB::lock2()) { - return; + return false; } /* Fully reset the FUSB302B */ // fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); // osDelay(2); if (!fusb_read_id()) { - return; + return false; } /* Turn on all power */ @@ -170,7 +170,7 @@ void fusb_setup() { fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ fusb_write_byte( FUSB_CONTROL1, - FUSB_CONTROL1_RX_FLUSH); + FUSB_CONTROL1_RX_FLUSH); /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); @@ -200,6 +200,7 @@ void fusb_setup() { HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTI9_5_IRQn, 10, 0); HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); + return true; } void fusb_get_status(union fusb_status *status) { @@ -225,7 +226,7 @@ enum fusb_typec_current fusb_get_typec_current() { } /* Read the BC_LVL into a variable */ enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( - FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); + FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { I2CBB::unlock2(); } @@ -255,7 +256,7 @@ bool fusb_read_id() { uint8_t version = 0; fusb_read_buf(FUSB_DEVICE_ID, 1, &version); if (version == 0 || version == 0xFF) - return false; + return false; return true; } uint8_t fusb302_detect() { diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 57cd78c2..a43dcb76 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -10,7 +10,7 @@ #include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; -#define FLAG_TIMEOUT 1000 +#define I2C_TIME_OUT (uint16_t)(5000) void FRToSI2C::CpltCallback() { //TODO } @@ -31,46 +31,189 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_b i2c_interrupt_disable(I2C0, I2C_INT_ERR); i2c_interrupt_disable(I2C0, I2C_INT_BUF); i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); - /* wait until I2C bus is idle */ - uint8_t timeout = 0; - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { - timeout++; - osDelay(1); - if (timeout > 20) { - unlock(); - return false; - } - } - i2c_slave_address = DevAddress; - i2c_read = p_buffer; - i2c_read_dress = read_address; - i2c_nbytes = number_of_byte; - i2c_error_code = 0; - i2c_process_flag = 1; - i2c_write_process = I2C_SEND_ADDRESS_FIRST; - i2c_read_process = I2C_SEND_ADDRESS_FIRST; + dma_parameter_struct dma_init_struct; -// if (2 == number_of_byte) { -// i2c_ackpos_config(I2C0, I2C_ACKPOS_NEXT); -// } - /* enable the I2C0 interrupt */ - i2c_interrupt_enable(I2C0, I2C_INT_ERR); - i2c_interrupt_enable(I2C0, I2C_INT_EV); - i2c_interrupt_enable(I2C0, I2C_INT_BUF); - /* send a start condition to I2C bus */ - i2c_start_on_bus(I2C0); - while ((i2c_nbytes > 0)) { - osDelay(1); - if (i2c_error_code != 0) { - unlock(); - return false; + uint8_t state = I2C_START; + uint8_t in_rx_cycle = 0; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + if (0 == in_rx_cycle) { + /* disable I2C0 */ + i2c_disable(I2C0); + /* enable I2C0 */ + i2c_enable(I2C0); + + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the start signal */ + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + } else { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + if (RESET == in_rx_cycle) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + if (0 == in_rx_cycle) { + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + //Write out the 8 byte address + i2c_data_transmit(I2C0, read_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + in_rx_cycle=1; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + } else { + /* one byte master reception procedure (polling) */ + if (number_of_byte < 2) { + /* disable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ + i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + /* wait for the byte to be received */ + while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) + ; + /* read the byte received from the EEPROM */ + *p_buffer = i2c_data_receive(I2C0); + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } else { /* more than one byte master reception procedure (DMA) */ + dma_deinit(DMA0, DMA_CH6); + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_init_struct.memory_addr = (uint32_t) p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH6, &dma_init_struct); + + i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH6); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { + osDelay(1); + } + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + default: + state = I2C_START; + in_rx_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; + break; } } unlock(); @@ -81,48 +224,150 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_bu if (!lock()) return false; - i2c_slave_address = DevAddress; - i2c_write = p_buffer; - i2c_write_dress = MemAddress; - i2c_nbytes = number_of_byte; - i2c_error_code = 0; - i2c_process_flag = 0; - i2c_write_process = I2C_SEND_ADDRESS_FIRST; - i2c_read_process = I2C_SEND_ADDRESS_FIRST; - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); - /* enable the I2C0 interrupt */ - i2c_interrupt_enable(I2C0, I2C_INT_ERR); - i2c_interrupt_enable(I2C0, I2C_INT_EV); - i2c_interrupt_enable(I2C0, I2C_INT_BUF); - /* wait until I2C bus is idle */ - uint8_t timeout = 0; - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) { - timeout++; - osDelay(1); - if (timeout > 20) { - unlock(); - return false; - } - } + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; - /* send a start condition to I2C bus */ - //This sending will kickoff the IRQ's - i2c_start_on_bus(I2C0); - while ((i2c_nbytes > 0)) { - osDelay(1); - if (i2c_error_code != 0) { - unlock(); - return false; + uint8_t state = I2C_START; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + //Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + unlock(); + return false; + + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(I2C0, MemAddress); + timeout = 0; + } else { + timedout = true; + timeout = 0; + state = I2C_START; + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + dma_deinit(DMA0, DMA_CH5); + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_addr = (uint32_t) p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH5, &dma_init_struct); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH5); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { + osDelay(1); + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + state = I2C_STOP; + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + i2c_timeout_flag = I2C_OK; + timeout = 0; + break; } } unlock(); - return true; + return timedout == false; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index 1049fc18..8a726beb 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -74,215 +74,11 @@ void EXTI5_9_IRQHandler(void) { #endif } -/*! - \brief handle I2C0 event interrupt request - \param[in] none - \param[out] none - \retval none - */ +//These are unused for now void I2C0_EV_IRQHandler(void) { - if (RESET == i2c_process_flag) { - switch (i2c_write_process) { - case I2C_SEND_ADDRESS_FIRST: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { - /* send slave address */ - i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); - i2c_write_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; - } - break; - case I2C_CLEAR_ADDRESS_FLAG_FIRST: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { - /*clear ADDSEND bit */ - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); - i2c_write_process = I2C_TRANSMIT_WRITE_READ_ADD; - } - break; - case I2C_TRANSMIT_WRITE_READ_ADD: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - i2c_data_transmit(I2C0, i2c_write_dress); - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - i2c_write_process = I2C_TRANSMIT_DATA; - } - break; - case I2C_TRANSMIT_DATA: - if (i2c_nbytes) { - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - /* the master sends a data byte */ - i2c_data_transmit(I2C0, *i2c_write++); - i2c_nbytes--; - if (0 == i2c_nbytes) { - i2c_write_process = I2C_STOP; - } - } - } else { - i2c_write_process = I2C_STOP; - } - break; - case I2C_STOP: - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_write_process = I2C_SEND_ADDRESS_FIRST; - break; - default: - break; - } - } else if (SET == i2c_process_flag) { - switch (i2c_read_process) { - case I2C_SEND_ADDRESS_FIRST: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { - /* send slave address */ - i2c_master_addressing(I2C0, i2c_slave_address, I2C_TRANSMITTER); - i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_FIRST; - } - break; - case I2C_CLEAR_ADDRESS_FLAG_FIRST: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { - /*clear ADDSEND bit */ - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); - i2c_read_process = I2C_TRANSMIT_WRITE_READ_ADD; - } - break; - case I2C_TRANSMIT_WRITE_READ_ADD: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE)) { - i2c_data_transmit(I2C0, i2c_read_dress); - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - /* send a start condition to I2C bus */ - i2c_start_on_bus(I2C0); - i2c_read_process = I2C_SEND_ADDRESS_SECOND; - } - break; - case I2C_SEND_ADDRESS_SECOND: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SBSEND)) { - i2c_master_addressing(I2C0, i2c_slave_address, I2C_RECEIVER); - if ((1 == i2c_nbytes) || (2 == i2c_nbytes)) { - i2c_ackpos_config(I2C0, i2c_nbytes == 1 ? I2C_ACKPOS_CURRENT : I2C_ACKPOS_NEXT); - /* clear the ACKEN before the ADDSEND is cleared */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } else { - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - } - i2c_read_process = I2C_CLEAR_ADDRESS_FLAG_SECOND; - } - break; - case I2C_CLEAR_ADDRESS_FLAG_SECOND: - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND)) { - - /*clear ADDSEND bit */ - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND); - i2c_read_process = I2C_TRANSMIT_DATA; - - } - break; - case I2C_TRANSMIT_DATA: - if (i2c_nbytes > 0) { - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE)) { - /* read a byte from the EEPROM */ - if (i2c_nbytes == 2) { - /* wait until BTC bit is set */ - i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT); - /* clear the ACKEN before the ADDSEND is cleared */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - } - *i2c_read = i2c_data_receive(I2C0); - i2c_read++; - i2c_nbytes--; - if (i2c_nbytes == 0) { - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_process_flag = RESET; - i2c_read_process = I2C_DONE; - } - } - } else { - i2c_read_process = I2C_STOP; - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_process_flag = RESET; - i2c_read_process = I2C_DONE; - } - break; - case I2C_STOP: - /* the master sends a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* disable the I2C0 interrupt */ - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_process_flag = RESET; - i2c_read_process = I2C_DONE; - break; - default: - break; - } - } } -/*! - \brief handle I2C0 error interrupt request - \param[in] none - \param[out] none - \retval none - */ void I2C0_ER_IRQHandler(void) { - /* no acknowledge received */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_AERR); - i2c_error_code = 1; //NAK - } - - /* SMBus alert */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBALT)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBALT); - i2c_error_code = 2; //SMB Alert - } - - /* bus timeout in SMBus mode */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_SMBTO)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_SMBTO); - i2c_error_code = 3; //SMB Timeout - } - - /* over-run or under-run when SCL stretch is disabled */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_OUERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_OUERR); - i2c_error_code = 4; //OverRun - } - - /* arbitration lost */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_LOSTARB)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_LOSTARB); - i2c_error_code = 5; //Lost ARB -- multi master -- shouldnt happen - } - - /* bus error */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_BERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_BERR); - i2c_error_code = 6; //Bus Error - } - - /* CRC value doesn't match */ - if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_PECERR)) { - i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_PECERR); - i2c_error_code = 7; //CRC Fail -- Shouldnt Happen - } - - i2c_stop_on_bus(I2C0); } diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.h b/workspace/TS100/Core/BSP/Pine64/IRQ.h index 354a8d6a..e0465ac7 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.h +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.h @@ -34,6 +34,11 @@ typedef enum { I2C_STOP, //Send stop I2C_ABORTED, // I2C_DONE,// I2C transfer is complete + I2C_START , + I2C_END, + I2C_OK, + I2C_SEND_ADDRESS, + I2C_CLEAR_ADDRESS_FLAG, } i2c_process_enum; extern volatile uint8_t i2c_slave_address; extern volatile uint8_t i2c_read_process; diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 08a2c7d4..3dd25f03 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -35,7 +35,7 @@ void hardware_init() { //Timers setup_timers(); //Watchdog - setup_iwdg(); + setup_iwdg(); /* enable TIMER1 - PWM control timing*/ timer_enable(TIMER1); @@ -65,7 +65,7 @@ void setup_gpio() { gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, OLED_RESET_Pin); //I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); //PWM output as AF Push Pull gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); @@ -78,15 +78,6 @@ void setup_gpio() { //Remap PB4 away from JTAG NJRST gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); - //Setup IRQ for USB-PD - gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, FUSB302_IRQ_Pin); - eclic_irq_enable(EXTI5_9_IRQn, 1, 1); - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); - - /* configure key EXTI line */ - exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(EXTI_5); //TODO - rest of pins as floating } @@ -121,7 +112,6 @@ void setup_dma() { } } void setup_i2c() { - //TODO - DMA /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 400kHz @@ -130,8 +120,8 @@ void setup_i2c() { i2c_enable(I2C0); /* enable acknowledge */ i2c_ack_config(I2C0, I2C_ACK_ENABLE); - eclic_irq_enable(I2C0_EV_IRQn,1,0); - eclic_irq_enable(I2C0_ER_IRQn,2,0); + eclic_irq_enable(I2C0_EV_IRQn, 1, 0); + eclic_irq_enable(I2C0_ER_IRQn, 2, 0); } void setup_adc() { @@ -290,3 +280,15 @@ void setup_timers() { void setup_iwdg() { //TODO } + +void setupFUSBIRQ() { + //Setup IRQ for USB-PD + gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, FUSB302_IRQ_Pin); + eclic_irq_enable(EXTI5_9_IRQn, 1, 1); + /* connect key EXTI line to key GPIO pin */ + gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); + + /* configure key EXTI line */ + exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); + exti_interrupt_flag_clear(EXTI_5); +} diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.h b/workspace/TS100/Core/BSP/Pine64/Setup.h index 805a78de..8bc6fdeb 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.h +++ b/workspace/TS100/Core/BSP/Pine64/Setup.h @@ -15,6 +15,7 @@ extern "C" { #endif uint16_t getADC(uint8_t channel); void hardware_init(); +void setupFUSBIRQ(); #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp index 2d1a89b8..1e96dc7c 100644 --- a/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Pine64/fusb302b.cpp @@ -16,6 +16,7 @@ */ #include "Model_Config.h" #ifdef POW_PD +#include "Setup.h" #include "BSP.h" #include "fusb302b.h" #include "I2C_Wrapper.hpp" @@ -133,9 +134,9 @@ void fusb_send_hardrst() { } -void fusb_setup() { +bool fusb_setup() { if (!FRToSI2C::probe(FUSB302B_ADDR)) { - return; + return false; } /* Fully reset the FUSB302B */ fusb_write_byte( FUSB_RESET, FUSB_RESET_SW_RES); @@ -145,7 +146,7 @@ void fusb_setup() { osDelay(10); tries++; if (tries > 5) { - return; //Welp :( + return false; //Welp :( } } @@ -187,6 +188,8 @@ void fusb_setup() { } fusb_reset(); + setupFUSBIRQ(); + return true; } void fusb_get_status(union fusb_status *status) { diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h index bcd66407..1276e276 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h +++ b/workspace/TS100/Core/Drivers/FUSB302/fusb302b.h @@ -293,7 +293,7 @@ enum fusb_typec_current fusb_get_typec_current(); /* * Initialization routine for the FUSB302B */ -void fusb_setup(); +bool fusb_setup(); /* * Reset the FUSB302B diff --git a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp index fb8c833c..f8624fbe 100644 --- a/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp +++ b/workspace/TS100/Core/Drivers/FUSB302/fusbpd.cpp @@ -18,10 +18,11 @@ void fusb302_start_processing() { /* Initialize the FUSB302B */ - fusb_setup(); - PolicyEngine::init(); - ProtocolTransmit::init(); - ProtocolReceive::init(); - InterruptHandler::init(); + if (fusb_setup()) { + PolicyEngine::init(); + ProtocolTransmit::init(); + ProtocolReceive::init(); + InterruptHandler::init(); + } } #endif From 8d0addd7f151b7d6409a1a836257f9b6d570c1b2 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 26 Sep 2020 17:09:57 +1000 Subject: [PATCH 24/72] Fix build --- .../TS100/Core/BSP/Miniware/I2C_Wrapper.cpp | 120 ++- .../TS100/Core/BSP/Pine64/FreeRTOSConfig.h | 48 +- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 716 +++++++++--------- workspace/TS100/Core/BSP/Pine64/N200/port.c | 335 ++++---- .../TS100/Core/BSP/Pine64/N200/portmacro.h | 126 +-- workspace/TS100/Core/Inc/FreeRTOSConfig.h | 171 ----- 6 files changed, 642 insertions(+), 874 deletions(-) delete mode 100644 workspace/TS100/Core/Inc/FreeRTOSConfig.h diff --git a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp index 95ae98b1..d819646e 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp @@ -4,110 +4,96 @@ * Created on: 14Apr.,2018 * Author: Ralim */ -#include #include "BSP.h" #include "Setup.h" +#include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; -SemaphoreHandle_t FRToSI2C::I2CSemaphore2 = nullptr; -StaticSemaphore_t FRToSI2C::xSemaphoreBuffer2; void FRToSI2C::CpltCallback() { - hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) - if (I2CSemaphore) { - xSemaphoreGiveFromISR(I2CSemaphore, NULL); - } + hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) + if (I2CSemaphore) { + xSemaphoreGiveFromISR(I2CSemaphore, NULL); + } } bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (!lock()) + return false; + if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } - - unlock(); - return true; + I2C_Unstick(); + unlock(); + return false; + } + unlock(); + return true; } bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - return Mem_Write(address, reg, &data, 1); + return Mem_Write(address, reg, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t tx_data[1]; - Mem_Read(add, reg, tx_data, 1); - return tx_data[0]; + uint8_t tx_data[1]; + Mem_Read(add, reg, tx_data, 1); + return tx_data[0]; } bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (!lock()) + return false; + if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } + I2C_Unstick(); + unlock(); + return false; + } - unlock(); - return true; + unlock(); + return true; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } - return true; + if (!lock()) + return false; + if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) { + I2C_Unstick(); + unlock(); + return false; + } + return true; } bool FRToSI2C::probe(uint16_t DevAddress) { - if (!lock()) - return false; - uint8_t buffer[1]; - bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; - unlock(); - return worked; + if (!lock()) + return false; + uint8_t buffer[1]; + bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; + unlock(); + return worked; } void FRToSI2C::I2C_Unstick() { - unstick_I2C(); + unstick_I2C(); } void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); + xSemaphoreGive(I2CSemaphore); } bool FRToSI2C::lock() { - return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; -} -bool FRToSI2C::lock2() { - if (I2CSemaphore2 == nullptr) - return true; - return xSemaphoreTake(I2CSemaphore2,1000) == pdTRUE; + return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; } -void FRToSI2C::unlock2() { - if (I2CSemaphore2 == nullptr) - return; - xSemaphoreGive(I2CSemaphore2); -} - -bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) - delay_ms(registers[index].pause_ms); - } - return true; +bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) + delay_ms(registers[index].pause_ms); + } + return true; } diff --git a/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h index 72625f02..f160e455 100644 --- a/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h +++ b/workspace/TS100/Core/BSP/Pine64/FreeRTOSConfig.h @@ -6,7 +6,7 @@ extern uint32_t SystemCoreClock; #endif //RISC-V configuration - +#include "n200_timer.h" #define USER_MODE_TASKS 0 #define configUSE_PREEMPTION 1 @@ -69,30 +69,30 @@ extern uint32_t SystemCoreClock; #define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) /* Define to trap errors during development. */ -#define configASSERT(x) \ - if ((x) == 0) { \ - taskDISABLE_INTERRUPTS(); \ - for (;;) \ - ; \ - } +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 1 -#define INCLUDE_vTaskDelete 1 -#define INCLUDE_vTaskSuspend 1 -#define INCLUDE_xResumeFromISR 1 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 -#define INCLUDE_xTaskGetIdleTaskHandle 1 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 1 -#define INCLUDE_xTimerPendFunctionCall 0 -#define INCLUDE_xTaskAbortDelay 0 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_xResumeFromISR 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 1 +#define INCLUDE_xTimerPendFunctionCall 0 +#define INCLUDE_xTaskAbortDelay 0 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif /* FREERTOS_CONFIG_H */ diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index a43dcb76..f24f0d81 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -5,403 +5,399 @@ * Author: Ralim */ #include "BSP.h" -#include "Setup.h" #include "IRQ.h" +#include "Setup.h" #include SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; -#define I2C_TIME_OUT (uint16_t)(5000) +#define I2C_TIME_OUT (uint16_t)(5000) void FRToSI2C::CpltCallback() { - //TODO + //TODO } bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - return Mem_Write(address, reg, &data, 1); + return Mem_Write(address, reg, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t temp = 0; - Mem_Read(add, reg, &temp, 1); - return temp; + uint8_t temp = 0; + Mem_Read(add, reg, &temp, 1); + return temp; } bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - dma_parameter_struct dma_init_struct; + if (!lock()) + return false; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint8_t in_rx_cycle = 0; - uint16_t timeout = 0; - uint8_t i2c_timeout_flag = 0; - while (!(i2c_timeout_flag)) { - switch (state) { - case I2C_START: - if (0 == in_rx_cycle) { - /* disable I2C0 */ - i2c_disable(I2C0); - /* enable I2C0 */ - i2c_enable(I2C0); + uint8_t state = I2C_START; + uint8_t in_rx_cycle = 0; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + if (0 == in_rx_cycle) { + /* disable I2C0 */ + i2c_disable(I2C0); + /* enable I2C0 */ + i2c_enable(I2C0); - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the start signal */ - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - } else { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - if (RESET == in_rx_cycle) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); - state = I2C_CLEAR_ADDRESS_FLAG; - } - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - break; - case I2C_TRANSMIT_DATA: - if (0 == in_rx_cycle) { - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - //Write out the 8 byte address - i2c_data_transmit(I2C0, read_address); - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - /* wait until BTC bit is set */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_START; - in_rx_cycle=1; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - } else { - /* one byte master reception procedure (polling) */ - if (number_of_byte < 2) { - /* disable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ - i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - /* wait for the byte to be received */ - while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) - ; - /* read the byte received from the EEPROM */ - *p_buffer = i2c_data_receive(I2C0); - /* decrement the read bytes counter */ - number_of_byte--; - timeout = 0; - } else { /* more than one byte master reception procedure (DMA) */ - dma_deinit(DMA0, DMA_CH6); - dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_init_struct.memory_addr = (uint32_t) p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH6, &dma_init_struct); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the start signal */ + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + } else { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + if (RESET == in_rx_cycle) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + if (0 == in_rx_cycle) { + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + //Write out the 8 byte address + i2c_data_transmit(I2C0, read_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + in_rx_cycle = 1; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + } else { + /* one byte master reception procedure (polling) */ + if (number_of_byte < 2) { + /* disable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ + i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + /* wait for the byte to be received */ + while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) + ; + /* read the byte received from the EEPROM */ + *p_buffer = i2c_data_receive(I2C0); + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } else { /* more than one byte master reception procedure (DMA) */ + dma_deinit(DMA0, DMA_CH6); + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_init_struct.memory_addr = (uint32_t)p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH6, &dma_init_struct); - i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH6); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { - osDelay(1); - } - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - } - timeout = 0; - state = I2C_STOP; - } - break; - case I2C_STOP: - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - i2c_timeout_flag = I2C_OK; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - default: - state = I2C_START; - in_rx_cycle = 0; - i2c_timeout_flag = I2C_OK; - timeout = 0; - break; - } - } - unlock(); - return true; + i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH6); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { + osDelay(1); + } + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + default: + state = I2C_START; + in_rx_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; + break; + } + } + unlock(); + return true; } bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; + if (!lock()) + return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - dma_parameter_struct dma_init_struct; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint16_t timeout = 0; - uint8_t i2c_timeout_flag = 0; - bool done = false; - bool timedout = false; - while (!(done || timedout)) { - switch (state) { - case I2C_START: - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - timeout = 0; - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - //Dont retry as this means a NAK - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - unlock(); - return false; - - } - break; - case I2C_TRANSMIT_DATA: - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the EEPROM's internal address to write to : only one byte address */ - i2c_data_transmit(I2C0, MemAddress); - timeout = 0; - } else { - timedout = true; - timeout = 0; - state = I2C_START; - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - dma_deinit(DMA0, DMA_CH5); - dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; - dma_init_struct.memory_addr = (uint32_t) p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH5, &dma_init_struct); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH5); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { - osDelay(1); - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - state = I2C_STOP; - break; - case I2C_STOP: - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - i2c_timeout_flag = I2C_OK; - done = true; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - default: - state = I2C_START; - i2c_timeout_flag = I2C_OK; - timeout = 0; - break; - } - } - unlock(); - return timedout == false; + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + //Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(I2C0, MemAddress); + timeout = 0; + } else { + timedout = true; + timeout = 0; + state = I2C_START; + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + dma_deinit(DMA0, DMA_CH5); + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_addr = (uint32_t)p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH5, &dma_init_struct); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH5); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { + osDelay(1); + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + state = I2C_STOP; + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); + return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); } bool FRToSI2C::probe(uint16_t DevAddress) { - uint8_t temp[1]; - return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); + uint8_t temp[1]; + return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); } void FRToSI2C::I2C_Unstick() { - unstick_I2C(); + unstick_I2C(); } bool FRToSI2C::lock() { - if (I2CSemaphore == nullptr) { - return false; - } - return xSemaphoreTake(I2CSemaphore,1000) == pdTRUE; + if (I2CSemaphore == nullptr) { + return false; + } + return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; } void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); + xSemaphoreGive(I2CSemaphore); } -bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG* registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) { - delay_ms(registers[index].pause_ms); - } - } - return true; +bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) { + delay_ms(registers[index].pause_ms); + } + } + return true; } diff --git a/workspace/TS100/Core/BSP/Pine64/N200/port.c b/workspace/TS100/Core/BSP/Pine64/N200/port.c index ac7c84fd..e49f68a4 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/port.c +++ b/workspace/TS100/Core/BSP/Pine64/N200/port.c @@ -1,41 +1,39 @@ +#include "FreeRTOSConfig.h" +// #include "FreeRTOS.h" -#include "task.h" -#include "portmacro.h" #include "gd32vf103.h" -#include "n200_func.h" -#include "riscv_encoding.h" -#include "n200_timer.h" #include "n200_eclic.h" - +#include "n200_func.h" +#include "n200_timer.h" +#include "portmacro.h" +#include "riscv_encoding.h" +#include "task.h" /* Standard Includes */ -#include #include +#include #include - /* Each task maintains its own interrupt status in the critical nesting variable. */ UBaseType_t uxCriticalNesting = 0xaaaaaaaa; #if USER_MODE_TASKS #ifdef __riscv_flen - unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); +unsigned long MSTATUS_INIT = (MSTATUS_MPIE | (0x1 << 13)); #else - unsigned long MSTATUS_INIT = (MSTATUS_MPIE); +unsigned long MSTATUS_INIT = (MSTATUS_MPIE); #endif #else #ifdef __riscv_flen - unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); +unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE | (0x1 << 13)); #else - unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); +unsigned long MSTATUS_INIT = (MSTATUS_MPP | MSTATUS_MPIE); #endif #endif - /* * Used to catch tasks that attempt to return from their implementing function. */ -static void prvTaskExitError( void ); - +static void prvTaskExitError(void); /** * @brief System Call Trap @@ -45,79 +43,63 @@ static void prvTaskExitError( void ); * @param arg1 ECALL macro stores argument in a2 * @return unsigned long 传入的sp */ -unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) -{ - switch(mcause&0X00000fff) - { - //on User and Machine ECALL, handler the request - case 8: - case 11: - { - if(arg1==IRQ_DISABLE) - { - //zero out mstatus.mpie - clear_csr(mstatus,MSTATUS_MPIE); - } - else if(arg1==IRQ_ENABLE) - { - //set mstatus.mpie - set_csr(mstatus,MSTATUS_MPIE); - } - else if(arg1==PORT_YIELD) - { - //always yield from machine mode - //fix up mepc on sync trap - unsigned long epc = read_csr(mepc); - vPortYield_from_ulSynchTrap(sp,epc+4); - } - else if(arg1==PORT_YIELD_TO_RA) - { - vPortYield_from_ulSynchTrap(sp,(*(unsigned long*)(sp+1*sizeof(sp)))); - } - break; - } - default: - { - /* 异常处理 */ - extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); - handle_trap(mcause,sp); - } - } +unsigned long ulSynchTrap(unsigned long mcause, unsigned long sp, unsigned long arg1) { + switch (mcause & 0X00000fff) { + //on User and Machine ECALL, handler the request + case 8: + case 11: { + if (arg1 == IRQ_DISABLE) { + //zero out mstatus.mpie + clear_csr(mstatus, MSTATUS_MPIE); + } else if (arg1 == IRQ_ENABLE) { + //set mstatus.mpie + set_csr(mstatus, MSTATUS_MPIE); + } else if (arg1 == PORT_YIELD) { + //always yield from machine mode + //fix up mepc on sync trap + unsigned long epc = read_csr(mepc); + vPortYield_from_ulSynchTrap(sp, epc + 4); + } else if (arg1 == PORT_YIELD_TO_RA) { + vPortYield_from_ulSynchTrap(sp, (*(unsigned long *)(sp + 1 * sizeof(sp)))); + } + break; + } + default: { + /* 异常处理 */ + extern uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp); + handle_trap(mcause, sp); + } + } - //fix mepc and return - unsigned long epc = read_csr(mepc); + //fix mepc and return + unsigned long epc = read_csr(mepc); - write_csr(mepc,epc+4); - return sp; + write_csr(mepc, epc + 4); + return sp; } /*-----------------------------------------------------------*/ - /** * @brief 设置触发软中断 * @note 目的是在软中断内进行任务上下文切换 * */ -void vPortSetMSIPInt(void) -{ - *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) |=0x01; - __asm volatile("fence"); - __asm volatile("fence.i"); +void vPortSetMSIPInt(void) { + *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) |= 0x01; + __asm volatile("fence"); + __asm volatile("fence.i"); } /*-----------------------------------------------------------*/ - /** * @brief 清除软中断 * */ -void vPortClearMSIPInt(void) -{ - *(volatile uint8_t *) (TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; +void vPortClearMSIPInt(void) { + *(volatile uint8_t *)(TIMER_CTRL_ADDR + TIMER_MSIP) &= ~0x01; } /*-----------------------------------------------------------*/ - /** * @brief 执行任务上下文切换,在portasm.S中被调用 * @@ -125,97 +107,84 @@ void vPortClearMSIPInt(void) * @param arg1 * @return unsigned long sp地址 */ -unsigned long taskswitch( unsigned long sp, unsigned long arg1) -{ - //always yield from machine mode - //fix up mepc on - unsigned long epc = read_csr(mepc); - vPortYield(sp,epc); //never returns +unsigned long taskswitch(unsigned long sp, unsigned long arg1) { + //always yield from machine mode + //fix up mepc on + unsigned long epc = read_csr(mepc); + vPortYield(sp, epc); //never returns - return sp; + return sp; } /*-----------------------------------------------------------*/ - /** * @brief 调研freertos内建函数vTaskSwitchContext,在portasm.S中被调用 * */ -void vDoTaskSwitchContext( void ) -{ - portDISABLE_INTERRUPTS(); - vTaskSwitchContext(); - portENABLE_INTERRUPTS(); +void vDoTaskSwitchContext(void) { + portDISABLE_INTERRUPTS(); + vTaskSwitchContext(); + portENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ - /** * @brief 进入临界段 * */ -void vPortEnterCritical( void ) -{ - #if USER_MODE_TASKS - ECALL(IRQ_DISABLE); - #else - portDISABLE_INTERRUPTS(); - #endif +void vPortEnterCritical(void) { +#if USER_MODE_TASKS + ECALL(IRQ_DISABLE); +#else + portDISABLE_INTERRUPTS(); +#endif - uxCriticalNesting++; + uxCriticalNesting++; } /*-----------------------------------------------------------*/ - /** * @brief 退出临界段 * */ -void vPortExitCritical( void ) -{ - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - #if USER_MODE_TASKS - ECALL(IRQ_ENABLE); - #else - portENABLE_INTERRUPTS(); - #endif - } - return; +void vPortExitCritical(void) { + configASSERT(uxCriticalNesting); + uxCriticalNesting--; + if (uxCriticalNesting == 0) { +#if USER_MODE_TASKS + ECALL(IRQ_ENABLE); +#else + portENABLE_INTERRUPTS(); +#endif + } + return; } /*-----------------------------------------------------------*/ - /** * @brief Clear current interrupt mask and set given mask * * @param int_mask mth值 */ -void vPortClearInterruptMask(int int_mask) -{ - eclic_set_mth (int_mask); +void vPortClearInterruptMask(int int_mask) { + eclic_set_mth(int_mask); } /*-----------------------------------------------------------*/ - /** * @brief Set interrupt mask and return current interrupt enable register * * @return int */ -int xPortSetInterruptMask(void) -{ - int int_mask=0; - int_mask=eclic_get_mth(); +int xPortSetInterruptMask(void) { + int int_mask = 0; + int_mask = eclic_get_mth(); - portDISABLE_INTERRUPTS(); - return int_mask; + portDISABLE_INTERRUPTS(); + return int_mask; } /*-----------------------------------------------------------*/ - /** * @brief 初始化任务栈帧 * @@ -224,138 +193,126 @@ int xPortSetInterruptMask(void) * @param pvParameters 任务参数 * @return StackType_t* 完成初始化后的栈顶 */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) -{ - /* Simulate the stack frame as it would be created by a context switch +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) { + /* Simulate the stack frame as it would be created by a context switch interrupt. */ #ifdef __riscv_flen - pxTopOfStack -= 32; /* 浮点寄存器 */ + pxTopOfStack -= 32; /* 浮点寄存器 */ #endif - pxTopOfStack--; - *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ + pxTopOfStack--; + *pxTopOfStack = 0xb8000000; /* CSR_MCAUSE */ - pxTopOfStack--; - *pxTopOfStack = 0x40; /* CSR_SUBM */ + pxTopOfStack--; + *pxTopOfStack = 0x40; /* CSR_SUBM */ - pxTopOfStack--; - *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ + pxTopOfStack--; + *pxTopOfStack = (portSTACK_TYPE)pxCode; /* Start address */ - pxTopOfStack--; - *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ + pxTopOfStack--; + *pxTopOfStack = MSTATUS_INIT; /* CSR_MSTATUS */ - pxTopOfStack -= 22; - *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ + pxTopOfStack -= 22; + *pxTopOfStack = (portSTACK_TYPE)pvParameters; /* Register a0 */ - pxTopOfStack -=9; - *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */ - pxTopOfStack--; + pxTopOfStack -= 9; + *pxTopOfStack = (portSTACK_TYPE)prvTaskExitError; /* Register ra */ + pxTopOfStack--; - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ - /** * @brief 任务退出函数 * */ -void prvTaskExitError( void ) -{ - /* A function that implements a task must not exit or attempt to return to +void prvTaskExitError(void) { + /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it should instead call vTaskDelete( NULL ). Artificially force an assert() to be triggered if configASSERT() is defined, then stop here so application writers can catch the error. */ - configASSERT( uxCriticalNesting == ~0UL ); - portDISABLE_INTERRUPTS(); - for( ;; ); + configASSERT(uxCriticalNesting == ~0UL); + portDISABLE_INTERRUPTS(); + for (;;) + ; } /*-----------------------------------------------------------*/ - /** * @brief tick中断 * @note 由于该中断配置为向量模式,则中断到来会调用portasm.S的MTIME_HANDLER,进行栈帧保存之后该函数会调用vPortSysTickHandler * */ -void vPortSysTickHandler(void) -{ - volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); +void vPortSysTickHandler(void) { + volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); - UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - #if CONFIG_SYSTEMVIEW_EN - traceISR_ENTER(); - #endif +#if CONFIG_SYSTEMVIEW_EN + traceISR_ENTER(); +#endif - uint64_t now = *mtime; - now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); - *mtimecmp = now; + uint64_t now = *mtime; + now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); + *mtimecmp = now; - /* 调用freertos的tick增加接口 */ - if( xTaskIncrementTick() != pdFALSE ) - { - #if CONFIG_SYSTEMVIEW_EN - traceISR_EXIT_TO_SCHEDULER(); - #endif - portYIELD(); - } - #if CONFIG_SYSTEMVIEW_EN - else - { - traceISR_EXIT(); - } - #endif + /* 调用freertos的tick增加接口 */ + if (xTaskIncrementTick() != pdFALSE) { +#if CONFIG_SYSTEMVIEW_EN + traceISR_EXIT_TO_SCHEDULER(); +#endif + portYIELD(); + } +#if CONFIG_SYSTEMVIEW_EN + else { + traceISR_EXIT(); + } +#endif - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } /*-----------------------------------------------------------*/ - /** * @brief 初始化tick * */ -void vPortSetupTimer(void) -{ - /* 内核timer定时器使用64位的计数器来实现 */ - volatile uint64_t * mtime = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIME); - volatile uint64_t * mtimecmp = (uint64_t*) (TIMER_CTRL_ADDR + TIMER_MTIMECMP); +void vPortSetupTimer(void) { + /* 内核timer定时器使用64位的计数器来实现 */ + volatile uint64_t *mtime = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIME); + volatile uint64_t *mtimecmp = (uint64_t *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP); - portENTER_CRITICAL(); + portENTER_CRITICAL(); uint64_t now = *mtime; now += (configRTC_CLOCK_HZ / configTICK_RATE_HZ); *mtimecmp = now; - portEXIT_CRITICAL(); + portEXIT_CRITICAL(); - eclic_set_vmode(CLIC_INT_TMR); - eclic_irq_enable(CLIC_INT_TMR,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); + eclic_set_vmode(CLIC_INT_TMR); + eclic_irq_enable(CLIC_INT_TMR, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); } /*-----------------------------------------------------------*/ - /** * @brief 初始化软中断 * */ -void vPortSetupMSIP(void) -{ - eclic_set_vmode(CLIC_INT_SFT); - eclic_irq_enable(CLIC_INT_SFT,configKERNEL_INTERRUPT_PRIORITY>>configPRIO_BITS,0); +void vPortSetupMSIP(void) { + eclic_set_vmode(CLIC_INT_SFT); + eclic_irq_enable(CLIC_INT_SFT, configKERNEL_INTERRUPT_PRIORITY >> configPRIO_BITS, 0); } /*-----------------------------------------------------------*/ - /** * @brief 调度启动前的初始化准备 * */ -void vPortSetup(void) -{ - vPortSetupTimer(); - vPortSetupMSIP(); - uxCriticalNesting = 0; +void vPortSetup(void) { + vPortSetupTimer(); + vPortSetupMSIP(); + uxCriticalNesting = 0; } /*-----------------------------------------------------------*/ diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h index 50383ac5..351f9f56 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h +++ b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h @@ -5,10 +5,8 @@ extern "C" { #endif - #include "riscv_encoding.h" - /*----------------------------------------------------------- * Port specific definitions. * @@ -20,123 +18,125 @@ extern "C" { */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long typedef portSTACK_TYPE StackType_t; typedef long BaseType_t; typedef unsigned long UBaseType_t; -#if( configUSE_16_BIT_TICKS == 1 ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +#if (configUSE_16_BIT_TICKS == 1) +typedef uint16_t TickType_t; +#define portMAX_DELAY (TickType_t)0xffff #else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +typedef uint32_t TickType_t; +#define portMAX_DELAY (TickType_t)0xffffffffUL #endif /*-----------------------------------------------------------*/ /* Architecture specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 8 +#define portSTACK_GROWTH (-1) +#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ) +#define portBYTE_ALIGNMENT 8 /*-----------------------------------------------------------*/ /* Architecture specifics. */ -extern void vPortYield(unsigned long,unsigned long); -extern void vPortYield_from_ulSynchTrap(unsigned long,unsigned long); +extern void vPortYield(unsigned long, unsigned long); +extern void vPortYield_from_ulSynchTrap(unsigned long, unsigned long); extern int xPortSetInterruptMask(void); -extern void vPortClearInterruptMask( int uxSavedStatusValue ); - +extern void vPortClearInterruptMask(int uxSavedStatusValue); /*-----------------------------------------------------------*/ /*System Calls */ /*-----------------------------------------------------------*/ //ecall macro used to store argument in a3 -#define ECALL(arg) ({ \ - register uintptr_t a2 asm ("a2") = (uintptr_t)(arg); \ - asm volatile ("ecall" \ - : "+r" (a2) \ - : \ - : "memory"); \ - a2; \ +#define ECALL(arg) ({ \ + register uintptr_t a2 asm("a2") = (uintptr_t)(arg); \ + asm volatile("ecall" \ + : "+r"(a2) \ + : \ + : "memory"); \ + a2; \ }) - extern void vPortSetMSIPInt(void); #define port_MSIPSET_BIT vPortSetMSIPInt() -#define IRQ_DISABLE 20 -#define IRQ_ENABLE 30 -#define PORT_YIELD 40 -#define PORT_YIELD_TO_RA 50 +#define IRQ_DISABLE 20 +#define IRQ_ENABLE 30 +#define PORT_YIELD 40 +#define PORT_YIELD_TO_RA 50 /*-----------------------------------------------------------*/ - /* Scheduler utilities. */ /* the return after the ECALL is VERY important */ //#define portYIELD() ECALL(PORT_YIELD); #define portYIELD() port_MSIPSET_BIT; -#if CONFIG_SYSTEMVIEW_EN -#define portEND_SWITCHING_ISR(xSwitchRequired) { if( xSwitchRequired != pdFALSE) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else {traceISR_EXIT(); } } +#ifdef CONFIG_SYSTEMVIEW_EN +#define portEND_SWITCHING_ISR(xSwitchRequired) \ + { \ + if (xSwitchRequired != pdFALSE) { \ + traceISR_EXIT_TO_SCHEDULER(); \ + portYIELD(); \ + } else { \ + traceISR_EXIT(); \ + } \ + } #else -#define portEND_SWITCHING_ISR(xSwitchRequired) if( xSwitchRequired != pdFALSE) portYIELD() +#define portEND_SWITCHING_ISR(xSwitchRequired) \ + if (xSwitchRequired != pdFALSE) \ + portYIELD() #endif -#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) +#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x) /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -extern void eclic_set_mth (uint8_t mth); -#define portDISABLE_INTERRUPTS() \ -{ \ - eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY)|0x1f); \ - __asm volatile("fence"); \ - __asm volatile("fence.i"); \ -} -#define portENABLE_INTERRUPTS() eclic_set_mth(0) -#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue ) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() +extern void vPortEnterCritical(void); +extern void vPortExitCritical(void); +extern void eclic_set_mth(uint8_t mth); +#define portDISABLE_INTERRUPTS() \ + { \ + eclic_set_mth((configMAX_SYSCALL_INTERRUPT_PRIORITY) | 0x1f); \ + __asm volatile("fence"); \ + __asm volatile("fence.i"); \ + } +#define portENABLE_INTERRUPTS() eclic_set_mth(0) +#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. These are not necessary for to use this port. They are defined so the common demo files (which build with all the ports) will build. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) +#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters) /*-----------------------------------------------------------*/ /* Tickless idle/low power functionality. */ #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +#define portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime) vPortSuppressTicksAndSleep(xExpectedIdleTime) #endif /*-----------------------------------------------------------*/ - -#define portINLINE __inline +#define portINLINE __inline #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) +#define portFORCE_INLINE inline __attribute__((always_inline)) #endif - - - #ifdef __cplusplus } #endif #endif /* PORTMACRO_H */ - diff --git a/workspace/TS100/Core/Inc/FreeRTOSConfig.h b/workspace/TS100/Core/Inc/FreeRTOSConfig.h deleted file mode 100644 index e2c1c4c7..00000000 --- a/workspace/TS100/Core/Inc/FreeRTOSConfig.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading - the FAQ page "My application does not run, what could be wrong?". Have you - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - http://www.FreeRTOS.org/training - Investing in training allows your team to - be as productive as possible as early as possible. Now you can receive - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. - Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! - */ - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -/* USER CODE BEGIN Includes */ -/* Section where include file can be added */ -/* USER CODE END Includes */ - -/* Ensure stdint is only used by the compiler, and not the assembler. */ -#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) -#include -extern uint32_t SystemCoreClock; -#endif - -#define configUSE_PREEMPTION 1 -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 -#define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 0 -#define configCPU_CLOCK_HZ ( SystemCoreClock ) -#define configTICK_RATE_HZ ((TickType_t)1000) -#define configMAX_PRIORITIES ( 6 ) -#define configMINIMAL_STACK_SIZE ((uint16_t)256) -#define configTOTAL_HEAP_SIZE ((size_t)1024*14) /*Currently use about 9000*/ -#define configMAX_TASK_NAME_LEN ( 32 ) -#define configUSE_16_BIT_TICKS 0 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configUSE_TIMERS 0 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#define configCHECK_FOR_STACK_OVERFLOW 2 /*Bump this to 2 during development and bug hunting*/ - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) - -/* Set the following definitions to 1 to include the API function, or zero - to exclude the API function. */ -#define INCLUDE_vTaskPrioritySet 1 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskCleanUpResources 0 -#define INCLUDE_vTaskSuspend 0 -#define INCLUDE_vTaskDelayUntil 0 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 1 - -/* Cortex-M specific definitions. */ -#ifdef __NVIC_PRIO_BITS - /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ - #define configPRIO_BITS __NVIC_PRIO_BITS -#else -#define configPRIO_BITS 4 -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" - function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 - -/* The highest interrupt priority that can be used by any interrupt service - routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL - INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER - PRIORITY THAN THIS! (higher priorities are lower numeric values. */ -#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 - -/* Interrupt priorities used by the kernel port layer itself. These are generic - to all Cortex-M ports, and do not rely on any particular library functions. */ -#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) -/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! - See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ -#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) - -/* Normal assert() semantics without relying on the provision of an assert.h - header file. */ -/* USER CODE BEGIN 1 */ -#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} -/* USER CODE END 1 */ - -/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS - standard names. */ -#define vPortSVCHandler SVC_Handler -#define xPortPendSVHandler PendSV_Handler - -#if configUSE_TIMERS -#define configTIMER_TASK_PRIORITY 2 -#define configTIMER_QUEUE_LENGTH 8 -#define configTIMER_TASK_STACK_DEPTH (512/4) -#endif - -#endif /* FREERTOS_CONFIG_H */ From ed138d8db72463b1e65557c55b525a26a84546bd Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 28 Sep 2020 21:11:40 +1000 Subject: [PATCH 25/72] Add GPIO for QC --- workspace/TS100/Core/BSP/Pine64/Pins.h | 13 ++++++++ workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp | 33 ++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/Pins.h b/workspace/TS100/Core/BSP/Pine64/Pins.h index 42cae4c3..88b27d7f 100644 --- a/workspace/TS100/Core/BSP/Pine64/Pins.h +++ b/workspace/TS100/Core/BSP/Pine64/Pins.h @@ -35,6 +35,19 @@ #define SDA_Pin BIT(7) #define SDA_GPIO_Port GPIOB + +#define USB_DM_Pin BIT(11) +#define USB_DM_LOW_GPIO_Port GPIOA + +#define QC_DP_LOW_Pin BIT(7) +#define QC_DP_LOW_GPIO_Port GPIOA + +// LOW = low resistance, HIGH = high resistance +#define QC_DM_LOW_Pin BIT(8) +#define QC_DM_LOW_GPIO_Port GPIOA +#define QC_DM_HIGH_Pin BIT(10) +#define QC_DM_HIGH_GPIO_Port GPIOA + #define FUSB302_IRQ_Pin BIT(5) #define FUSB302_IRQ_GPIO_Port GPIOB diff --git a/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp index dfb78715..6194add0 100644 --- a/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp @@ -9,25 +9,50 @@ #include "QC3.h" #include "Settings.h" #include "gd32vf103.h" +#ifdef POW_QC void QC_DPlusZero_Six() { + // pull down D+ + gpio_bit_reset(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin); } void QC_DNegZero_Six() { + gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin); + gpio_bit_reset(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin); + } void QC_DPlusThree_Three() { + // pull up D+ + gpio_bit_set(QC_DP_LOW_GPIO_Port, QC_DP_LOW_Pin); } void QC_DNegThree_Three() { + gpio_bit_set(QC_DM_LOW_GPIO_Port, QC_DM_LOW_Pin); + gpio_bit_set(QC_DM_HIGH_GPIO_Port, QC_DM_HIGH_Pin); } void QC_DM_PullDown() { + gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, USB_DM_Pin); } void QC_DM_No_PullDown() { + gpio_init(USB_DM_LOW_GPIO_Port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_2MHZ, USB_DM_Pin); } void QC_Init_GPIO() { + // Setup any GPIO into the right states for QC + //D+ pulldown as output + gpio_init(QC_DP_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DP_LOW_Pin); + //Make two D- pins floating + QC_DM_PullDown(); } void QC_Post_Probe_En() { + //Make two D- pins outputs + gpio_init(QC_DM_LOW_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_LOW_Pin); + gpio_init(QC_DM_HIGH_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, QC_DM_HIGH_Pin); + } -uint8_t QC_DM_PulledDown() { return 0; } - +uint8_t QC_DM_PulledDown() { + return gpio_input_bit_get(USB_DM_LOW_GPIO_Port, USB_DM_Pin) == RESET ? 1 : 0; +} +#endif void QC_resync() { - //Any ongoing adjustments -} \ No newline at end of file +#ifdef POW_QC + seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much +#endif +} From 2c626d7203119bfc9ccee0a5cc57453aada0578c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Mon, 5 Oct 2020 17:34:16 +1100 Subject: [PATCH 26/72] Refactor out the sleeping timeouts --- workspace/TS100/Core/Threads/GUIThread.cpp | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index b06bb3e7..749e3d43 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -366,7 +366,25 @@ static void display_countdown(int sleepThres) { OLED::print(SymbolSeconds); } } +static uint32_t getSleepTimeout() { + if (systemSettings.sensitivity && systemSettings.SleepTime) { + uint32_t sleepThres = 0; + if (systemSettings.SleepTime < 6) + sleepThres = systemSettings.SleepTime * 10 * 1000; + else + sleepThres = (systemSettings.SleepTime - 5) * 60 * 1000; + return sleepThres; + } + return 0; +} +static bool shouldBeSleeping() { +//Return true if the iron should be in sleep mode + if ((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout() && (xTaskGetTickCount() - lastButtonTime) > getSleepTimeout()) { + return true; + } + return false; +} static void gui_solderingMode(uint8_t jumpToSleep) { /* * * Soldering (gui_solderingMode) @@ -383,11 +401,6 @@ static void gui_solderingMode(uint8_t jumpToSleep) { */ bool boostModeOn = false; - uint32_t sleepThres = 0; - if (systemSettings.SleepTime < 6) - sleepThres = systemSettings.SleepTime * 10 * 1000; - else - sleepThres = (systemSettings.SleepTime - 5) * 60 * 1000; if (jumpToSleep) { if (gui_SolderingSleepingMode(jumpToSleep == 2)) { lastButtonTime = xTaskGetTickCount(); @@ -440,7 +453,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (systemSettings.sensitivity && systemSettings.SleepTime) { OLED::print(SymbolSpace); - display_countdown(sleepThres); + display_countdown(getSleepTimeout()); } OLED::setCursor(0, 8); @@ -515,7 +528,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { #endif if (systemSettings.sensitivity && systemSettings.SleepTime) - if (xTaskGetTickCount() - lastMovementTime > sleepThres && xTaskGetTickCount() - lastButtonTime > sleepThres) { + if (shouldBeSleeping()) { if (gui_SolderingSleepingMode(false)) { return; // If the function returns non-0 then exit } From 58c4ecaea66fefa269f689351e5da12a39564d2f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 18:46:37 +1100 Subject: [PATCH 27/72] Starting hall effect support --- workspace/TS100/Core/BSP/BSP.h | 4 +++ .../TS100/Core/BSP/Pine64/Model_Config.h | 3 +- workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 15 ++++++++ workspace/TS100/Core/Drivers/Si7210.cpp | 35 +++++++++++++++++++ workspace/TS100/Core/Drivers/Si7210.h | 21 +++++++++++ workspace/TS100/Core/Drivers/Si7210_defines.h | 19 ++++++++++ workspace/TS100/Core/Inc/Settings.h | 3 +- workspace/TS100/Core/Threads/GUIThread.cpp | 5 +++ 8 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 workspace/TS100/Core/Drivers/Si7210.cpp create mode 100644 workspace/TS100/Core/Drivers/Si7210.h create mode 100644 workspace/TS100/Core/Drivers/Si7210_defines.h diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index f1765c0f..74844887 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -51,6 +51,10 @@ uint8_t showBootLogoIfavailable(); void delay_ms(uint16_t count) ; //Used to allow knowledge of if usb_pd is being used uint8_t usb_pd_detect(); +// If the iron has a hall effect sensor in the handle, return an signed count of the reading +// If the sensor is single polarity (or polarity insensitive) just return 0..32768 +int16_t getRawHallEffect(); + #ifdef __cplusplus } diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 2abb9142..2c6a0c84 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -20,7 +20,8 @@ #define POW_QC #define TEMP_TMP36 #define ACCEL_BMA - +#define HALL_SENSOR +#define HALL_SI7210 #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp index d0022011..5914270f 100644 --- a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -9,10 +9,25 @@ #include "task.h" #include "I2C_Wrapper.hpp" #include "fusbpd.h" +#include "Si7210.h" + +bool hall_effect_present = false; void postRToSInit() { // Any after RTos setup #ifdef POW_PD //Spawn all of the USB-C processors fusb302_start_processing(); #endif +#ifdef HALL_SI7210 + if (Si7210::detect()) { + hall_effect_present = Si7210::init(); + } +#endif +} +int16_t getRawHallEffect() { + if (hall_effect_present) { + return Si7210::read(); + } + return 0; + } diff --git a/workspace/TS100/Core/Drivers/Si7210.cpp b/workspace/TS100/Core/Drivers/Si7210.cpp new file mode 100644 index 00000000..63bf4936 --- /dev/null +++ b/workspace/TS100/Core/Drivers/Si7210.cpp @@ -0,0 +1,35 @@ +/* + * Si7210.cpp + * + * Created on: 5 Oct. 2020 + * Author: Ralim + */ + +#include +#include "Si7210_defines.h" +#include "I2C_Wrapper.hpp" +bool Si7210::detect() { + return FRToSI2C::probe(SI7210_ADDRESS); +} + +bool Si7210::init() { + //Turn on auto increment and sanity check ID + uint8_t temp; + if (FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_ID, &temp, 1)) { + // We don't really care what model it is etc, just probing to check its probably this iC + if (temp != 0x00 && temp != 0xFF) { + temp = 0x01; //turn on auto increment + if (FRToSI2C::Mem_Write(SI7210_ADDRESS, SI7210_REG_INCR, &temp, 1)) { + return true; + } + } + } + return false; +} + +int16_t Si7210::read() { + //Read the two regs + int16_t temp = 0; + FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_DATAH,(uint8_t*) &temp, 2); + return __builtin_bswap16(temp); +} diff --git a/workspace/TS100/Core/Drivers/Si7210.h b/workspace/TS100/Core/Drivers/Si7210.h new file mode 100644 index 00000000..5f0477b5 --- /dev/null +++ b/workspace/TS100/Core/Drivers/Si7210.h @@ -0,0 +1,21 @@ +/* + * Si7210.h + * + * Created on: 5 Oct. 2020 + * Author: Ralim + */ + +#ifndef CORE_DRIVERS_SI7210_H_ +#define CORE_DRIVERS_SI7210_H_ +#include +class Si7210 { +public: + //Return true if present + static bool detect(); + + static bool init(); + static int16_t read(); +private: +}; + +#endif /* CORE_DRIVERS_SI7210_H_ */ diff --git a/workspace/TS100/Core/Drivers/Si7210_defines.h b/workspace/TS100/Core/Drivers/Si7210_defines.h new file mode 100644 index 00000000..3a7dc13d --- /dev/null +++ b/workspace/TS100/Core/Drivers/Si7210_defines.h @@ -0,0 +1,19 @@ +/* + * Si7210_defines.h + * + * Created on: 5 Oct. 2020 + * Author: Ralim + */ + +#ifndef CORE_DRIVERS_SI7210_DEFINES_H_ +#define CORE_DRIVERS_SI7210_DEFINES_H_ + +#define SI7210_ADDRESS (0x30<<1) +#define SI7210_REG_ID 0xC0 +#define SI7210_REG_DATAH 0xC1 +#define SI7210_REG_DATAL 0xC2 +#define SI7210_REG_INCR 0xC5 + + + +#endif /* CORE_DRIVERS_SI7210_DEFINES_H_ */ diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index 08e4b830..6ade2cfb 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -54,7 +54,8 @@ typedef struct { uint8_t ReverseButtonTempChangeEnabled; // Change the plus and minus button assigment uint16_t TempChangeLongStep; // Change the plus and minus button assigment uint16_t TempChangeShortStep; // Change the plus and minus button assigment - + uint8_t hallEffectMode; //Operating mode of the hall effect sensor + int16_t hallEffectThreshold; //Threshold of the halleffect sensor uint32_t padding; // This is here for in case we are not an even divisor so // that nothing gets cut off //MUST BE LAST diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 749e3d43..9f5e47f0 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -383,6 +383,11 @@ static bool shouldBeSleeping() { if ((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout() && (xTaskGetTickCount() - lastButtonTime) > getSleepTimeout()) { return true; } +#ifdef HALL_SENSOR +//If the hall effect sensor is enabled in the build, check if its over threshold, and if so then we force sleep + + +#endif return false; } static void gui_solderingMode(uint8_t jumpToSleep) { From 03afdcdf205fddbba2a5d5702ff52d48e4da2fe4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 18:55:09 +1100 Subject: [PATCH 28/72] Update push.yml --- .github/workflows/push.yml | 111 ++++++++++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 15 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index d4a34454..6d1a9f32 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,22 +1,103 @@ -name: CI Push +name: CI PR -on: [push] +on: [pull_request] jobs: - build: - runs-on: ubuntu-latest + build_TS80: + + runs-on: ubuntu-latest + steps: - uses: actions/checkout@v2 + - name: chmod - run: chmod +x build.sh - - name: translation - run: | - cd Translation\ Editor - python3 make_translation.py - - name: make - run: ./build.sh -l EN - - name: Archive production artifacts - uses: actions/upload-artifact@v1 + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + + - name: setup + run: ./setup.sh + + - name: build TS80 + run: cd workspace/TS100 && ./build.sh -m TS80 + + - name: Archive TS80 artifacts + uses: actions/upload-artifact@v2 with: - name: compiled - path: ci/artefacts + name: TS80 + path: | + workspace/TS100/Hexfile/TS80_*.hex + workspace/TS100/Hexfile/TS80_*.bin + if-no-files-found: error + build_TS80P: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + + - name: setup + run: ./setup.sh + + - name: build TS80P + run: cd workspace/TS100 && ./build.sh -m TS80P + + - name: Archive TS80P artifacts + uses: actions/upload-artifact@v2 + with: + name: TS80P + path: | + workspace/TS100/Hexfile/TS80P_*.hex + workspace/TS100/Hexfile/TS80P_*.bin + if-no-files-found: error + build_TS100: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + + - name: setup + run: ./setup.sh + + - name: build TS100 + run: cd workspace/TS100 && ./build.sh -m TS100 + + - name: Archive TS100 artifacts + uses: actions/upload-artifact@v2 + with: + name: TS100 + path: | + workspace/TS100/Hexfile/TS100_*.hex + workspace/TS100/Hexfile/TS100_*.bin + if-no-files-found: error + + build_Pinecil: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + + - name: setup + run: ./setup.sh + + - name: build Pinecil + run: cd workspace/TS100 && ./build.sh -m Pinecil + + - name: Archive Pinecil artifacts + uses: actions/upload-artifact@v2 + with: + name: Pinecil + path: | + workspace/TS100/Hexfile/Pinecil_*.hex + workspace/TS100/Hexfile/Pinecil_*.bin + if-no-files-found: error + \ No newline at end of file From 2e4168be7324bef6dbf75569f12fc23978bf4300 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 19:04:16 +1100 Subject: [PATCH 29/72] Bulk format --- workspace/TS100/Core/BSP/Miniware/BSP.cpp | 237 +++++----- .../TS100/Core/BSP/Miniware/I2C_Wrapper.cpp | 116 ++--- workspace/TS100/Core/BSP/Miniware/IRQ.cpp | 2 +- workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp | 84 ++-- workspace/TS100/Core/BSP/Miniware/Setup.c | 2 +- .../TS100/Core/BSP/Miniware/Software_I2C.h | 2 - workspace/TS100/Core/BSP/Miniware/flash.c | 6 +- .../TS100/Core/BSP/Miniware/fusb302b.cpp | 24 +- workspace/TS100/Core/BSP/Miniware/logo.cpp | 3 +- workspace/TS100/Core/BSP/Miniware/port.c | 426 ++++++++---------- workspace/TS100/Core/BSP/Miniware/portmacro.h | 114 +++-- .../Core/BSP/Miniware/stm32f1xx_hal_msp.c | 7 +- .../BSP/Miniware/stm32f1xx_hal_timebase_TIM.c | 252 +++++------ .../TS100/Core/BSP/Miniware/stm32f1xx_it.c | 2 +- .../Core/BSP/Miniware/system_stm32f1xx.c | 263 ++++++----- 15 files changed, 730 insertions(+), 810 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/BSP.cpp b/workspace/TS100/Core/BSP/Miniware/BSP.cpp index 030cbf2a..d5e5bdcd 100644 --- a/workspace/TS100/Core/BSP/Miniware/BSP.cpp +++ b/workspace/TS100/Core/BSP/Miniware/BSP.cpp @@ -21,92 +21,88 @@ uint16_t totalPWM; //htim2.Init.Period, the full PWM cycle static bool fastPWM; //2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = {{0}, 0, 0}; -void resetWatchdog() -{ +history rawTempFilter = { { 0 }, 0, 0 }; +void resetWatchdog() { HAL_IWDG_Refresh(&hiwdg); } #ifdef TEMP_NTC //Lookup table for the NTC //Stored as ADCReading,Temp in degC static const uint16_t NTCHandleLookup[] = { - //ADC Reading , Temp in C - 29189, 0, // - 29014, 1, // - 28832, 2, // - 28644, 3, // - 28450, 4, // - 28249, 5, // - 28042, 6, // - 27828, 7, // - 27607, 8, // - 27380, 9, // - 27146, 10, // - 26906, 11, // - 26660, 12, // - 26407, 13, // - 26147, 14, // - 25882, 15, // - 25610, 16, // - 25332, 17, // - 25049, 18, // - 24759, 19, // - 24465, 20, // - 24164, 21, // - 23859, 22, // - 23549, 23, // - 23234, 24, // - 22915, 25, // - 22591, 26, // - 22264, 27, // - 21933, 28, // - 21599, 29, // - // 21261, 30, // - // 20921, 31, // - // 20579, 32, // - // 20234, 33, // - // 19888, 34, // - // 19541, 35, // - // 19192, 36, // - // 18843, 37, // - // 18493, 38, // - // 18143, 39, // - // 17793, 40, // - // 17444, 41, // - // 17096, 42, // - // 16750, 43, // - // 16404, 44, // - // 16061, 45, // - // 15719, 46, // - // 15380, 47, // - // 15044, 48, // - // 14710, 49, // - // 14380, 50, // - // 14053, 51, // - // 13729, 52, // - // 13410, 53, // - // 13094, 54, // - // 12782, 55, // - // 12475, 56, // - // 12172, 57, // - // 11874, 58, // - // 11580, 59, // - // 11292, 60, // -}; +//ADC Reading , Temp in C + 29189, 0, // + 29014, 1, // + 28832, 2, // + 28644, 3, // + 28450, 4, // + 28249, 5, // + 28042, 6, // + 27828, 7, // + 27607, 8, // + 27380, 9, // + 27146, 10, // + 26906, 11, // + 26660, 12, // + 26407, 13, // + 26147, 14, // + 25882, 15, // + 25610, 16, // + 25332, 17, // + 25049, 18, // + 24759, 19, // + 24465, 20, // + 24164, 21, // + 23859, 22, // + 23549, 23, // + 23234, 24, // + 22915, 25, // + 22591, 26, // + 22264, 27, // + 21933, 28, // + 21599, 29, // + // 21261, 30, // + // 20921, 31, // + // 20579, 32, // + // 20234, 33, // + // 19888, 34, // + // 19541, 35, // + // 19192, 36, // + // 18843, 37, // + // 18493, 38, // + // 18143, 39, // + // 17793, 40, // + // 17444, 41, // + // 17096, 42, // + // 16750, 43, // + // 16404, 44, // + // 16061, 45, // + // 15719, 46, // + // 15380, 47, // + // 15044, 48, // + // 14710, 49, // + // 14380, 50, // + // 14053, 51, // + // 13729, 52, // + // 13410, 53, // + // 13094, 54, // + // 12782, 55, // + // 12475, 56, // + // 12172, 57, // + // 11874, 58, // + // 11580, 59, // + // 11292, 60, // + }; #endif -uint16_t getHandleTemperature() -{ +uint16_t getHandleTemperature() { #ifdef TEMP_NTC //TS80P uses 100k NTC resistors instead //NTCG104EF104FT1X from TDK //For now not doing interpolation int32_t result = getADC(0); for (uint32_t i = 0; i < (sizeof(NTCHandleLookup) / (2 * sizeof(uint16_t))); - i++) - { - if (result > NTCHandleLookup[(i * 2) + 0]) - { + i++) { + if (result > NTCHandleLookup[(i * 2) + 0]) { return NTCHandleLookup[(i * 2) + 1] * 10; } } @@ -130,8 +126,7 @@ uint16_t getHandleTemperature() #endif } -uint16_t getTipInstantTemperature() -{ +uint16_t getTipInstantTemperature() { uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits uint16_t readings[8]; //Looking to reject the highest outlier readings. @@ -146,29 +141,23 @@ uint16_t getTipInstantTemperature() readings[6] = hadc2.Instance->JDR3; readings[7] = hadc2.Instance->JDR4; - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < 8; i++) { sum += readings[i]; } return sum; // 8x over sample } -uint16_t getTipRawTemp(uint8_t refresh) -{ - if (refresh) - { +uint16_t getTipRawTemp(uint8_t refresh) { + if (refresh) { uint16_t lastSample = getTipInstantTemperature(); rawTempFilter.update(lastSample); return lastSample; - } - else - { + } else { return rawTempFilter.average(); } } -uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) -{ +uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { // ADC maximum is 32767 == 3.3V at input == 28.05V at VIN // Therefore we can divide down from there // Multiplying ADC max by 4 for additional calibration options, @@ -182,14 +171,12 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; static uint8_t index = 0; - if (preFillneeded) - { + if (preFillneeded) { for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) samples[i] = getADC(1); preFillneeded--; } - if (sample) - { + if (sample) { samples[index] = getADC(1); index = (index + 1) % BATTFILTERDEPTH; } @@ -199,23 +186,20 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) sum += samples[i]; sum /= BATTFILTERDEPTH; - if (divisor == 0) - { + if (divisor == 0) { divisor = 1; } return sum * 4 / divisor; } -void setTipPWM(uint8_t pulse) -{ +void setTipPWM(uint8_t pulse) { PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is // disabled if the PID task is not scheduled often enough. pendingPWM = pulse; } -static void switchToFastPWM(void) -{ +static void switchToFastPWM(void) { fastPWM = true; totalPWM = powerPWM + tempMeasureTicks * 2; htim2.Instance->ARR = totalPWM; @@ -225,8 +209,7 @@ static void switchToFastPWM(void) htim2.Instance->PSC = 2000; } -static void switchToSlowPWM(void) -{ +static void switchToSlowPWM(void) { fastPWM = false; totalPWM = powerPWM + tempMeasureTicks; htim2.Instance->ARR = totalPWM; @@ -236,16 +219,12 @@ static void switchToSlowPWM(void) htim2.Instance->PSC = 4000; } -bool tryBetterPWM(uint8_t pwm) -{ - if (fastPWM && pwm == powerPWM) - { +bool tryBetterPWM(uint8_t pwm) { + if (fastPWM && pwm == powerPWM) { // maximum power for fast PWM reached, need to go slower to get more switchToSlowPWM(); return true; - } - else if (!fastPWM && pwm < 230) - { + } else if (!fastPWM && pwm < 230) { // 254 in fast PWM mode gives the same power as 239 in slow // allow for some reasonable hysteresis by switching only when it goes // below 230 (equivalent to 245 in fast mode) @@ -258,11 +237,9 @@ bool tryBetterPWM(uint8_t pwm) // These are called by the HAL after the corresponding events from the system // timers. -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { // Period has elapsed - if (htim->Instance == TIM2) - { + if (htim->Instance == TIM2) { // we want to turn on the output again PWMSafetyTimer--; // We decrement this safety value so that lockups in the @@ -271,32 +248,24 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) // While we could assume this could never happen, its a small price for // increased safety htim2.Instance->CCR4 = pendingPWM; - if (htim2.Instance->CCR4 && PWMSafetyTimer) - { + if (htim2.Instance->CCR4 && PWMSafetyTimer) { HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); - } - else - { + } else { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } - } - else if (htim->Instance == TIM1) - { + } else if (htim->Instance == TIM1) { // STM uses this for internal functions as a counter for timeouts HAL_IncTick(); } } -void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) -{ +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { // This was a when the PWM for the output has timed out - if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) - { + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) { HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1); } } -void unstick_I2C() -{ +void unstick_I2C() { GPIO_InitTypeDef GPIO_InitStruct; int timeout = 100; int timeout_cnt = 0; @@ -320,8 +289,7 @@ void unstick_I2C() HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct); HAL_GPIO_WritePin(SDA_GPIO_Port, SDA_Pin, GPIO_PIN_SET); - while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) - { + while (GPIO_PIN_SET != HAL_GPIO_ReadPin(SDA_GPIO_Port, SDA_Pin)) { //Move clock to release I2C HAL_GPIO_WritePin(SCL_GPIO_Port, SCL_Pin, GPIO_PIN_RESET); asm("nop"); @@ -366,26 +334,23 @@ void unstick_I2C() HAL_I2C_Init(&hi2c1); } -uint8_t getButtonA() -{ - return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? 1 : 0; +uint8_t getButtonA() { + return HAL_GPIO_ReadPin(KEY_A_GPIO_Port, KEY_A_Pin) == GPIO_PIN_RESET ? + 1 : 0; } -uint8_t getButtonB() -{ - return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? 1 : 0; +uint8_t getButtonB() { + return HAL_GPIO_ReadPin(KEY_B_GPIO_Port, KEY_B_Pin) == GPIO_PIN_RESET ? + 1 : 0; } -void BSPInit(void) -{ +void BSPInit(void) { switchToFastPWM(); } -void reboot() -{ +void reboot() { NVIC_SystemReset(); } -void delay_ms(uint16_t count) -{ +void delay_ms(uint16_t count) { HAL_Delay(count); } diff --git a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp index d819646e..e4fc3307 100644 --- a/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Miniware/I2C_Wrapper.cpp @@ -11,89 +11,97 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; void FRToSI2C::CpltCallback() { - hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) - if (I2CSemaphore) { - xSemaphoreGiveFromISR(I2CSemaphore, NULL); - } + hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error) + if (I2CSemaphore) { + xSemaphoreGiveFromISR(I2CSemaphore, NULL); + } } -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (!lock()) + return false; + if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, + pData, Size, 500) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } + I2C_Unstick(); + unlock(); + return false; + } - unlock(); - return true; + unlock(); + return true; } bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - return Mem_Write(address, reg, &data, 1); + return Mem_Write(address, reg, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t tx_data[1]; - Mem_Read(add, reg, tx_data, 1); - return tx_data[0]; + uint8_t tx_data[1]; + Mem_Read(add, reg, tx_data, 1); + return tx_data[0]; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) { +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) { + if (!lock()) + return false; + if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, + pData, Size, 500) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } + I2C_Unstick(); + unlock(); + return false; + } - unlock(); - return true; + unlock(); + return true; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - if (!lock()) - return false; - if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) != HAL_OK) { - I2C_Unstick(); - unlock(); - return false; - } - return true; + if (!lock()) + return false; + if (HAL_I2C_Master_Transmit_DMA(&hi2c1, DevAddress, pData, Size) + != HAL_OK) { + I2C_Unstick(); + unlock(); + return false; + } + return true; } bool FRToSI2C::probe(uint16_t DevAddress) { - if (!lock()) - return false; - uint8_t buffer[1]; - bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; - unlock(); - return worked; + if (!lock()) + return false; + uint8_t buffer[1]; + bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, + I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK; + unlock(); + return worked; } void FRToSI2C::I2C_Unstick() { - unstick_I2C(); + unstick_I2C(); } void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); + xSemaphoreGive(I2CSemaphore); } bool FRToSI2C::lock() { - return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; + return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; } -bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) - delay_ms(registers[index].pause_ms); - } - return true; +bool FRToSI2C::writeRegistersBulk(const uint8_t address, + const I2C_REG *registers, const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, + registers[index].val)) { + return false; + } + if (registers[index].pause_ms) + delay_ms(registers[index].pause_ms); + } + return true; } diff --git a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp index fe7b4b15..e480c2ba 100644 --- a/workspace/TS100/Core/BSP/Miniware/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Miniware/IRQ.cpp @@ -44,6 +44,6 @@ void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { - (void)GPIO_Pin; + (void) GPIO_Pin; InterruptHandler::irqCallback(); } diff --git a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp index a4bba7db..5f9dee75 100644 --- a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp @@ -12,65 +12,67 @@ #include "Model_Config.h" #ifdef POW_QC void QC_DPlusZero_Six() { - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // pull down D+ } void QC_DNegZero_Six() { - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); } void QC_DPlusThree_Three() { - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); // pull up D+ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); // pull up D+ } void QC_DNegThree_Three() { - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); } void QC_DM_PullDown() { - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLDOWN; - GPIO_InitStruct.Pin = GPIO_PIN_11; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Pin = GPIO_PIN_11; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void QC_DM_No_PullDown() { - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Pin = GPIO_PIN_11; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pin = GPIO_PIN_11; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void QC_Init_GPIO() { - // Setup any GPIO into the right states for QC - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Pin = GPIO_PIN_3; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - // Turn off output mode on pins that we can - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + // Setup any GPIO into the right states for QC + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + // Turn off output mode on pins that we can + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void QC_Post_Probe_En() { - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } -uint8_t QC_DM_PulledDown() { return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; } +uint8_t QC_DM_PulledDown() { + return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == GPIO_PIN_RESET ? 1 : 0; +} #endif void QC_resync() { #ifdef POW_QC - seekQC((systemSettings.cutoutSetting) ? 120 : 90, - systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much + seekQC((systemSettings.cutoutSetting) ? 120 : 90, + systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif } diff --git a/workspace/TS100/Core/BSP/Miniware/Setup.c b/workspace/TS100/Core/BSP/Miniware/Setup.c index 515b4a59..1ecc25a5 100644 --- a/workspace/TS100/Core/BSP/Miniware/Setup.c +++ b/workspace/TS100/Core/BSP/Miniware/Setup.c @@ -323,7 +323,7 @@ static void MX_TIM2_Init(void) { htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // dummy value, will be reconfigured by BSPInit() htim2.Init.Period = 255 + 17 * 2; - htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 8 MHz (x2 APB1) before divide + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4; // 8 MHz (x2 APB1) before divide htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; htim2.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim2); diff --git a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h index 9fc62d5d..73084261 100644 --- a/workspace/TS100/Core/BSP/Miniware/Software_I2C.h +++ b/workspace/TS100/Core/BSP/Miniware/Software_I2C.h @@ -22,6 +22,4 @@ #endif - - #endif /* BSP_MINIWARE_SOFTWARE_I2C_H_ */ diff --git a/workspace/TS100/Core/BSP/Miniware/flash.c b/workspace/TS100/Core/BSP/Miniware/flash.c index 7559f23e..ba429dd4 100644 --- a/workspace/TS100/Core/BSP/Miniware/flash.c +++ b/workspace/TS100/Core/BSP/Miniware/flash.c @@ -17,7 +17,7 @@ uint8_t flash_save_buffer(const uint8_t *buffer, const uint16_t length) { pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES; pEraseInit.Banks = FLASH_BANK_1; pEraseInit.NbPages = 1; - pEraseInit.PageAddress = (uint32_t)settings_page; + pEraseInit.PageAddress = (uint32_t) settings_page; uint32_t failingAddress = 0; resetWatchdog(); __HAL_FLASH_CLEAR_FLAG( @@ -33,8 +33,8 @@ uint8_t flash_save_buffer(const uint8_t *buffer, const uint16_t length) { HAL_FLASH_Unlock(); for (uint8_t i = 0; i < (length / 2); i++) { resetWatchdog(); - HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, (uint32_t)&settings_page[i], - data[i]); + HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, + (uint32_t) &settings_page[i], data[i]); } HAL_FLASH_Lock(); return 1; diff --git a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp index 7ff579f6..fda41003 100644 --- a/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp +++ b/workspace/TS100/Core/BSP/Miniware/fusb302b.cpp @@ -78,16 +78,16 @@ void fusb_send_message(const union pd_msg *msg) { } /* Token sequences for the FUSB302B */ static uint8_t sop_seq[5] = { - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP1, - FUSB_FIFO_TX_SOP2, - FUSB_FIFO_TX_PACKSYM}; + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP1, + FUSB_FIFO_TX_SOP2, + FUSB_FIFO_TX_PACKSYM }; static const uint8_t eop_seq[4] = { - FUSB_FIFO_TX_JAM_CRC, - FUSB_FIFO_TX_EOP, - FUSB_FIFO_TX_TXOFF, - FUSB_FIFO_TX_TXON}; + FUSB_FIFO_TX_JAM_CRC, + FUSB_FIFO_TX_EOP, + FUSB_FIFO_TX_TXOFF, + FUSB_FIFO_TX_TXON }; /* Take the I2C2 mutex now so there can't be a race condition on sop_seq */ /* Get the length of the message: a two-octet header plus NUMOBJ four-octet @@ -170,7 +170,7 @@ bool fusb_setup() { fusb_write_byte( FUSB_CONTROL2, 0x00); /* Flush the RX buffer */ fusb_write_byte( FUSB_CONTROL1, - FUSB_CONTROL1_RX_FLUSH); + FUSB_CONTROL1_RX_FLUSH); /* Measure CC1 */ fusb_write_byte( FUSB_SWITCHES0, 0x07); @@ -226,7 +226,7 @@ enum fusb_typec_current fusb_get_typec_current() { } /* Read the BC_LVL into a variable */ enum fusb_typec_current bc_lvl = (enum fusb_typec_current) (fusb_read_byte( - FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); + FUSB_STATUS0) & FUSB_STATUS0_BC_LVL); if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { I2CBB::unlock2(); } @@ -256,7 +256,7 @@ bool fusb_read_id() { uint8_t version = 0; fusb_read_buf(FUSB_DEVICE_ID, 1, &version); if (version == 0 || version == 0xFF) - return false; + return false; return true; } uint8_t fusb302_detect() { diff --git a/workspace/TS100/Core/BSP/Miniware/logo.cpp b/workspace/TS100/Core/BSP/Miniware/logo.cpp index b0ad3cb4..e1a0f925 100644 --- a/workspace/TS100/Core/BSP/Miniware/logo.cpp +++ b/workspace/TS100/Core/BSP/Miniware/logo.cpp @@ -15,8 +15,7 @@ static uint8_t logo_page[1024] __attribute__ ((section (".logo_page"))); uint8_t showBootLogoIfavailable() { // Do not show logo data if signature is not found. - if (LOGO_HEADER_VALUE - != *(reinterpret_cast(logo_page))) { + if (LOGO_HEADER_VALUE != *(reinterpret_cast(logo_page))) { return 0; } diff --git a/workspace/TS100/Core/BSP/Miniware/port.c b/workspace/TS100/Core/BSP/Miniware/port.c index 53592606..5b742f0f 100644 --- a/workspace/TS100/Core/BSP/Miniware/port.c +++ b/workspace/TS100/Core/BSP/Miniware/port.c @@ -34,16 +34,16 @@ #include "task.h" /* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is -defined. The value should also ensure backward compatibility. -FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ + defined. The value should also ensure backward compatibility. + FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ #ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 255 +#define configKERNEL_INTERRUPT_PRIORITY 255 #endif #ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ +/* Ensure the SysTick is clocked at the same frequency as the core. */ +#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #else /* The way the SysTick is clocked is not modified in case it is not the same as the core. */ @@ -85,21 +85,21 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ #define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /* A fiddle factor to estimate the number of SysTick counts that would have -occurred while the SysTick counter is stopped during tickless idle -calculations. */ + occurred while the SysTick counter is stopped during tickless idle + calculations. */ #define portMISSED_COUNTS_FACTOR ( 45UL ) /* For strict compliance with the Cortex-M spec the task start address should -have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ + have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ #define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /* Let the user override the pre-loading of the initial LR with the address of -prvTaskExitError() in case it messes up unwinding of the stack in the -debugger. */ + prvTaskExitError() in case it messes up unwinding of the stack in the + debugger. */ #ifdef configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError +#define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* @@ -107,29 +107,29 @@ debugger. */ * file is weak to allow application writers to change the timer used to * generate the tick interrupt. */ -void vPortSetupTimerInterrupt( void ); +void vPortSetupTimerInterrupt(void); /* * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__ (( naked )); +void xPortPendSVHandler(void) __attribute__ (( naked )); +void xPortSysTickHandler(void); +void vPortSVCHandler(void) __attribute__ (( naked )); /* * Start first task is a separate function so it can be tested in isolation. */ -static void prvPortStartFirstTask( void ) __attribute__ (( naked )); +static void prvPortStartFirstTask(void) __attribute__ (( naked )); /* * Used to catch tasks that attempt to return from their implementing function. */ -static void prvTaskExitError( void ); +static void prvTaskExitError(void); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. */ + variable. */ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* @@ -161,9 +161,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ #if( configASSERT_DEFINED == 1 ) - static uint8_t ucMaxSysCallPriority = 0; - static uint32_t ulMaxPRIGROUPValue = 0; - static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16; +static uint8_t ucMaxSysCallPriority = 0; +static uint32_t ulMaxPRIGROUPValue = 0; +static const volatile uint8_t *const pcInterruptPriorityRegisters = + (const volatile uint8_t* const ) portNVIC_IP_REGISTERS_OFFSET_16; #endif /* configASSERT_DEFINED */ /*-----------------------------------------------------------*/ @@ -171,129 +172,126 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) -{ +StackType_t* pxPortInitialiseStack(StackType_t *pxTopOfStack, + TaskFunction_t pxCode, void *pvParameters) { /* Simulate the stack frame as it would be created by a context switch - interrupt. */ + interrupt. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ pxTopOfStack--; - *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ + *pxTopOfStack = ((StackType_t) pxCode) & portSTART_ADDRESS_MASK; /* PC */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + *pxTopOfStack = (StackType_t) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = (StackType_t) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ return pxTopOfStack; } /*-----------------------------------------------------------*/ -static void prvTaskExitError( void ) -{ -volatile uint32_t ulDummy = 0UL; +static void prvTaskExitError(void) { + volatile uint32_t ulDummy = 0UL; /* A function that implements a task must not exit or attempt to return to - its caller as there is nothing to return to. If a task wants to exit it - should instead call vTaskDelete( NULL ). + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). - Artificially force an assert() to be triggered if configASSERT() is - defined, then stop here so application writers can catch the error. */ - configASSERT( uxCriticalNesting == ~0UL ); + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT(uxCriticalNesting == ~0UL); portDISABLE_INTERRUPTS(); - while( ulDummy == 0 ) - { + while (ulDummy == 0) { /* This file calls prvTaskExitError() after the scheduler has been - started to remove a compiler warning about the function being defined - but never called. ulDummy is used purely to quieten other warnings - about code appearing after this function is called - making ulDummy - volatile makes the compiler think the function could return and - therefore not output an 'unreachable code' warning for code that appears - after it. */ + started to remove a compiler warning about the function being defined + but never called. ulDummy is used purely to quieten other warnings + about code appearing after this function is called - making ulDummy + volatile makes the compiler think the function could return and + therefore not output an 'unreachable code' warning for code that appears + after it. */ } } /*-----------------------------------------------------------*/ -void vPortSVCHandler( void ) -{ +void vPortSVCHandler(void) { __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " isb \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " orr r14, #0xd \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " orr r14, #0xd \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ -static void prvPortStartFirstTask( void ) -{ +static void prvPortStartFirstTask(void) { __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc 0 \n" /* System call to start first task. */ - " nop \n" - ); + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); } /*-----------------------------------------------------------*/ /* * See header file for description. */ -BaseType_t xPortStartScheduler( void ) -{ +BaseType_t xPortStartScheduler(void) { /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. - See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ - configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT(configMAX_SYSCALL_INTERRUPT_PRIORITY); - #if( configASSERT_DEFINED == 1 ) +#if( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t *const pucFirstUserPriorityRegister = + (volatile uint8_t* const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + + portFIRST_USER_INTERRUPT_NUMBER); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API - functions can be called. ISR safe functions are those that end in - "FromISR". FreeRTOS maintains separate thread and ISR API functions to - ensure interrupt entry is as fast and simple as possible. + functions can be called. ISR safe functions are those that end in + "FromISR". FreeRTOS maintains separate thread and ISR API functions to + ensure interrupt entry is as fast and simple as possible. - Save the interrupt priority value that is about to be clobbered. */ + Save the interrupt priority value that is about to be clobbered. */ ulOriginalPriority = *pucFirstUserPriorityRegister; /* Determine the number of priority bits available. First write to all - possible bits. */ + possible bits. */ *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; /* Read the value back to see how many bits stuck. */ ucMaxPriorityValue = *pucFirstUserPriorityRegister; /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY + & ucMaxPriorityValue; /* Calculate the maximum acceptable priority group value for the number - of bits read back. */ + of bits read back. */ ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; - while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) - { + while ((ucMaxPriorityValue & portTOP_BIT_OF_BYTE) == portTOP_BIT_OF_BYTE) { ulMaxPRIGROUPValue--; - ucMaxPriorityValue <<= ( uint8_t ) 0x01; + ucMaxPriorityValue <<= (uint8_t) 0x01; } - #ifdef __NVIC_PRIO_BITS +#ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of priority bits matches the number of priority bits actually queried @@ -302,7 +300,7 @@ BaseType_t xPortStartScheduler( void ) } #endif - #ifdef configPRIO_BITS +#ifdef configPRIO_BITS { /* Check the FreeRTOS configuration that defines the number of priority bits matches the number of priority bits actually queried @@ -312,22 +310,22 @@ BaseType_t xPortStartScheduler( void ) #endif /* Shift the priority group value back to its position within the AIRCR - register. */ + register. */ ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; /* Restore the clobbered interrupt priority register to its original - value. */ + value. */ *pucFirstUserPriorityRegister = ulOriginalPriority; } - #endif /* conifgASSERT_DEFINED */ +#endif /* conifgASSERT_DEFINED */ /* Make PendSV and SysTick the lowest priority interrupts. */ portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ + here already. */ vPortSetupTimerInterrupt(); /* Initialise the critical nesting count ready for the first task. */ @@ -337,11 +335,11 @@ BaseType_t xPortStartScheduler( void ) prvPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task - exit error function to prevent compiler warnings about a static function - not being called in the case that the application writer overrides this - functionality by defining configTASK_RETURN_ADDRESS. Call - vTaskSwitchContext() so link time optimisation does not remove the - symbol. */ + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. Call + vTaskSwitchContext() so link time optimisation does not remove the + symbol. */ vTaskSwitchContext(); prvTaskExitError(); @@ -350,92 +348,84 @@ BaseType_t xPortStartScheduler( void ) } /*-----------------------------------------------------------*/ -void vPortEndScheduler( void ) -{ +void vPortEndScheduler(void) { /* Not implemented in ports where there is nothing to return to. - Artificially force an assert. */ - configASSERT( uxCriticalNesting == 1000UL ); + Artificially force an assert. */ + configASSERT(uxCriticalNesting == 1000UL); } /*-----------------------------------------------------------*/ -void vPortEnterCritical( void ) -{ +void vPortEnterCritical(void) { portDISABLE_INTERRUPTS(); uxCriticalNesting++; /* This is not the interrupt safe version of the enter critical function so - assert() if it is being called from an interrupt context. Only API - functions that end in "FromISR" can be used in an interrupt. Only assert if - the critical nesting count is 1 to protect against recursive calls if the - assert function also uses a critical section. */ - if( uxCriticalNesting == 1 ) - { - configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + assert() if it is being called from an interrupt context. Only API + functions that end in "FromISR" can be used in an interrupt. Only assert if + the critical nesting count is 1 to protect against recursive calls if the + assert function also uses a critical section. */ + if (uxCriticalNesting == 1) { + configASSERT(( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0); } } /*-----------------------------------------------------------*/ -void vPortExitCritical( void ) -{ - configASSERT( uxCriticalNesting ); +void vPortExitCritical(void) { + configASSERT(uxCriticalNesting); uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { + if (uxCriticalNesting == 0) { portENABLE_INTERRUPTS(); } } /*-----------------------------------------------------------*/ -void xPortPendSVHandler( void ) -{ +void xPortPendSVHandler(void) { /* This is a naked function. */ __asm volatile ( - " mrs r0, psp \n" - " isb \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r3, r14} \n" - " mov r0, %0 \n" - " msr basepri, r0 \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r3, r14} \n" - " \n" /* Restore the context, including the critical nesting count. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ - " msr psp, r0 \n" - " isb \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n" /* Restore the context, including the critical nesting count. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ + " msr psp, r0 \n" + " isb \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ); } /*-----------------------------------------------------------*/ -void xPortSysTickHandler( void ) -{ +void xPortSysTickHandler(void) { /* The SysTick runs at the lowest interrupt priority, so when this interrupt - executes all interrupts must be unmasked. There is therefore no need to - save and then restore the interrupt mask value as its value is already - known. */ + executes all interrupts must be unmasked. There is therefore no need to + save and then restore the interrupt mask value as its value is already + known. */ portDISABLE_INTERRUPTS(); { /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { + if (xTaskIncrementTick() != pdFALSE) { /* A context switch is required. Context switching is performed in - the PendSV interrupt. Pend the PendSV interrupt. */ + the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } @@ -614,10 +604,9 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) -{ +__attribute__(( weak )) void vPortSetupTimerInterrupt(void) { /* Calculate the constants required to configure the tick interrupt. */ - #if( configUSE_TICKLESS_IDLE == 1 ) +#if( configUSE_TICKLESS_IDLE == 1 ) { ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; @@ -630,88 +619,69 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ) + - 1UL; + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT + | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT); } /*-----------------------------------------------------------*/ #if( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { +void vPortValidateInterruptPriority(void) { uint32_t ulCurrentInterrupt; uint8_t ucCurrentPriority; - /* Obtain the number of the currently executing interrupt. */ - __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); - /* Is the interrupt number a user defined interrupt? */ - if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) - { - /* Look up the interrupt's priority. */ - ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + /* Is the interrupt number a user defined interrupt? */ + if (ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER) { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ulCurrentInterrupt]; - /* The following assertion will fail if a service routine (ISR) for - an interrupt that has been assigned a priority above - configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API - function. ISR safe FreeRTOS API functions must *only* be called - from interrupts that have been assigned a priority at or below - configMAX_SYSCALL_INTERRUPT_PRIORITY. + /* The following assertion will fail if a service routine (ISR) for + an interrupt that has been assigned a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + function. ISR safe FreeRTOS API functions must *only* be called + from interrupts that have been assigned a priority at or below + configMAX_SYSCALL_INTERRUPT_PRIORITY. - Numerically low interrupt priority numbers represent logically high - interrupt priorities, therefore the priority of the interrupt must - be set to a value equal to or numerically *higher* than - configMAX_SYSCALL_INTERRUPT_PRIORITY. + Numerically low interrupt priority numbers represent logically high + interrupt priorities, therefore the priority of the interrupt must + be set to a value equal to or numerically *higher* than + configMAX_SYSCALL_INTERRUPT_PRIORITY. - Interrupts that use the FreeRTOS API must not be left at their - default priority of zero as that is the highest possible priority, - which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, - and therefore also guaranteed to be invalid. + Interrupts that use the FreeRTOS API must not be left at their + default priority of zero as that is the highest possible priority, + which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + and therefore also guaranteed to be invalid. - FreeRTOS maintains separate thread and ISR API functions to ensure - interrupt entry is as fast and simple as possible. + FreeRTOS maintains separate thread and ISR API functions to ensure + interrupt entry is as fast and simple as possible. - The following links provide detailed information: - http://www.freertos.org/RTOS-Cortex-M3-M4.html - http://www.freertos.org/FAQHelp.html */ - configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); - } - - /* Priority grouping: The interrupt controller (NVIC) allows the bits - that define each interrupt's priority to be split between bits that - define the interrupt's pre-emption priority bits and bits that define - the interrupt's sub-priority. For simplicity all bits must be defined - to be pre-emption priority bits. The following assertion will fail if - this is not the case (if some bits represent a sub-priority). - - If the application only uses CMSIS libraries for interrupt - configuration then the correct setting can be achieved on all Cortex-M - devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the - scheduler. Note however that some vendor specific peripheral libraries - assume a non-zero priority group setting, in which cases using a value - of zero will result in unpredictable behaviour. */ - configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + The following links provide detailed information: + http://www.freertos.org/RTOS-Cortex-M3-M4.html + http://www.freertos.org/FAQHelp.html */ + configASSERT(ucCurrentPriority >= ucMaxSysCallPriority); } + /* Priority grouping: The interrupt controller (NVIC) allows the bits + that define each interrupt's priority to be split between bits that + define the interrupt's pre-emption priority bits and bits that define + the interrupt's sub-priority. For simplicity all bits must be defined + to be pre-emption priority bits. The following assertion will fail if + this is not the case (if some bits represent a sub-priority). + + If the application only uses CMSIS libraries for interrupt + configuration then the correct setting can be achieved on all Cortex-M + devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + scheduler. Note however that some vendor specific peripheral libraries + assume a non-zero priority group setting, in which cases using a value + of zero will result in unpredictable behaviour. */ + configASSERT( + ( portAIRCR_REG & portPRIORITY_GROUP_MASK) <= ulMaxPRIGROUPValue); +} + #endif /* configASSERT_DEFINED */ - - - - - - - - - - - - - - - - - - - - diff --git a/workspace/TS100/Core/BSP/Miniware/portmacro.h b/workspace/TS100/Core/BSP/Miniware/portmacro.h index 29bccbb2..6e62a075 100644 --- a/workspace/TS100/Core/BSP/Miniware/portmacro.h +++ b/workspace/TS100/Core/BSP/Miniware/portmacro.h @@ -25,7 +25,6 @@ * 1 tab == 4 spaces! */ - #ifndef PORTMACRO_H #define PORTMACRO_H @@ -60,12 +59,12 @@ typedef unsigned long UBaseType_t; typedef uint16_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffff #else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL - /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - not need to be guarded with a critical section. */ - #define portTICK_TYPE_IS_ATOMIC 1 +/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 #endif /*-----------------------------------------------------------*/ @@ -94,8 +93,8 @@ typedef unsigned long UBaseType_t; /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); +extern void vPortEnterCritical(void); +extern void vPortExitCritical(void); #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() @@ -106,55 +105,55 @@ extern void vPortExitCritical( void ); /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. These are -not necessary for to use this port. They are defined so the common demo files -(which build with all the ports) will build. */ + not necessary for to use this port. They are defined so the common demo files + (which build with all the ports) will build. */ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ /* Tickless idle/low power functionality. */ #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #endif /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #endif #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { +/* Generic helper function. */ +__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( + uint32_t ulBitmap) { uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); + return ucReturn; +} - /* Check the configuration. */ - #if( configMAX_PRIORITIES > 32 ) - #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. - #endif +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) +#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. +#endif - /* Store/clear the ready priorities in a bit map. */ - #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) - #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ #ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +void vPortValidateInterruptPriority( void ); +#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif /* portNOP() is not required by this port. */ @@ -163,25 +162,21 @@ not necessary for to use this port. They are defined so the common demo files #define portINLINE __inline #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) +#define portFORCE_INLINE inline __attribute__(( always_inline)) #endif /*-----------------------------------------------------------*/ -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; +portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt(void) { + uint32_t ulCurrentInterrupt; + BaseType_t xReturn; /* Obtain the number of the currently executing interrupt. */ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" ); - if( ulCurrentInterrupt == 0 ) - { + if (ulCurrentInterrupt == 0) { xReturn = pdFALSE; - } - else - { + } else { xReturn = pdTRUE; } @@ -190,47 +185,44 @@ BaseType_t xReturn; /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; +portFORCE_INLINE static void vPortRaiseBASEPRI(void) { + uint32_t ulNewBASEPRI; __asm volatile ( - " mov %0, %1 \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + " mov %0, %1 \n" + " msr basepri, %0 \n" + " isb \n" + " dsb \n" + :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ); } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; +portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI(void) { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; __asm volatile ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + " mrs %0, basepri \n" + " mov %1, %2 \n" + " msr basepri, %1 \n" + " isb \n" + " dsb \n" + :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ); /* This return will not be reached but is necessary to prevent compiler - warnings. */ + warnings. */ return ulOriginalBASEPRI; } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ +portFORCE_INLINE static void vPortSetBASEPRI(uint32_t ulNewMaskValue) { __asm volatile ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" + " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" ); } /*-----------------------------------------------------------*/ diff --git a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_msp.c b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_msp.c index 3ccd6413..a9daf6ac 100644 --- a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_msp.c +++ b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_msp.c @@ -26,10 +26,9 @@ void HAL_MspInit(void) { /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0); - } -void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) { +void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) { GPIO_InitTypeDef GPIO_InitStruct; if (hadc->Instance == ADC1) { @@ -72,7 +71,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) { } -void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { GPIO_InitTypeDef GPIO_InitStruct; /**I2C1 GPIO Configuration @@ -123,7 +122,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { } -void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) { +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) { if (htim_base->Instance == TIM3) { /* Peripheral clock enable */ __HAL_RCC_TIM3_CLK_ENABLE() diff --git a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_timebase_TIM.c b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_timebase_TIM.c index 84a8ae55..033a3f80 100644 --- a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_timebase_TIM.c +++ b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_hal_timebase_TIM.c @@ -1,158 +1,154 @@ /** - ****************************************************************************** - * @file stm32f1xx_hal_timebase_TIM.c - * @brief HAL time base based on the hardware TIM. - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2017 STMicroelectronics International N.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ + ****************************************************************************** + * @file stm32f1xx_hal_timebase_TIM.c + * @brief HAL time base based on the hardware TIM. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2017 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ /* Includes ------------------------------------------------------------------*/ #include "stm32f1xx_hal.h" #include "stm32f1xx_hal_tim.h" /** @addtogroup STM32F7xx_HAL_Examples - * @{ - */ + * @{ + */ /** @addtogroup HAL_TimeBase - * @{ - */ + * @{ + */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ -TIM_HandleTypeDef htim1; -uint32_t uwIncrementState = 0; +TIM_HandleTypeDef htim1; +uint32_t uwIncrementState = 0; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** - * @brief This function configures the TIM1 as a time base source. - * The time source is configured to have 1ms time base with a dedicated - * Tick interrupt priority. - * @note This function is called automatically at the beginning of program after - * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). - * @param TickPriority: Tick interrupt priorty. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) -{ - RCC_ClkInitTypeDef clkconfig; - uint32_t uwTimclock = 0; - uint32_t uwPrescalerValue = 0; - uint32_t pFLatency; - - /*Configure the TIM1 IRQ priority */ - HAL_NVIC_SetPriority(TIM1_UP_IRQn, TickPriority ,0); - - /* Enable the TIM1 global Interrupt */ - HAL_NVIC_EnableIRQ(TIM1_UP_IRQn); - - /* Enable TIM1 clock */ - __HAL_RCC_TIM1_CLK_ENABLE(); - - /* Get clock configuration */ - HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); - - /* Compute TIM1 clock */ - uwTimclock = HAL_RCC_GetPCLK2Freq(); - - /* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */ - uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1); - - /* Initialize TIM1 */ - htim1.Instance = TIM1; - - /* Initialize TIMx peripheral as follow: - + Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base. - + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. - + ClockDivision = 0 - + Counter direction = Up - */ - htim1.Init.Period = (1000000 / 1000) - 1; - htim1.Init.Prescaler = uwPrescalerValue; - htim1.Init.ClockDivision = 0; - htim1.Init.CounterMode = TIM_COUNTERMODE_UP; - if(HAL_TIM_Base_Init(&htim1) == HAL_OK) - { - /* Start the TIM time Base generation in interrupt mode */ - return HAL_TIM_Base_Start_IT(&htim1); - } - - /* Return function status */ - return HAL_ERROR; + * @brief This function configures the TIM1 as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority: Tick interrupt priorty. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { + RCC_ClkInitTypeDef clkconfig; + uint32_t uwTimclock = 0; + uint32_t uwPrescalerValue = 0; + uint32_t pFLatency; + + /*Configure the TIM1 IRQ priority */ + HAL_NVIC_SetPriority(TIM1_UP_IRQn, TickPriority, 0); + + /* Enable the TIM1 global Interrupt */ + HAL_NVIC_EnableIRQ(TIM1_UP_IRQn); + + /* Enable TIM1 clock */ + __HAL_RCC_TIM1_CLK_ENABLE(); + + /* Get clock configuration */ + HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + + /* Compute TIM1 clock */ + uwTimclock = HAL_RCC_GetPCLK2Freq(); + + /* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */ + uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1); + + /* Initialize TIM1 */ + htim1.Instance = TIM1; + + /* Initialize TIMx peripheral as follow: + + Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base. + + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + + ClockDivision = 0 + + Counter direction = Up + */ + htim1.Init.Period = (1000000 / 1000) - 1; + htim1.Init.Prescaler = uwPrescalerValue; + htim1.Init.ClockDivision = 0; + htim1.Init.CounterMode = TIM_COUNTERMODE_UP; + if (HAL_TIM_Base_Init(&htim1) == HAL_OK) { + /* Start the TIM time Base generation in interrupt mode */ + return HAL_TIM_Base_Start_IT(&htim1); + } + + /* Return function status */ + return HAL_ERROR; } /** - * @brief Suspend Tick increment. - * @note Disable the tick increment by disabling TIM1 update interrupt. - * @param None - * @retval None - */ -void HAL_SuspendTick(void) -{ - /* Disable TIM1 update Interrupt */ - __HAL_TIM_DISABLE_IT(&htim1, TIM_IT_UPDATE); + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling TIM1 update interrupt. + * @param None + * @retval None + */ +void HAL_SuspendTick(void) { + /* Disable TIM1 update Interrupt */ + __HAL_TIM_DISABLE_IT(&htim1, TIM_IT_UPDATE); } /** - * @brief Resume Tick increment. - * @note Enable the tick increment by Enabling TIM1 update interrupt. - * @param None - * @retval None - */ -void HAL_ResumeTick(void) -{ - /* Enable TIM1 Update interrupt */ - __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE); + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling TIM1 update interrupt. + * @param None + * @retval None + */ +void HAL_ResumeTick(void) { + /* Enable TIM1 Update interrupt */ + __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE); } /** - * @} - */ + * @} + */ /** - * @} - */ + * @} + */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c index b9ee5c51..a38190b4 100644 --- a/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c +++ b/workspace/TS100/Core/BSP/Miniware/stm32f1xx_it.c @@ -82,6 +82,6 @@ void DMA1_Channel6_IRQHandler(void) { void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); } -void EXTI9_5_IRQHandler(void){ +void EXTI9_5_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9); } diff --git a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c index 5c5c0297..08dee014 100644 --- a/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c +++ b/workspace/TS100/Core/BSP/Miniware/system_stm32f1xx.c @@ -7,7 +7,7 @@ This value can be provided and adapted by the user application. */ #endif /* HSI_VALUE */ -/*!< Uncomment the following line if you need to use external SRAM */ +/*!< Uncomment the following line if you need to use external SRAM */ #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) /* #define DATA_IN_ExtSRAM */ #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ @@ -19,68 +19,67 @@ #endif /******************************************************************************* -* Clock Definitions -*******************************************************************************/ + * Clock Definitions + *******************************************************************************/ #if defined(STM32F100xB) ||defined(STM32F100xE) uint32_t SystemCoreClock = 24000000U; /*!< System Clock Frequency (Core Clock) */ #else /*!< HSI Selected as System Clock source */ - uint32_t SystemCoreClock = 64000000U; /*!< System Clock Frequency (Core Clock) */ +uint32_t SystemCoreClock = 64000000U; /*!< System Clock Frequency (Core Clock) */ #endif -const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -const uint8_t APBPrescTable[8U] = {0, 0, 0, 0, 1, 2, 3, 4}; - +const uint8_t AHBPrescTable[16U] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, + 8, 9 }; +const uint8_t APBPrescTable[8U] = { 0, 0, 0, 0, 1, 2, 3, 4 }; /** - * @brief Setup the microcontroller system - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemCoreClock variable. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -void SystemInit (void) -{ - /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ - /* Set HSION bit */ - RCC->CR |= 0x00000001U; + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemCoreClock variable. + * @note This function should be used only after reset. + * @param None + * @retval None + */ +void SystemInit(void) { + /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ + /* Set HSION bit */ + RCC->CR |= 0x00000001U; - /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ + /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ #if !defined(STM32F105xC) && !defined(STM32F107xC) - RCC->CFGR &= 0xF8FF0000U; + RCC->CFGR &= 0xF8FF0000U; #else - RCC->CFGR &= 0xF0FF0000U; + RCC->CFGR &= 0xF0FF0000U; #endif /* STM32F105xC */ - - /* Reset HSEON, CSSON and PLLON bits */ - RCC->CR &= 0xFEF6FFFFU; - /* Reset HSEBYP bit */ - RCC->CR &= 0xFFFBFFFFU; + /* Reset HSEON, CSSON and PLLON bits */ + RCC->CR &= 0xFEF6FFFFU; - /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ - RCC->CFGR &= 0xFF80FFFFU; + /* Reset HSEBYP bit */ + RCC->CR &= 0xFFFBFFFFU; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ + RCC->CFGR &= 0xFF80FFFFU; #if defined(STM32F105xC) || defined(STM32F107xC) - /* Reset PLL2ON and PLL3ON bits */ - RCC->CR &= 0xEBFFFFFFU; + /* Reset PLL2ON and PLL3ON bits */ + RCC->CR &= 0xEBFFFFFFU; - /* Disable all interrupts and clear pending bits */ - RCC->CIR = 0x00FF0000U; + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x00FF0000U; - /* Reset CFGR2 register */ - RCC->CFGR2 = 0x00000000U; + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000U; #elif defined(STM32F100xB) || defined(STM32F100xE) - /* Disable all interrupts and clear pending bits */ - RCC->CIR = 0x009F0000U; + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000U; - /* Reset CFGR2 register */ - RCC->CFGR2 = 0x00000000U; + /* Reset CFGR2 register */ + RCC->CFGR2 = 0x00000000U; #else - /* Disable all interrupts and clear pending bits */ - RCC->CIR = 0x009F0000U; + /* Disable all interrupts and clear pending bits */ + RCC->CIR = 0x009F0000U; #endif /* STM32F105xC */ - + #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) #ifdef DATA_IN_ExtSRAM SystemInit_ExtMemCtl(); @@ -90,48 +89,47 @@ void SystemInit (void) #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ #else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif } /** - * @brief Update SystemCoreClock variable according to Clock Register Values. - * The SystemCoreClock variable contains the core clock (HCLK), it can - * be used by the user application to setup the SysTick timer or configure - * other parameters. - * - * @note Each time the core clock (HCLK) changes, this function must be called - * to update SystemCoreClock variable value. Otherwise, any configuration - * based on this variable will be incorrect. - * - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value - * 8 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value - * 8 MHz or 25 MHz, depending on the product used), user has to ensure - * that HSE_VALUE is same as the real frequency of the crystal used. - * Otherwise, this function may have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * @param None - * @retval None - */ -void SystemCoreClockUpdate (void) -{ - uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U; + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value + * 8 MHz or 25 MHz, depending on the product used), user has to ensure + * that HSE_VALUE is same as the real frequency of the crystal used. + * Otherwise, this function may have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) { + uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U; #if defined(STM32F105xC) || defined(STM32F107xC) uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U; @@ -140,50 +138,43 @@ void SystemCoreClockUpdate (void) #if defined(STM32F100xB) || defined(STM32F100xE) uint32_t prediv1factor = 0U; #endif /* STM32F100xB or STM32F100xE */ - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00U: /* HSI used as system clock */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04U: /* HSE used as system clock */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08U: /* PLL used as system clock */ - /* Get PLL clock source and multiplication factor ----------------------*/ - pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; - pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; - + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) { + case 0x00U: /* HSI used as system clock */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04U: /* HSE used as system clock */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08U: /* PLL used as system clock */ + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + #if !defined(STM32F105xC) && !defined(STM32F107xC) - pllmull = ( pllmull >> 18U) + 2U; - - if (pllsource == 0x00U) - { - /* HSI oscillator clock divided by 2 selected as PLL clock entry */ - SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; - } - else - { - #if defined(STM32F100xB) || defined(STM32F100xE) + pllmull = (pllmull >> 18U) + 2U; + + if (pllsource == 0x00U) { + /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + SystemCoreClock = (HSI_VALUE >> 1U) * pllmull; + } else { +#if defined(STM32F100xB) || defined(STM32F100xE) prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U; /* HSE oscillator clock selected as PREDIV1 clock entry */ SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; #else - /* HSE selected as PLL clock entry */ - if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) - {/* HSE oscillator clock divided by 2 */ - SystemCoreClock = (HSE_VALUE >> 1U) * pllmull; - } - else - { - SystemCoreClock = HSE_VALUE * pllmull; - } - #endif - } + /* HSE selected as PLL clock entry */ + if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t) RESET) {/* HSE oscillator clock divided by 2 */ + SystemCoreClock = (HSE_VALUE >> 1U) * pllmull; + } else { + SystemCoreClock = HSE_VALUE * pllmull; + } +#endif + } #else pllmull = pllmull >> 18U; @@ -223,18 +214,18 @@ void SystemCoreClockUpdate (void) } } #endif /* STM32F105xC */ - break; + break; - default: - SystemCoreClock = HSI_VALUE; - break; - } - - /* Compute HCLK clock frequency ----------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; - /* HCLK clock frequency */ - SystemCoreClock >>= tmp; + default: + SystemCoreClock = HSI_VALUE; + break; + } + + /* Compute HCLK clock frequency ----------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; } #if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG) @@ -302,14 +293,14 @@ void SystemInit_ExtMemCtl(void) #endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */ /** - * @} - */ + * @} + */ /** - * @} - */ - + * @} + */ + /** - * @} - */ + * @} + */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From e72c884b62e001f6b9a12219393b9c334beda548 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 19:06:33 +1100 Subject: [PATCH 30/72] Update pr.yml --- .github/workflows/pr.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 218b7984..6d1a9f32 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -75,3 +75,29 @@ jobs: workspace/TS100/Hexfile/TS100_*.hex workspace/TS100/Hexfile/TS100_*.bin if-no-files-found: error + + build_Pinecil: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + + - name: setup + run: ./setup.sh + + - name: build Pinecil + run: cd workspace/TS100 && ./build.sh -m Pinecil + + - name: Archive Pinecil artifacts + uses: actions/upload-artifact@v2 + with: + name: Pinecil + path: | + workspace/TS100/Hexfile/Pinecil_*.hex + workspace/TS100/Hexfile/Pinecil_*.bin + if-no-files-found: error + \ No newline at end of file From 5386dfdfaff1e0f34280016d2a79a6f317d1366f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 19:30:08 +1100 Subject: [PATCH 31/72] Update setup.sh --- setup.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 36ba14f4..a5c36c96 100644 --- a/setup.sh +++ b/setup.sh @@ -1,13 +1,15 @@ #!/bin/bash set -e # Setup shell file to setup the environment on an ubuntu machine -sudo apt-get update +sudo apt-get update sudo apt-get install -y make bzip2 git python3 wget sudo mkdir /build cd /build sudo wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | sudo tar -xj +RUN wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj # Add compiler to the path sudo ln -s /build/gcc-arm-none-eabi-9-2020-q2-update/bin/* /usr/local/bin +sudo ln -s /build/rv_linux_bare_1908312208/bin/* /usr/local/bin From baef9264ff5377de881fbb4ba9f5bbbb45f6c220 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 19:45:52 +1100 Subject: [PATCH 32/72] Update setup.sh --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index a5c36c96..bd2d0d5a 100644 --- a/setup.sh +++ b/setup.sh @@ -7,7 +7,7 @@ sudo mkdir /build cd /build sudo wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | sudo tar -xj -RUN wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj +sudo wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj # Add compiler to the path From d380cd4b9e73bc89165906049bb75189928f59e7 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 19:47:41 +1100 Subject: [PATCH 33/72] Update setup.sh --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index bd2d0d5a..21036bfb 100644 --- a/setup.sh +++ b/setup.sh @@ -7,7 +7,7 @@ sudo mkdir /build cd /build sudo wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | sudo tar -xj -sudo wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj +sudo wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | sudo tar -xj # Add compiler to the path From 40cf09a910c66aae9dbad469d8da28feb8c582ed Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 20:23:43 +1100 Subject: [PATCH 34/72] Add support for dual speed PWM --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 45 +++++++++++++--------- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 49 ++++++++++++++++++++++-- workspace/TS100/Core/BSP/Pine64/Setup.c | 4 +- workspace/TS100/Core/BSP/Pine64/Setup.h | 3 +- workspace/TS100/Core/BSP/Pine64/logo.cpp | 1 - workspace/TS100/Core/Src/power.cpp | 5 +-- 6 files changed, 76 insertions(+), 31 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 7eef4672..391c1bf6 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -10,6 +10,12 @@ #include "systick.h" #include +const uint16_t powerPWM = 255; +const uint8_t holdoffTicks = 13; // delay of 7 ms +const uint8_t tempMeasureTicks = 17; + +uint16_t totalPWM; //htim2.Init.Period, the full PWM cycle + //2 second filter (ADC is PID_TIM_HZ Hz) history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { @@ -58,7 +64,6 @@ uint16_t getHandleTemperature() { } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - static uint8_t preFillneeded = 10; static uint32_t samples[BATTFILTERDEPTH]; static uint8_t index = 0; @@ -84,24 +89,24 @@ uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { } void unstick_I2C() { - /* configure SDA/SCL for GPIO */ - GPIO_BC(GPIOB) |= SDA_Pin|SCL_Pin; - gpio_init(SDA_GPIO_Port,GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - GPIO_BOP(GPIOB) |= SCL_Pin; - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - GPIO_BOP(GPIOB) |= SDA_Pin; - /* connect PB6 to I2C0_SCL */ - /* connect PB7 to I2C0_SDA */ - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + /* configure SDA/SCL for GPIO */ + GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin; + gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SCL_Pin; + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + asm ("nop"); + GPIO_BOP(GPIOB) |= SDA_Pin; + /* connect PB6 to I2C0_SCL */ + /* connect PB7 to I2C0_SDA */ + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); } uint8_t getButtonA() { @@ -120,3 +125,5 @@ void reboot() { void delay_ms(uint16_t count) { delay_1ms(count); } + + diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index 8a726beb..f9654cfd 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -55,13 +55,54 @@ void TIMER1_IRQHandler(void) { } void setTipPWM(uint8_t pulse) { - PWMSafetyTimer = 10; -// This is decremented in the handler for PWM so that the tip pwm is -// disabled if the PID task is not scheduled often enough. - + PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is + // disabled if the PID task is not scheduled often enough. pendingPWM = pulse; } +static bool fastPWM; +static void switchToFastPWM(void) { + fastPWM = true; + totalPWM = powerPWM + tempMeasureTicks * 2; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + + // ~3.5 Hz rate + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2; + //1 kHz tick rate + TIMER_PSC(TIMER1) = 12000; + /* generate an update event */ + TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG; + +} + +static void switchToSlowPWM(void) { + fastPWM = false; + totalPWM = powerPWM + tempMeasureTicks; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + // ~1.84 Hz rate + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks; + // 500 Hz tick rate + TIMER_PSC(TIMER1) = 24000; + /* generate an update event */ + TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG; + +} + +bool tryBetterPWM(uint8_t pwm) { + if (fastPWM && pwm == powerPWM) { + // maximum power for fast PWM reached, need to go slower to get more + switchToSlowPWM(); + return true; + } else if (!fastPWM && pwm < 230) { + // 254 in fast PWM mode gives the same power as 239 in slow + // allow for some reasonable hysteresis by switching only when it goes + // below 230 (equivalent to 245 in fast mode) + switchToFastPWM(); + return true; + } + return false; +} + void EXTI5_9_IRQHandler(void) { #ifdef POW_PD if (RESET != exti_interrupt_flag_get(EXTI_5)) { diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 3dd25f03..f48862be 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -211,7 +211,7 @@ void setup_timers() { timer_initpara.prescaler = 24000; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = 255 + 17; + timer_initpara.period = powerPWM + tempMeasureTicks; timer_initpara.clockdivision = TIMER_CKDIV_DIV4; timer_initpara.repetitioncounter = 0; timer_init(TIMER1, &timer_initpara); @@ -222,7 +222,7 @@ void setup_timers() { timer_ocintpara.outputstate = TIMER_CCX_ENABLE; timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, 255 + 13); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, powerPWM + holdoffTicks); timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM1); timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.h b/workspace/TS100/Core/BSP/Pine64/Setup.h index 8bc6fdeb..47d19dbe 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.h +++ b/workspace/TS100/Core/BSP/Pine64/Setup.h @@ -19,5 +19,6 @@ void setupFUSBIRQ(); #ifdef __cplusplus } #endif - +extern const uint8_t holdoffTicks; +extern const uint8_t tempMeasureTicks; #endif /* SETUP_H_ */ diff --git a/workspace/TS100/Core/BSP/Pine64/logo.cpp b/workspace/TS100/Core/BSP/Pine64/logo.cpp index 1001e712..9d82ca36 100644 --- a/workspace/TS100/Core/BSP/Pine64/logo.cpp +++ b/workspace/TS100/Core/BSP/Pine64/logo.cpp @@ -9,7 +9,6 @@ #include "OLED.hpp" // Second last page of flash set aside for logo image. #define FLASH_LOGOADDR (0x8000000 | 0xF800) -//TODO // Logo header signature. #define LOGO_HEADER_VALUE 0xF00DAA55 diff --git a/workspace/TS100/Core/Src/power.cpp b/workspace/TS100/Core/Src/power.cpp index be042aa7..5620f50c 100644 --- a/workspace/TS100/Core/Src/power.cpp +++ b/workspace/TS100/Core/Src/power.cpp @@ -33,7 +33,7 @@ static uint32_t availableW10(uint8_t sample) { //P = V^2 / R, v*v = v^2 * 100 // R = R*10 // P therefore is in V^2*100/R*10 = W*10. - uint32_t v = getInputVoltageX10(systemSettings.voltageDiv, sample); // 100 = 10v + uint32_t v = getInputVoltageX10(systemSettings.voltageDiv, sample); // 100 = 10v uint32_t availableWattsX10 = (v * v) / tipResistance; //However, 100% duty cycle is not possible as there is a dead time while the ADC takes a reading //Therefore need to scale available milliwats by this @@ -53,8 +53,6 @@ uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample) { getInputVoltageX10(systemSettings.voltageDiv, sample); return 0; } - // if (milliWatts > (int(systemSettings.pidPowerLimit) * 10)) -// milliWatts = (int(systemSettings.pidPowerLimit) * 10); //Calculate desired milliwatts as a percentage of availableW10 uint32_t pwm; @@ -74,5 +72,4 @@ static int32_t PWMToX10Watts(uint8_t pwm, uint8_t sample) { uint32_t maxMW = availableW10(sample); //Get the milliwatts for the max pwm period //Then convert pwm into percentage of powerPWM to get the percentage of the max mw return (((uint32_t) pwm) * maxMW) / powerPWM; - } From 7da04841d64c89dc291a3df372d5aae7b3b7c75a Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 20:32:51 +1100 Subject: [PATCH 35/72] Update Makefile --- workspace/TS100/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 07b8c591..86f35881 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -68,7 +68,7 @@ S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld DEV_LDFLAGS=-nostartfiles -DEV_AFLAGS = -msmall-data-limit=8 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections +DEV_GLOBAL_DEFS=-mtune=size -msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" endif From c8182aa1925c0bcfd049dd2ff94c9db8158f1589 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 22:08:30 +1100 Subject: [PATCH 36/72] Debugging history.hpp compiling odd --- .../BSP/Pine64/Vendor/Lib/GD32VF103xB.lds | 176 ------------------ workspace/TS100/Core/Drivers/BMA223.cpp | 8 +- .../TS100/Core/Drivers/TipThermoModel.cpp | 15 +- workspace/TS100/Core/Threads/GUIThread.cpp | 10 +- workspace/TS100/Makefile | 19 +- 5 files changed, 27 insertions(+), 201 deletions(-) delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds deleted file mode 100644 index 83ce13a0..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/GD32VF103xB.lds +++ /dev/null @@ -1,176 +0,0 @@ -OUTPUT_ARCH( "riscv" ) - -ENTRY( _start ) - -MEMORY -{ - /* Run in FLASH */ - flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k - ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K - - /* Run in RAM */ -/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k - ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K -*/ -} - - -SECTIONS -{ - __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; - - - .init : - { - KEEP (*(SORT_NONE(.init))) - } >flash AT>flash - - .ilalign : - { - . = ALIGN(4); - PROVIDE( _ilm_lma = . ); - } >flash AT>flash - - .ialign : - { - PROVIDE( _ilm = . ); - } >flash AT>flash - - .text : - { - *(.rodata .rodata.*) - *(.text.unlikely .text.unlikely.*) - *(.text.startup .text.startup.*) - *(.text .text.*) - *(.gnu.linkonce.t.*) - } >flash AT>flash - - .fini : - { - KEEP (*(SORT_NONE(.fini))) - } >flash AT>flash - - . = ALIGN(4); - - PROVIDE (__etext = .); - PROVIDE (_etext = .);/*0x80022c8*/ - PROVIDE (etext = .);/*0x80022c8*/ - PROVIDE( _eilm = . ); - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >flash AT>flash - - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } >flash AT>flash - - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >flash AT>flash - - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } >flash AT>flash - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } >flash AT>flash - - . = ALIGN(4); - PROVIDE( _eilm = . ); - - .lalign : - { - . = ALIGN(4); - PROVIDE( _data_lma = . ); - } >flash AT>flash - - .dalign : - { - . = ALIGN(4); - PROVIDE( _data = . ); - } >ram AT>flash - - - .data : - { - *(.rdata) - - *(.gnu.linkonce.r.*) - *(.data .data.*) - *(.gnu.linkonce.d.*) - . = ALIGN(8); - PROVIDE( __global_pointer$ = . + 0x800); - *(.sdata .sdata.*) - *(.gnu.linkonce.s.*) - . = ALIGN(8); - *(.srodata.cst16) - *(.srodata.cst8) - *(.srodata.cst4) - *(.srodata.cst2) - *(.srodata .srodata.*) - } >ram AT>flash - - . = ALIGN(4); - PROVIDE( _edata = . ); - PROVIDE( edata = . ); - - PROVIDE( _fbss = . ); /*0X200052A0 0X200002A0*/ - PROVIDE( __bss_start = . ); - .bss : - { - *(.sbss*) - *(.gnu.linkonce.sb.*) - *(.bss .bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN(4); - } >ram AT>ram - - . = ALIGN(8); - PROVIDE( _end = . ); /*0X2000,0340*/ - PROVIDE( end = . ); - PROVIDE( heap_start = . ); - - .stack ORIGIN(ram) + LENGTH(ram) - __stack_size : - { - PROVIDE( heap_end = . ); - . = __stack_size; - PROVIDE( _sp = . ); - } >ram AT>ram -} diff --git a/workspace/TS100/Core/Drivers/BMA223.cpp b/workspace/TS100/Core/Drivers/BMA223.cpp index 939b3d31..7cd08530 100644 --- a/workspace/TS100/Core/Drivers/BMA223.cpp +++ b/workspace/TS100/Core/Drivers/BMA223.cpp @@ -45,12 +45,12 @@ void BMA223::getAxisReadings(int16_t& x, int16_t& y, int16_t& z) { uint8_t sensorData[6] = { 0, 0, 0, 0, 0, 0 }; if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) { - x = 0xAAFF; + x = y = z = 0; return; } - x = sensorData[1] << 4; - y = sensorData[3] << 4; - z = sensorData[5] << 4; + x = sensorData[1] << 5; + y = sensorData[3] << 5; + z = sensorData[5] << 5; } diff --git a/workspace/TS100/Core/Drivers/TipThermoModel.cpp b/workspace/TS100/Core/Drivers/TipThermoModel.cpp index c94e6284..18ab0a10 100644 --- a/workspace/TS100/Core/Drivers/TipThermoModel.cpp +++ b/workspace/TS100/Core/Drivers/TipThermoModel.cpp @@ -31,7 +31,7 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC) { // This takes the raw ADC samples, converts these to uV // Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals) // Then remove the calibration value that is stored as a tip offset - uint32_t vddRailmVX10 = 33000;//The vreg is +-2%, but we have no higher accuracy available + uint32_t vddRailmVX10 = 33000; //The vreg is +-2%, but we have no higher accuracy available // 4096 * 8 readings for full scale // Convert the input ADC reading back into mV times 10 format. uint32_t rawInputmVX10 = (rawADC * vddRailmVX10) / (4096 * 8); @@ -64,8 +64,7 @@ uint32_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) { // [x2, y2] = point 2 // x = input value // output is x's extrapolated y value -int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - int32_t x) { +int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x) { return y1 + (((((x - x1) * 1000) / (x2 - x1)) * (y2 - y1))) / 1000; } @@ -95,15 +94,16 @@ uint32_t TipThermoModel::convertCtoF(uint32_t degC) { uint32_t TipThermoModel::convertFtoC(uint32_t degF) { //(Y°F − 32) × 5/9 = Y°C if (degF < 32) - return 0; + return 0; return ((degF - 32) * 5) / 9; } #endif uint32_t TipThermoModel::getTipInC(bool sampleNow) { - uint32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC( - getTipRawTemp(sampleNow)); + int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow)); currentTipTempInC += getHandleTemperature() / 10; //Add handle offset + if (currentTipTempInC < 0) + return 0; return currentTipTempInC; } #ifdef ENABLED_FAHRENHEIT_SUPPORT @@ -116,8 +116,7 @@ uint32_t TipThermoModel::getTipInF(bool sampleNow) { #endif uint32_t TipThermoModel::getTipMaxInC() { - uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC( - 0x7FFF - (80 * 5)); //back off approx 5 deg c from ADC max + uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(0x7FFF - (80 * 5)); //back off approx 5 deg c from ADC max maximumTipTemp += getHandleTemperature() / 10; //Add handle offset return maximumTipTemp - 1; } diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 9f5e47f0..f1b7604a 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -56,7 +56,7 @@ void GUIDelay() { } void gui_drawTipTemp(bool symbol) { // Draw tip temp handling unit conversion & tolerance near setpoint - uint16_t Temp = 0; + uint32_t Temp = 0; #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { Temp = TipThermoModel::getTipInF(); @@ -581,13 +581,13 @@ void showDebugMenu(void) { { uint32_t temp = systemSettings.CalibrationOffset; systemSettings.CalibrationOffset = 0; - OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(1)), 6); + OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0)), 6); systemSettings.CalibrationOffset = temp; } break; case 7: // Temp in C - OLED::printNumber(TipThermoModel::getTipInC(1), 5); + OLED::printNumber(TipThermoModel::getTipInC(), 5); break; case 8: // Handle Temp @@ -628,7 +628,7 @@ void startGUITask(void const *argument __unused) { bool tempOnDisplay = false; { //Generate the flipped screen into ram for later use -//flipped is generated by flipping each row + //flipped is generated by flipping each row for (int row = 0; row < 2; row++) { for (int x = 0; x < 84; x++) { idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + (83 - x)]; @@ -716,7 +716,7 @@ void startGUITask(void const *argument __unused) { currentTempTargetDegC = 0; // ensure tip is off getInputVoltageX10(systemSettings.voltageDiv, 0); - uint16_t tipTemp = TipThermoModel::getTipInC(); + uint32_t tipTemp = TipThermoModel::getTipInC(); // Preemptively turn the display on. Turn it off if and only if // the tip temperature is below 50 degrees C *and* motion sleep diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 86f35881..2084b781 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -53,6 +53,8 @@ DEV_LDFLAGS= DEV_AFLAGS= DEV_CFLAGS= DEV_CXXFLAGS= +flash_size=64k +bootldr_size=0x4000 endif ifeq ($(model),Pinecil) @@ -67,10 +69,12 @@ DEVICE_BSP_DIR = ./Core/BSP/Pine64 S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld -DEV_LDFLAGS=-nostartfiles -DEV_GLOBAL_DEFS=-mtune=size -msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common +DEV_LDFLAGS=-nostartfiles -Xlinker +DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" +flash_size=128k +bootldr_size=0x0 endif INCLUDES = -I$(APP_INC_DIR) \ @@ -99,10 +103,8 @@ OUTPUT_DIR=Objects # code optimisation ------------------------------------------------------------ OPTIM_AS= -Wall -OPTIM=-Os -flto -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections +OPTIM=-Os -flto -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections -flash_size=64k -bootldr_size=0x4000 # global defines --------------------------------------------------------------- GLOBAL_DEFINES += -D LANG_$(lang) -D LANG -D MODEL_$(model) $(DEV_GLOBAL_DEFS) @@ -151,7 +153,8 @@ endif ifeq ($(model),Pinecil) CPUFLAGS= -march=rv32imac \ -mabi=ilp32 \ - -mcmodel=medany \ + -mtune=size \ + -mcmodel=medlow \ -DGD32VF103C_START \ -DUSE_STDPERIPH_DRIVER endif @@ -159,7 +162,6 @@ endif # linker flags ----------------------------------------------------------------- -LD_FILE = $(PINE_VENDOR_INC_DIR)/GD32VF103xB.lds LINKER_FLAGS=-Wl,--gc-sections \ -Wl,--wrap=malloc \ -Wl,--wrap=free \ @@ -284,7 +286,8 @@ all: $(OUT_HEXFILE).hex $(OUT_HEXFILE).bin $(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) @test -d $(@D) || mkdir -p $(@D) @echo Linking $(OUTPUT_EXE).elf - @$(CPP) $(CXXFLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) $(LINKER_FLAGS) + @echo $(CPP) $(CXXFLAGS) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) + @$(CPP) $(CXXFLAGS) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) From 3e62afc4556777f035de994e73df200fbb708d08 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 13 Oct 2020 22:31:46 +1100 Subject: [PATCH 37/72] Move to nuclei compiler --- Dockerfile | 4 ++-- setup.sh | 4 ++-- workspace/TS100/Makefile | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 69b7b686..9c0435bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,10 @@ RUN apt-get update && \ wget && \ apt-get clean RUN wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | tar -xj -RUN wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | tar -xj +RUN wget -qO- https://github.com/Ralim/nuclei-compiler/releases/download/2020.08/nuclei_riscv_newlibc_prebuilt_linux64_2020.08.tar.bz2 | tar -xj # Add compiler to the path ENV PATH "/build/gcc-arm-none-eabi-9-2020-q2-update/bin:$PATH" -ENV PATH "/build/rv_linux_bare_1908312208/bin/:$PATH" +ENV PATH "/build/gcc/bin/:$PATH" COPY . /build/source COPY ./ci /build/ci diff --git a/setup.sh b/setup.sh index 21036bfb..3a18536f 100644 --- a/setup.sh +++ b/setup.sh @@ -7,9 +7,9 @@ sudo mkdir /build cd /build sudo wget -qO- https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 | sudo tar -xj -sudo wget -qO- https://github.com/riscv-mcu/riscv-gnu-toolchain/releases/download/v9.2RC/rv_linux_bare_1908312208.tar.bz2 | sudo tar -xj +sudo wget -qO- https://github.com/Ralim/nuclei-compiler/releases/download/2020.08/nuclei_riscv_newlibc_prebuilt_linux64_2020.08.tar.bz2 | sudo tar -xj # Add compiler to the path sudo ln -s /build/gcc-arm-none-eabi-9-2020-q2-update/bin/* /usr/local/bin -sudo ln -s /build/rv_linux_bare_1908312208/bin/* /usr/local/bin +sudo ln -s /build/gcc/bin/* /usr/local/bin diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 2084b781..1ca0daeb 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -69,8 +69,8 @@ DEVICE_BSP_DIR = ./Core/BSP/Pine64 S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld -DEV_LDFLAGS=-nostartfiles -Xlinker -DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common +DEV_LDFLAGS=-nostartfiles -Xlinker +DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common -fabi-version=0 DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" flash_size=128k @@ -154,7 +154,7 @@ ifeq ($(model),Pinecil) CPUFLAGS= -march=rv32imac \ -mabi=ilp32 \ -mtune=size \ - -mcmodel=medlow \ + -mcmodel=medany \ -DGD32VF103C_START \ -DUSE_STDPERIPH_DRIVER endif @@ -292,7 +292,6 @@ $(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCR $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) @echo Compiling ${<} - @echo @$(CC) -c $(CFLAGS) $< -o $@ @$(CC) -c $(CFLAGS) $< -o $@ @$(OBJDUMP) -d -S $@ > $@.lst From 77dbc9df56e00242c58ac4d3695c06bf337858c4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Wed, 14 Oct 2020 20:26:00 +1100 Subject: [PATCH 38/72] Update Makefile --- workspace/TS100/Makefile | 48 ++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 1ca0daeb..e9ab7293 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -49,7 +49,7 @@ LDSCRIPT=stm32f103.ld DEV_GLOBAL_DEFS= -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D GCC_ARMCM3 \ -D ARM_MATH_CM3 \ -D STM32F10X_MD -DEV_LDFLAGS= +DEV_LDFLAGS=-lm -Wl,--gc-sections DEV_AFLAGS= DEV_CFLAGS= DEV_CXXFLAGS= @@ -69,8 +69,8 @@ DEVICE_BSP_DIR = ./Core/BSP/Pine64 S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld -DEV_LDFLAGS=-nostartfiles -Xlinker -DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common -fabi-version=0 +DEV_LDFLAGS=-nostartfiles -Xlinker --gc-sections +DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -fabi-version=0 DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" flash_size=128k @@ -162,18 +162,32 @@ endif # linker flags ----------------------------------------------------------------- -LINKER_FLAGS=-Wl,--gc-sections \ - -Wl,--wrap=malloc \ - -Wl,--wrap=free \ - -o$(OUT_HEXFILE).elf \ - -Wl,-Map=$(OUT_HEXFILE).map \ - $(CPUFLAGS) \ - -lm -Og -flto -Wl,--undefined=vTaskSwitchContext \ - -T$(LDSCRIPT) \ - -Wl,--defsym=__FLASH_SIZE__=$(flash_size) \ - -Wl,--defsym=__BOOTLDR_SIZE__=$(bootldr_size) \ - --specs=nano.specs \ - $(DEV_LDFLAGS) +LINKER_FLAGS=$(CPUFLAGS) \ + $(GLOBAL_DEFINES) \ + -D${COMPILER} \ + -MMD \ + -std=c++11 \ + $(OPTIM) \ + -fno-common \ + -ffreestanding \ + -fno-rtti \ + -fno-exceptions \ + -fno-non-call-exceptions \ + -fno-use-cxa-atexit \ + -fno-strict-aliasing \ + -fno-rtti \ + -fno-exceptions \ + -fno-threadsafe-statics \ + -Wl,--wrap=malloc \ + -Wl,--wrap=free \ + -Wl,-Map=$(OUT_HEXFILE).map \ + -Wl,--undefined=vTaskSwitchContext \ + -T $(LDSCRIPT) \ + -Wl,--defsym=__FLASH_SIZE__=$(flash_size) \ + -Wl,--defsym=__BOOTLDR_SIZE__=$(bootldr_size) \ + --specs=nano.specs \ + $(DEV_LDFLAGS) \ + -o$(OUT_HEXFILE).elf \ @@ -286,8 +300,8 @@ all: $(OUT_HEXFILE).hex $(OUT_HEXFILE).bin $(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) @test -d $(@D) || mkdir -p $(@D) @echo Linking $(OUTPUT_EXE).elf - @echo $(CPP) $(CXXFLAGS) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) - @$(CPP) $(CXXFLAGS) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) + @echo $(CPP) $(LINKER_FLAGS) + @$(CPP) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) From 4496cfd41dec5de31c3c47183d56112bb5e84f0d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Tue, 27 Oct 2020 18:38:40 +1100 Subject: [PATCH 39/72] More hooks for hall effect --- workspace/TS100/Core/BSP/BSP.h | 1 + workspace/TS100/Core/BSP/Pine64/Model_Config.h | 2 +- workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 4 ++++ workspace/TS100/GD32VF103xB.ld | 7 +------ 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index f0c427dc..5fde786d 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -63,6 +63,7 @@ uint8_t showBootLogoIfavailable(); void delay_ms(uint16_t count) ; //Used to allow knowledge of if usb_pd is being used uint8_t usb_pd_detect(); +bool getHallSensorFitted(); // If the iron has a hall effect sensor in the handle, return an signed count of the reading // If the sensor is single polarity (or polarity insensitive) just return 0..32768 int16_t getRawHallEffect(); diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 2c6a0c84..7587cc60 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -21,7 +21,7 @@ #define TEMP_TMP36 #define ACCEL_BMA #define HALL_SENSOR -#define HALL_SI7210 +//#define HALL_SI7210 #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp index 5914270f..13fcacf3 100644 --- a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -31,3 +31,7 @@ int16_t getRawHallEffect() { return 0; } + +bool getHallSensorFitted() { + return hall_effect_present; +} diff --git a/workspace/TS100/GD32VF103xB.ld b/workspace/TS100/GD32VF103xB.ld index 83ce13a0..204f7ca8 100644 --- a/workspace/TS100/GD32VF103xB.ld +++ b/workspace/TS100/GD32VF103xB.ld @@ -7,11 +7,6 @@ MEMORY /* Run in FLASH */ flash (rxai!w) : ORIGIN = 0x08000000, LENGTH = 128k ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 32K - - /* Run in RAM */ -/* flash (rxai!w) : ORIGIN = 0x20000000, LENGTH = 24k - ram (wxa!ri) : ORIGIN = 0x20006000, LENGTH = 8K -*/ } @@ -173,4 +168,4 @@ SECTIONS . = __stack_size; PROVIDE( _sp = . ); } >ram AT>ram -} +} \ No newline at end of file From ba5bd39e43f0ffb348396cc501d8252c9066a498 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 31 Oct 2020 00:03:44 +1100 Subject: [PATCH 40/72] Cleanup stubs so that LTO can be used on Pinecil --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 717 +++++++++--------- .../TS100/Core/BSP/Pine64/Model_Config.h | 2 +- .../TS100/Core/BSP/Pine64/N200/portmacro.h | 1 + .../Pine64/Vendor/Lib/Stubs/clock_getres.c | 13 + .../Pine64/Vendor/Lib/Stubs/clock_gettime.c | 20 + .../Pine64/Vendor/Lib/Stubs/clock_settime.c | 9 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/close.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/execve.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/exit.c | 9 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/fork.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/fstat.c | 18 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/getpid.c | 7 + .../Pine64/Vendor/Lib/Stubs/gettimeofday.c | 14 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/isatty.c | 7 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/kill.c | 10 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/link.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/lseek.c | 10 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/open.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/read.c | 10 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/sbrk.c | 9 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/stat.c | 8 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/times.c | 26 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/unlink.c | 11 + .../Core/BSP/Pine64/Vendor/Lib/Stubs/wait.c | 12 + .../Vendor/Lib/{read.c => Stubs/write.c} | 8 +- .../Core/BSP/Pine64/Vendor/Lib/handlers.c | 5 - .../TS100/Core/BSP/Pine64/Vendor/Lib/init.c | 2 + .../TS100/Core/BSP/Pine64/Vendor/Lib/stub.h | 3 +- .../TS100/Core/BSP/Pine64/Vendor/Lib/write.c | 47 -- .../Core/BSP/Pine64/Vendor/RISCV/n200_func.h | 2 +- workspace/TS100/Core/BSP/Pine64/postRTOS.cpp | 9 +- workspace/TS100/Core/Drivers/Si7210.cpp | 6 +- workspace/TS100/Core/Src/syscalls.c | 95 --- workspace/TS100/Core/Src/sysmem.c | 18 - workspace/TS100/Core/Threads/GUIThread.cpp | 13 +- 35 files changed, 639 insertions(+), 537 deletions(-) create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_getres.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_gettime.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_settime.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/close.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/execve.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/exit.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fork.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fstat.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/getpid.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/gettimeofday.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/isatty.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/kill.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/link.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/lseek.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/open.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/read.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/sbrk.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/stat.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/times.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/unlink.c create mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/wait.c rename workspace/TS100/Core/BSP/Pine64/Vendor/Lib/{read.c => Stubs/write.c} (59%) delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c delete mode 100644 workspace/TS100/Core/Src/sysmem.c diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index f24f0d81..3eb6e728 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -12,392 +12,403 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; #define I2C_TIME_OUT (uint16_t)(5000) void FRToSI2C::CpltCallback() { - //TODO + //TODO } bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - return Mem_Write(address, reg, &data, 1); + return Mem_Write(address, reg, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t temp = 0; - Mem_Read(add, reg, &temp, 1); - return temp; + uint8_t temp = 0; + Mem_Read(add, reg, &temp, 1); + return temp; } bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - dma_parameter_struct dma_init_struct; + if (!lock()) + return false; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint8_t in_rx_cycle = 0; - uint16_t timeout = 0; - uint8_t i2c_timeout_flag = 0; - while (!(i2c_timeout_flag)) { - switch (state) { - case I2C_START: - if (0 == in_rx_cycle) { - /* disable I2C0 */ - i2c_disable(I2C0); - /* enable I2C0 */ - i2c_enable(I2C0); + uint8_t state = I2C_START; + uint8_t in_rx_cycle = 0; + uint16_t timeout = 0; + uint8_t tries = 0; + uint8_t i2c_timeout_flag = 0; + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + tries++; + if (tries > 64) { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + unlock(); + return false; + } + if (0 == in_rx_cycle) { + /* disable I2C0 */ + i2c_disable(I2C0); + /* enable I2C0 */ + i2c_enable(I2C0); - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the start signal */ - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - } else { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - if (RESET == in_rx_cycle) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); - state = I2C_CLEAR_ADDRESS_FLAG; - } - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - break; - case I2C_TRANSMIT_DATA: - if (0 == in_rx_cycle) { - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - //Write out the 8 byte address - i2c_data_transmit(I2C0, read_address); - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - /* wait until BTC bit is set */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_START; - in_rx_cycle = 1; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - } else { - /* one byte master reception procedure (polling) */ - if (number_of_byte < 2) { - /* disable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ - i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - /* wait for the byte to be received */ - while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) - ; - /* read the byte received from the EEPROM */ - *p_buffer = i2c_data_receive(I2C0); - /* decrement the read bytes counter */ - number_of_byte--; - timeout = 0; - } else { /* more than one byte master reception procedure (DMA) */ - dma_deinit(DMA0, DMA_CH6); - dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_init_struct.memory_addr = (uint32_t)p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH6, &dma_init_struct); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the start signal */ + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + } else { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + if (RESET == in_rx_cycle) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + if (0 == in_rx_cycle) { + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + //Write out the 8 byte address + i2c_data_transmit(I2C0, read_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + in_rx_cycle = 1; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + } else { + /* one byte master reception procedure (polling) */ + if (number_of_byte < 2) { + /* disable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ + i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + /* wait for the byte to be received */ + while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) + ; + /* read the byte received from the EEPROM */ + *p_buffer = i2c_data_receive(I2C0); + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } else { /* more than one byte master reception procedure (DMA) */ + dma_deinit(DMA0, DMA_CH6); + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_init_struct.memory_addr = (uint32_t) p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH6, &dma_init_struct); - i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH6); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { - osDelay(1); - } - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - } - timeout = 0; - state = I2C_STOP; - } - break; - case I2C_STOP: - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - i2c_timeout_flag = I2C_OK; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - default: - state = I2C_START; - in_rx_cycle = 0; - i2c_timeout_flag = I2C_OK; - timeout = 0; - break; - } - } - unlock(); - return true; + i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH6); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { + osDelay(1); + } + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + default: + state = I2C_START; + in_rx_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; + break; + } + } + unlock(); + return true; } bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; + if (!lock()) + return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - dma_parameter_struct dma_init_struct; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint16_t timeout = 0; - bool done = false; - bool timedout = false; - while (!(done || timedout)) { - switch (state) { - case I2C_START: - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - timeout = 0; - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - //Dont retry as this means a NAK - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - unlock(); - return false; - } - break; - case I2C_TRANSMIT_DATA: - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the EEPROM's internal address to write to : only one byte address */ - i2c_data_transmit(I2C0, MemAddress); - timeout = 0; - } else { - timedout = true; - timeout = 0; - state = I2C_START; - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - dma_deinit(DMA0, DMA_CH5); - dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; - dma_init_struct.memory_addr = (uint32_t)p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH5, &dma_init_struct); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH5); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { - osDelay(1); - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - state = I2C_STOP; - break; - case I2C_STOP: - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - done = true; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - default: - state = I2C_START; - timeout = 0; - break; - } - } - unlock(); - return timedout == false; + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + //Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(I2C0, MemAddress); + timeout = 0; + } else { + timedout = true; + timeout = 0; + state = I2C_START; + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + dma_deinit(DMA0, DMA_CH5); + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_addr = (uint32_t) p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH5, &dma_init_struct); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH5); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { + osDelay(1); + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + state = I2C_STOP; + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); + return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); } bool FRToSI2C::probe(uint16_t DevAddress) { - uint8_t temp[1]; - return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); + uint8_t temp[1]; + return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); } void FRToSI2C::I2C_Unstick() { - unstick_I2C(); + unstick_I2C(); } bool FRToSI2C::lock() { - if (I2CSemaphore == nullptr) { - return false; - } - return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; + if (I2CSemaphore == nullptr) { + return false; + } + return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; } void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); + xSemaphoreGive(I2CSemaphore); } bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) { - delay_ms(registers[index].pause_ms); - } - } - return true; + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { + return false; + } + if (registers[index].pause_ms) { + delay_ms(registers[index].pause_ms); + } + } + return true; } diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 7587cc60..2c6a0c84 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -21,7 +21,7 @@ #define TEMP_TMP36 #define ACCEL_BMA #define HALL_SENSOR -//#define HALL_SI7210 +#define HALL_SI7210 #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h index 351f9f56..4358333f 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h +++ b/workspace/TS100/Core/BSP/Pine64/N200/portmacro.h @@ -5,6 +5,7 @@ extern "C" { #endif +#include "n200_func.h" #include "riscv_encoding.h" /*----------------------------------------------------------- diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_getres.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_getres.c new file mode 100644 index 00000000..59eabc58 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_getres.c @@ -0,0 +1,13 @@ +/* See LICENSE of license details. */ +#include +#include +#include +#include "system_gd32vf103.h" +/* Get resolution of clock. */ + int clock_getres(clockid_t clock_id, struct timespec *res) +{ + res->tv_sec = 0; + res->tv_nsec = 1000000000 / SystemCoreClock; + + return 0; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_gettime.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_gettime.c new file mode 100644 index 00000000..efa6dea4 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_gettime.c @@ -0,0 +1,20 @@ +/* See LICENSE of license details. */ +#include +#include +#include + +extern int _gettimeofday(struct timeval *tp, void *tzp); + +/* Get current value of CLOCK and store it in tp. */ + int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + struct timeval tv; + int retval = -1; + + retval = _gettimeofday(&tv, NULL); + if (retval == 0) { + TIMEVAL_TO_TIMESPEC(&tv, tp); + } + + return retval; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_settime.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_settime.c new file mode 100644 index 00000000..3b3ed50c --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/clock_settime.c @@ -0,0 +1,9 @@ +/* See LICENSE of license details. */ +#include +#include + +/* Set CLOCK to value TP. */ + int clock_settime(clockid_t clock_id, const struct timespec *tp) +{ + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/close.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/close.c new file mode 100644 index 00000000..47849e9a --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/close.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int _close(int fd) +{ + errno = EBADF; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/execve.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/execve.c new file mode 100644 index 00000000..27ecd31d --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/execve.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int _execve(char *name, char **argv, char **env) +{ + errno = ENOMEM; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/exit.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/exit.c new file mode 100644 index 00000000..7cfe2707 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/exit.c @@ -0,0 +1,9 @@ +/* See LICENSE of license details. */ + +#include "n200_func.h" + void _exit(int fd) +{ + while(1) { + __WFI(); + } +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fork.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fork.c new file mode 100644 index 00000000..1d452c59 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fork.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int fork(void) +{ + errno = EAGAIN; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fstat.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fstat.c new file mode 100644 index 00000000..5ec53073 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/fstat.c @@ -0,0 +1,18 @@ +/* See LICENSE of license details. */ +#include +#include +#include + +#undef errno +extern int errno; + + int _fstat(int file, struct stat *st) +{ + if ((STDOUT_FILENO == file) || (STDERR_FILENO == file)) { + st->st_mode = S_IFCHR; + return 0; + } else { + errno = EBADF; + return -1; + } +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/getpid.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/getpid.c new file mode 100644 index 00000000..d1b3b17c --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/getpid.c @@ -0,0 +1,7 @@ +/* See LICENSE of license details. */ +#include + + int getpid(void) +{ + return 1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/gettimeofday.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/gettimeofday.c new file mode 100644 index 00000000..88d7781b --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/gettimeofday.c @@ -0,0 +1,14 @@ +/* See LICENSE of license details. */ +#include +#include +#include "system_gd32vf103.h" + int _gettimeofday(struct timeval *tp, void *tzp) +{ + uint64_t cycles; + + cycles = __get_rv_cycle(); + + tp->tv_sec = cycles / SystemCoreClock; + tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock; + return 0; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/isatty.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/isatty.c new file mode 100644 index 00000000..ae87d497 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/isatty.c @@ -0,0 +1,7 @@ +/* See LICENSE of license details. */ +#include + + int _isatty(int fd) +{ + return 1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/kill.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/kill.c new file mode 100644 index 00000000..c3a979c6 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/kill.c @@ -0,0 +1,10 @@ +/* See LICENSE of license details. */ +#include +#undef errno +extern int errno; + + int _kill(int pid, int sig) +{ + errno = EINVAL; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/link.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/link.c new file mode 100644 index 00000000..9928e65f --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/link.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + +int _link(char *old, char *new) +{ + errno = EMLINK; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/lseek.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/lseek.c new file mode 100644 index 00000000..7f3d2760 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/lseek.c @@ -0,0 +1,10 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int _lseek(int file, int offset, int whence) +{ + return 0; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/open.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/open.c new file mode 100644 index 00000000..d6aab254 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/open.c @@ -0,0 +1,11 @@ +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int _open(const char *name, int flags, int mode) +{ + errno = ENOSYS; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/read.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/read.c new file mode 100644 index 00000000..fb364683 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/read.c @@ -0,0 +1,10 @@ +/* See LICENSE of license details. */ +#include +#include +#include +#include + + +ssize_t _read(int fd, void* ptr, size_t len) { + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/sbrk.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/sbrk.c new file mode 100644 index 00000000..3339baaa --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/sbrk.c @@ -0,0 +1,9 @@ +/* See LICENSE of license details. */ +#include +#include +#include + + void *_sbrk(ptrdiff_t incr) +{ + return (void *)0; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/stat.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/stat.c new file mode 100644 index 00000000..92ce2903 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/stat.c @@ -0,0 +1,8 @@ +/* See LICENSE of license details. */ +#include + + int _stat(char *file, struct stat *st) +{ + st->st_mode = S_IFCHR; + return 0; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/times.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/times.c new file mode 100644 index 00000000..1c282597 --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/times.c @@ -0,0 +1,26 @@ +/* See LICENSE of license details. */ +#include +#include +#include + +extern int _gettimeofday(struct timeval *, void *); + + clock_t _times(struct tms *buf) +{ + static struct timeval t0; + struct timeval t; + long long utime; + + /* When called for the first time, initialize t0. */ + if (t0.tv_sec == 0 && t0.tv_usec == 0) { + _gettimeofday(&t0, 0); + } + + _gettimeofday(&t, 0); + + utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec); + buf->tms_utime = utime * CLOCKS_PER_SEC / 1000000; + buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0; + + return buf->tms_utime; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/unlink.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/unlink.c new file mode 100644 index 00000000..22b15afd --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/unlink.c @@ -0,0 +1,11 @@ + +/* See LICENSE of license details. */ +#include + +#undef errno +extern int errno; + + int _unlink(const char *name) +{ + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/wait.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/wait.c new file mode 100644 index 00000000..ff54036f --- /dev/null +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/wait.c @@ -0,0 +1,12 @@ +/* See LICENSE of license details. */ +#include +#include + +#undef errno +extern int errno; + + int _wait(int *status) +{ + errno = ECHILD; + return -1; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/write.c similarity index 59% rename from workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c rename to workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/write.c index c874f678..ffcf9cfc 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/read.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/Stubs/write.c @@ -1,13 +1,11 @@ /* See LICENSE of license details. */ - #include #include #include #include -#include "stub.h" - -ssize_t _read(int fd, void* ptr, size_t len) + ssize_t _write(int fd, const void* ptr, size_t len) { - return _stub(EBADF); + return -1; + } diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c index ecc22d05..c6e4e1df 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/handlers.c @@ -6,7 +6,6 @@ #include "n200_func.h" __attribute__((weak)) uintptr_t handle_nmi() { - write(1, "nmi\n", 5); _exit(1); return 0; } @@ -15,10 +14,6 @@ __attribute__((weak)) uintptr_t handle_trap(uintptr_t mcause, uintptr_t sp) { if ((mcause & 0xFFF) == 0xFFF) { handle_nmi(); } - write(1, "trap\n", 5); - printf("In trap handler, the mcause is %d\n", mcause); - printf("In trap handler, the mepc is 0x%x\n", read_csr(mepc)); - printf("In trap handler, the mtval is 0x%x\n", read_csr(mbadaddr)); _exit(mcause); return 0; } diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c index 39a72ab2..96fc9323 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/init.c @@ -32,3 +32,5 @@ void _init() void _fini() { } + + diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h index 791615c7..7056d663 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/stub.h @@ -14,9 +14,8 @@ static inline int _stub(int err) { return -1; } -void _exit(int code); #endif /* _NUCLEI_SYS_STUB_H */ #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c deleted file mode 100644 index 8836b701..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/write.c +++ /dev/null @@ -1,47 +0,0 @@ -/* See LICENSE of license details. */ - -#include -#include -#include -#include -#include -#include - -#include "stub.h" -#include "gd32vf103.h" - -typedef unsigned int size_t; - -extern int _put_char(int ch) __attribute__((weak)); - -ssize_t _write(int fd, const void* ptr, size_t len) { - const uint8_t * current = (const uint8_t *) ptr; - -// if (isatty(fd)) - { - for (size_t jj = 0; jj < len; jj++) { - _put_char(current[jj]); - - if (current[jj] == '\n') { - _put_char('\r'); - } - } - return len; - } - - return _stub(EBADF); -} - -int puts(const char* string) { - return _write(0, (const void *) string, strlen(string)); -} - -int _put_char(int ch) -{ - usart_data_transmit(USART0, (uint8_t) ch ); - while (usart_flag_get(USART0, USART_FLAG_TBE)== RESET){ - } - - return ch; -} - diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h index 6531d0b9..288f36c2 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/n200_func.h @@ -3,7 +3,7 @@ #ifndef N200_FUNC_H #define N200_FUNC_H - +#include #include #include "n200_timer.h" #include "n200_eclic.h" diff --git a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp index 13fcacf3..0d12d291 100644 --- a/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp +++ b/workspace/TS100/Core/BSP/Pine64/postRTOS.cpp @@ -14,15 +14,16 @@ bool hall_effect_present = false; void postRToSInit() { // Any after RTos setup -#ifdef POW_PD - //Spawn all of the USB-C processors - fusb302_start_processing(); -#endif #ifdef HALL_SI7210 if (Si7210::detect()) { hall_effect_present = Si7210::init(); } #endif +#ifdef POW_PD + //Spawn all of the USB-C processors + fusb302_start_processing(); +#endif + } int16_t getRawHallEffect() { if (hall_effect_present) { diff --git a/workspace/TS100/Core/Drivers/Si7210.cpp b/workspace/TS100/Core/Drivers/Si7210.cpp index 63bf4936..dbe60ace 100644 --- a/workspace/TS100/Core/Drivers/Si7210.cpp +++ b/workspace/TS100/Core/Drivers/Si7210.cpp @@ -9,7 +9,9 @@ #include "Si7210_defines.h" #include "I2C_Wrapper.hpp" bool Si7210::detect() { - return FRToSI2C::probe(SI7210_ADDRESS); + uint8_t temp; + return FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_ID, &temp, 1); + //Cant use normal probe as reg 0x00 is not used } bool Si7210::init() { @@ -30,6 +32,6 @@ bool Si7210::init() { int16_t Si7210::read() { //Read the two regs int16_t temp = 0; - FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_DATAH,(uint8_t*) &temp, 2); + FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_DATAH, (uint8_t*) &temp, 2); return __builtin_bswap16(temp); } diff --git a/workspace/TS100/Core/Src/syscalls.c b/workspace/TS100/Core/Src/syscalls.c index 1a0f4f8e..94e38850 100644 --- a/workspace/TS100/Core/Src/syscalls.c +++ b/workspace/TS100/Core/Src/syscalls.c @@ -8,16 +8,6 @@ #include #include -/* Variables */ -//#undef errno -extern int errno; -extern int __io_putchar(int ch) __attribute__((weak)); -extern int __io_getchar(void) __attribute__((weak)); - -register char *stack_ptr asm("sp"); - -char *__env[1] = { 0 }; -char **environ = __env; /* Functions */ void initialise_monitor_handles() { @@ -27,88 +17,3 @@ int _getpid(void) { return 1; } -int _kill(int pid, int sig) { - errno = EINVAL; - return -1; -} - -void _exit(int status) { - _kill(status, -1); - while (1) { - } /* Make sure we hang here */ -} - -__attribute__((weak)) int _read(int file, char *ptr, int len) { - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) { - *ptr++ = __io_getchar(); - } - - return len; -} - -__attribute__((weak)) int _write(int file, char *ptr, int len) { - int DataIdx; - - for (DataIdx = 0; DataIdx < len; DataIdx++) { - __io_putchar(*ptr++); - } - return len; -} - -int _close(int file) { - return -1; -} - -int _fstat(int file, struct stat *st) { - st->st_mode = S_IFCHR; - return 0; -} - -int _isatty(int file) { - return 1; -} - -int _lseek(int file, int ptr, int dir) { - return 0; -} - -int _open(char *path, int flags, ...) { - /* Pretend like we always fail */ - return -1; -} - -int _wait(int *status) { - errno = ECHILD; - return -1; -} - -int _unlink(char *name) { - errno = ENOENT; - return -1; -} - -int _times(struct tms *buf) { - return -1; -} - -int _stat(char *file, struct stat *st) { - st->st_mode = S_IFCHR; - return 0; -} - -int _link(char *old, char *new) { - errno = EMLINK; - return -1; -} - -int _fork(void) { - errno = EAGAIN; - return -1; -} - -int _execve(char *name, char **argv, char **env) { - errno = ENOMEM; - return -1; -} diff --git a/workspace/TS100/Core/Src/sysmem.c b/workspace/TS100/Core/Src/sysmem.c deleted file mode 100644 index fc88ed94..00000000 --- a/workspace/TS100/Core/Src/sysmem.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Includes */ -#include -#include - -/* Variables */ -extern int errno; -register char *stack_ptr asm("sp"); - -/* Functions */ - -/** - _sbrk - Increase program data space. Malloc and related functions depend on this - **/ -caddr_t _sbrk(int incr) { - return (void*) -1; -} - diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index f1b7604a..5563a8ae 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -386,7 +386,6 @@ static bool shouldBeSleeping() { #ifdef HALL_SENSOR //If the hall effect sensor is enabled in the build, check if its over threshold, and if so then we force sleep - #endif return false; } @@ -620,9 +619,7 @@ uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { OLED::initialize(); // start up the LCD -// for (;;) { -// osDelay(2000); -// } + uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; @@ -657,6 +654,14 @@ void startGUITask(void const *argument __unused) { OLED::refresh(); waitForButtonPressOrTimeout(10000); } + if (getHallSensorFitted()) { + OLED::clearScreen(); + OLED::setFont(1); + OLED::setCursor(0, 0); + OLED::printNumber(5000, 4, 0); + OLED::refresh(); + waitForButtonPressOrTimeout(10000); + } if (systemSettings.autoStartMode) { // jump directly to the autostart mode if (systemSettings.autoStartMode == 1) { From 1f4ed60838d2d13d5a58d53ecd910deeb11f0198 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 31 Oct 2020 00:15:30 +1100 Subject: [PATCH 41/72] Wake Halleffect correctly helps..... --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 107 ++++++++++++++++++ workspace/TS100/Core/BSP/Pine64/Setup.c | 2 +- workspace/TS100/Core/Drivers/I2C_Wrapper.hpp | 2 +- workspace/TS100/Core/Drivers/Si7210.cpp | 4 +- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 3eb6e728..90818c4d 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -412,3 +412,110 @@ bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *register } return true; } + +bool FRToSI2C::wakePart(uint16_t DevAddress) { + //wakepart is a special case where only the device address is sent + if (!lock()) + return false; + + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; + + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + //Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_STOP; + } else { + //Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + unlock(); + return false; + } + break; + + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; +} diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index f48862be..314f894c 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -115,7 +115,7 @@ void setup_i2c() { /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); //Setup I20 at 400kHz - i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_2); + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); i2c_enable(I2C0); /* enable acknowledge */ diff --git a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp index ca4a50a4..9d5996df 100644 --- a/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp +++ b/workspace/TS100/Core/Drivers/I2C_Wrapper.hpp @@ -34,7 +34,7 @@ public: static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size); //Returns true if device ACK's being addressed static bool probe(uint16_t DevAddress); - + static bool wakePart(uint16_t DevAddress); static bool Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size); static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx); diff --git a/workspace/TS100/Core/Drivers/Si7210.cpp b/workspace/TS100/Core/Drivers/Si7210.cpp index dbe60ace..d3ef1686 100644 --- a/workspace/TS100/Core/Drivers/Si7210.cpp +++ b/workspace/TS100/Core/Drivers/Si7210.cpp @@ -10,8 +10,8 @@ #include "I2C_Wrapper.hpp" bool Si7210::detect() { uint8_t temp; - return FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_ID, &temp, 1); - //Cant use normal probe as reg 0x00 is not used + return FRToSI2C::wakePart(SI7210_ADDRESS); + } bool Si7210::init() { From a1a7eb9e598b1e3639d4c30429e8223a7717c6c4 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sat, 31 Oct 2020 15:45:36 +1100 Subject: [PATCH 42/72] Hall Effect sensor working in higher range --- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 172 +++++++++--------- workspace/TS100/Core/Drivers/Si7210.cpp | 159 +++++++++++++++- workspace/TS100/Core/Drivers/Si7210.h | 6 + workspace/TS100/Core/Drivers/Si7210_defines.h | 78 +++++++- 4 files changed, 320 insertions(+), 95 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index 90818c4d..f1e9f25b 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -293,9 +293,9 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_bu return false; } } + timeout = 0; if (timeout < I2C_TIME_OUT) { i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; state = I2C_TRANSMIT_DATA; } else { //Dont retry as this means a NAK @@ -416,106 +416,106 @@ bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *register bool FRToSI2C::wakePart(uint16_t DevAddress) { //wakepart is a special case where only the device address is sent if (!lock()) - return false; + return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - dma_parameter_struct dma_init_struct; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint16_t timeout = 0; - bool done = false; - bool timedout = false; - while (!(done || timedout)) { - switch (state) { - case I2C_START: - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - timeout = 0; - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_STOP; - } else { - //Dont retry as this means a NAK + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); i2c_stop_on_bus(I2C0); /* i2c master sends STOP signal successfully */ while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { timeout++; } + //Address NACK'd unlock(); return false; } - break; - - case I2C_STOP: - /* send a stop condition to I2C bus */ + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_STOP; + } else { + //Dont retry as this means a NAK i2c_stop_on_bus(I2C0); /* i2c master sends STOP signal successfully */ while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { timeout++; } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - done = true; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - default: - state = I2C_START; - timeout = 0; - break; + unlock(); + return false; } + break; + + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; } - unlock(); - return timedout == false; + } + unlock(); + return timedout == false; } diff --git a/workspace/TS100/Core/Drivers/Si7210.cpp b/workspace/TS100/Core/Drivers/Si7210.cpp index d3ef1686..b3eae4ae 100644 --- a/workspace/TS100/Core/Drivers/Si7210.cpp +++ b/workspace/TS100/Core/Drivers/Si7210.cpp @@ -3,27 +3,61 @@ * * Created on: 5 Oct. 2020 * Author: Ralim + * + * This is based on the very nice sample code by Sean Farrelly (@FARLY7) + * Over here : https://github.com/FARLY7/si7210-driver + * + * This class is licensed as MIT to match this code base */ #include #include "Si7210_defines.h" #include "I2C_Wrapper.hpp" bool Si7210::detect() { - uint8_t temp; return FRToSI2C::wakePart(SI7210_ADDRESS); } bool Si7210::init() { //Turn on auto increment and sanity check ID + //Load OTP cal + uint8_t temp; if (FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_ID, &temp, 1)) { // We don't really care what model it is etc, just probing to check its probably this iC if (temp != 0x00 && temp != 0xFF) { - temp = 0x01; //turn on auto increment - if (FRToSI2C::Mem_Write(SI7210_ADDRESS, SI7210_REG_INCR, &temp, 1)) { - return true; + temp = 0x00; + + /* Set device and internal driver settings */ + if (!write_reg( SI7210_CTRL1, (uint8_t) ~SW_LOW4FIELD_MASK, 0)) { + return false; } + + /* Disable periodic auto-wakeup by device, and tamper detect. */ + if ((!write_reg(SI7210_CTRL3, (uint8_t) ~SL_TIMEENA_MASK, 0))) + return false; + + /* Disable tamper detection by setting sw_tamper to 63 */ + if (!write_reg(SI7210_CTRL3, SL_FAST_MASK | SL_TIMEENA_MASK, 63 << 2)) + return false; + + if (!set_high_range()) + return false; + + /* Stop the control loop by setting stop bit */ + if (!write_reg( SI7210_POWER_CTRL, MEAS_MASK | USESTORE_MASK, STOP_MASK)) /* WARNING: Removed USE_STORE MASK */ + return false; + + /* Use a burst size of 128/4096 samples in FIR and IIR modes */ + if (!write_reg(SI7210_CTRL4, 0, DF_BURSTSIZE_128 | DF_BW_4096)) + return false; + + /* Select field strength measurement */ + if (!write_reg( SI7210_DSPSIGSEL, 0, DSP_SIGSEL_FIELD_MASK)) + return false; + + return true; //start_periodic_measurement(); + } } return false; @@ -32,6 +66,119 @@ bool Si7210::init() { int16_t Si7210::read() { //Read the two regs int16_t temp = 0; - FRToSI2C::Mem_Read(SI7210_ADDRESS, SI7210_REG_DATAH, (uint8_t*) &temp, 2); - return __builtin_bswap16(temp); + if (!get_field_strength(&temp)) { + temp = 0; + } + return temp; +} + +bool Si7210::write_reg(const uint8_t reg, const uint8_t mask, const uint8_t val) { + uint8_t temp = 0; + if (mask) { + if (!read_reg(reg, &temp)) { + return false; + } + temp &= mask; + } + temp |= val; + return FRToSI2C::Mem_Write(SI7210_ADDRESS, reg, &temp, 1); +} + +bool Si7210::read_reg(const uint8_t reg, uint8_t* val) { + return FRToSI2C::Mem_Read(SI7210_ADDRESS, reg, val, 1); +} + +bool Si7210::start_periodic_measurement() { + /* Enable periodic wakeup */ + if (!write_reg(SI7210_CTRL3, (uint8_t) ~SL_TIMEENA_MASK, SL_TIMEENA_MASK)) + return false; + + /* Start measurement */ + /* Change to ~STOP_MASK with STOP_MASK */ + return write_reg( SI7210_POWER_CTRL, MEAS_MASK | USESTORE_MASK, 0); + +} + +bool Si7210::get_field_strength(int16_t* field) { + *field = 0; + uint8_t val = 0; + FRToSI2C::wakePart(SI7210_ADDRESS); + + if (!write_reg( SI7210_POWER_CTRL, MEAS_MASK | USESTORE_MASK, STOP_MASK)) + return false; + + /* Read most-significant byte */ + if (!read_reg( SI7210_DSPSIGM, &val)) + return false; + *field = (val & DSP_SIGM_DATA_MASK) << 8; + + /* Read least-significant byte of data */ + if (!read_reg( SI7210_DSPSIGL, &val)) + return false; + + *field += val; + *field -= 16384U; + //field is now a +- measurement + //In units of 0.0125 mT + // Aka 12.5uT + //Clear flags + read_reg( SI7210_CTRL1, &val); + read_reg( SI7210_CTRL2, &val); +//Start next one + + /* Use a burst size of 128/4096 samples in FIR and IIR modes */ + write_reg( SI7210_CTRL4, 0, DF_BURSTSIZE_128 | DF_BW_4096); + + /* Selet field strength measurement */ + write_reg( SI7210_DSPSIGSEL, 0, DSP_SIGSEL_FIELD_MASK); + + /* Start measurement */ + write_reg( SI7210_POWER_CTRL, MEAS_MASK | USESTORE_MASK, ONEBURST_MASK); + + return true; +} + +bool Si7210::set_high_range() { + //To set the unit into 200mT range, no magnet temperature calibration + // We want to copy OTP 0x27->0x2C into a0->a5 + uint8_t base_addr = 0x27; // You can change this to pick the temp calibration + bool worked = true; + uint8_t val = 0; + + /* Load A0 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A0, 0, val); + + /* Load A1 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr + 1); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A1, 0, val); + + /* Load A2 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr + 2); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A2, 0, val); + + /* Load A3 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr + 3); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A3, 0, val); + + /* Load A4 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr + 4); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A4, 0, val); + + /* Load A5 register */ + worked &= write_reg( SI7210_OTP_ADDR, 0, base_addr + 5); + worked &= write_reg( SI7210_OTP_CTRL, 0, OTP_READ_EN_MASK); + worked &= read_reg( SI7210_OTP_DATA, &val); + worked &= write_reg( SI7210_A5, 0, val); + return worked; } diff --git a/workspace/TS100/Core/Drivers/Si7210.h b/workspace/TS100/Core/Drivers/Si7210.h index 5f0477b5..ed99ba2b 100644 --- a/workspace/TS100/Core/Drivers/Si7210.h +++ b/workspace/TS100/Core/Drivers/Si7210.h @@ -16,6 +16,12 @@ public: static bool init(); static int16_t read(); private: + static bool write_reg(const uint8_t reg,const uint8_t mask,const uint8_t val); + static bool read_reg(const uint8_t reg, uint8_t *val); + static bool start_periodic_measurement(); + static bool get_field_strength(int16_t *field); + static bool set_high_range(); + }; #endif /* CORE_DRIVERS_SI7210_H_ */ diff --git a/workspace/TS100/Core/Drivers/Si7210_defines.h b/workspace/TS100/Core/Drivers/Si7210_defines.h index 3a7dc13d..a7123069 100644 --- a/workspace/TS100/Core/Drivers/Si7210_defines.h +++ b/workspace/TS100/Core/Drivers/Si7210_defines.h @@ -10,9 +10,81 @@ #define SI7210_ADDRESS (0x30<<1) #define SI7210_REG_ID 0xC0 -#define SI7210_REG_DATAH 0xC1 -#define SI7210_REG_DATAL 0xC2 -#define SI7210_REG_INCR 0xC5 + +/* Si7210 Register addresses */ +#define SI7210_HREVID 0xC0U +#define SI7210_DSPSIGM 0xC1U +#define SI7210_DSPSIGL 0xC2U +#define SI7210_DSPSIGSEL 0xC3U +#define SI7210_POWER_CTRL 0xC4U +#define SI7210_ARAUTOINC 0xC5U +#define SI7210_CTRL1 0xC6U +#define SI7210_CTRL2 0xC7U +#define SI7210_SLTIME 0xC8U +#define SI7210_CTRL3 0xC9U +#define SI7210_A0 0xCAU +#define SI7210_A1 0xCBU +#define SI7210_A2 0xCCU +#define SI7210_CTRL4 0xCDU +#define SI7210_A3 0xCEU +#define SI7210_A4 0xCFU +#define SI7210_A5 0xD0U +#define SI7210_OTP_ADDR 0xE1U +#define SI7210_OTP_DATA 0xE2U +#define SI7210_OTP_CTRL 0xE3U +#define SI7210_TM_FG 0xE4U + +/* Si7210 Register bit masks */ +#define CHIP_ID_MASK 0xF0U +#define REV_ID_MASK 0x0FU +#define DSP_SIGSEL_MASK 0x07U +#define MEAS_MASK 0x80U +#define USESTORE_MASK 0x08U +#define ONEBURST_MASK 0x04U +#define STOP_MASK 0x02U +#define SLEEP_MASK 0x01U +#define ARAUTOINC_MASK 0x01U +#define SW_LOW4FIELD_MASK 0x80U +#define SW_OP_MASK 0x7FU +#define SW_FIELDPOLSEL_MASK 0xC0U +#define SW_HYST_MASK 0x3FU +#define SW_TAMPER_MASK 0xFCU +#define SL_FAST_MASK 0x02U +#define SL_TIMEENA_MASK 0x01U +#define DF_BURSTSIZE_MASK 0xE0U +#define DF_BW_MASK 0x1EU +#define DF_IIR_MASK 0x01U +#define OTP_READ_EN_MASK 0x02U +#define OTP_BUSY_MASK 0x01U +#define TM_FG_MASK 0x03U + +#define DSP_SIGM_DATA_FLAG 0x80U +#define DSP_SIGM_DATA_MASK 0x7FU +#define DSP_SIGSEL_TEMP_MASK 0x01U +#define DSP_SIGSEL_FIELD_MASK 0x04U + +/* Burst sizes */ +#define DF_BW_1 0x0U << 1 +#define DF_BW_2 0x1U << 1 +#define DF_BW_4 0x2U << 1 +#define DF_BW_8 0x3U << 1 +#define DF_BW_16 0x4U << 1 +#define DF_BW_32 0x5U << 1 +#define DF_BW_64 0x6U << 1 +#define DF_BW_128 0x7U << 1 +#define DF_BW_256 0x8U << 1 +#define DF_BW_512 0x9U << 1 +#define DF_BW_1024 0xAU << 1 +#define DF_BW_2048 0xBU << 1 +#define DF_BW_4096 0xCU << 1 +#define DF_BURSTSIZE_1 0x0U << 5 +#define DF_BURSTSIZE_2 0x1U << 5 +#define DF_BURSTSIZE_4 0x2U << 5 +#define DF_BURSTSIZE_8 0x3U << 5 +#define DF_BURSTSIZE_16 0x4U << 5 +#define DF_BURSTSIZE_32 0x5U << 5 +#define DF_BURSTSIZE_64 0x6U << 5 +#define DF_BURSTSIZE_128 0x7U << 5 From 13af7c258ef571429dbed4fd592a25fdb9ff6626 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 10:38:21 +1100 Subject: [PATCH 43/72] Add Sensitivities for Hall Effect --- Translation Editor/translation_bg.json | 5 ++++- Translation Editor/translation_cs.json | 5 ++++- Translation Editor/translation_da.json | 5 ++++- Translation Editor/translation_de.json | 5 ++++- Translation Editor/translation_en.json | 12 +++++++++++- Translation Editor/translation_es.json | 5 ++++- Translation Editor/translation_fi.json | 5 ++++- Translation Editor/translation_fr.json | 5 ++++- Translation Editor/translation_hr.json | 5 ++++- Translation Editor/translation_hu.json | 5 ++++- Translation Editor/translation_it.json | 5 ++++- Translation Editor/translation_lt.json | 5 ++++- Translation Editor/translation_nl.json | 5 ++++- Translation Editor/translation_nl_be.json | 5 ++++- Translation Editor/translation_no.json | 5 ++++- Translation Editor/translation_pl.json | 5 ++++- Translation Editor/translation_pt.json | 5 ++++- Translation Editor/translation_ru.json | 5 ++++- Translation Editor/translation_sk.json | 5 ++++- Translation Editor/translation_sl.json | 5 ++++- Translation Editor/translation_sr_cyrl.json | 5 ++++- Translation Editor/translation_sr_latn.json | 5 ++++- Translation Editor/translation_sv.json | 5 ++++- Translation Editor/translation_tr.json | 5 ++++- Translation Editor/translation_uk.json | 5 ++++- Translation Editor/translations_def.js | 17 +++++++++++++++++ 26 files changed, 124 insertions(+), 25 deletions(-) diff --git a/Translation Editor/translation_bg.json b/Translation Editor/translation_bg.json index b5b477a7..572143e2 100644 --- a/Translation Editor/translation_bg.json +++ b/Translation Editor/translation_bg.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_cs.json b/Translation Editor/translation_cs.json index 05195a17..068d4cbd 100755 --- a/Translation Editor/translation_cs.json +++ b/Translation Editor/translation_cs.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_da.json b/Translation Editor/translation_da.json index 1b5033ca..634ccd16 100644 --- a/Translation Editor/translation_da.json +++ b/Translation Editor/translation_da.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "L", "SettingStartSleepChar": "D", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "S" + "SettingStartNoneChar": "S", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_de.json b/Translation Editor/translation_de.json index 7603b9bb..96783a52 100644 --- a/Translation Editor/translation_de.json +++ b/Translation Editor/translation_de.json @@ -35,7 +35,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_en.json b/Translation Editor/translation_en.json index 1a039077..28d65f0e 100644 --- a/Translation Editor/translation_en.json +++ b/Translation Editor/translation_en.json @@ -35,7 +35,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { @@ -249,6 +252,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting the stand" } } } diff --git a/Translation Editor/translation_es.json b/Translation Editor/translation_es.json index 7357d144..4e737990 100644 --- a/Translation Editor/translation_es.json +++ b/Translation Editor/translation_es.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "S", "SettingStartSleepChar": "R", "SettingStartSleepOffChar": "F", - "SettingStartNoneChar": "N" + "SettingStartNoneChar": "N", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_fi.json b/Translation Editor/translation_fi.json index eac2bff9..f2ed1135 100644 --- a/Translation Editor/translation_fi.json +++ b/Translation Editor/translation_fi.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_fr.json b/Translation Editor/translation_fr.json index 0ee8ec52..98ef2818 100644 --- a/Translation Editor/translation_fr.json +++ b/Translation Editor/translation_fr.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "A", "SettingStartSleepChar": "V", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "D" + "SettingStartNoneChar": "D", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_hr.json b/Translation Editor/translation_hr.json index f1d5708d..6a206bfd 100644 --- a/Translation Editor/translation_hr.json +++ b/Translation Editor/translation_hr.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_hu.json b/Translation Editor/translation_hu.json index 42928cbc..5e7d9029 100644 --- a/Translation Editor/translation_hu.json +++ b/Translation Editor/translation_hu.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_it.json b/Translation Editor/translation_it.json index b0adc38d..863ea218 100644 --- a/Translation Editor/translation_it.json +++ b/Translation Editor/translation_it.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "A", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "D" + "SettingStartNoneChar": "D", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_lt.json b/Translation Editor/translation_lt.json index 2af028e4..8761a0d3 100644 --- a/Translation Editor/translation_lt.json +++ b/Translation Editor/translation_lt.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_nl.json b/Translation Editor/translation_nl.json index b592d6b3..ebf90b86 100644 --- a/Translation Editor/translation_nl.json +++ b/Translation Editor/translation_nl.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_nl_be.json b/Translation Editor/translation_nl_be.json index 9404c78a..d23ca854 100644 --- a/Translation Editor/translation_nl_be.json +++ b/Translation Editor/translation_nl_be.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_no.json b/Translation Editor/translation_no.json index ddecb065..d9da9b64 100644 --- a/Translation Editor/translation_no.json +++ b/Translation Editor/translation_no.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "L", "SettingStartSleepChar": "D", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "I" + "SettingStartNoneChar": "I", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_pl.json b/Translation Editor/translation_pl.json index e158629c..1b60095c 100644 --- a/Translation Editor/translation_pl.json +++ b/Translation Editor/translation_pl.json @@ -35,7 +35,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "Z", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "B" + "SettingStartNoneChar": "B", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_pt.json b/Translation Editor/translation_pt.json index e66e93dd..b4cb1927 100644 --- a/Translation Editor/translation_pt.json +++ b/Translation Editor/translation_pt.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_ru.json b/Translation Editor/translation_ru.json index 9723c112..d0b91f79 100644 --- a/Translation Editor/translation_ru.json +++ b/Translation Editor/translation_ru.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "П", "SettingStartSleepChar": "О", "SettingStartSleepOffChar": "К", - "SettingStartNoneChar": "В" + "SettingStartNoneChar": "В", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_sk.json b/Translation Editor/translation_sk.json index 225e95c1..d3b99688 100644 --- a/Translation Editor/translation_sk.json +++ b/Translation Editor/translation_sk.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "S", "SettingStartSleepChar": "K", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "N" + "SettingStartNoneChar": "N", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_sl.json b/Translation Editor/translation_sl.json index 53e6654d..4714ae0f 100644 --- a/Translation Editor/translation_sl.json +++ b/Translation Editor/translation_sl.json @@ -33,7 +33,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_sr_cyrl.json b/Translation Editor/translation_sr_cyrl.json index 13447f5a..1d478fec 100644 --- a/Translation Editor/translation_sr_cyrl.json +++ b/Translation Editor/translation_sr_cyrl.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_sr_latn.json b/Translation Editor/translation_sr_latn.json index f4c2cd32..f54d20c9 100644 --- a/Translation Editor/translation_sr_latn.json +++ b/Translation Editor/translation_sr_latn.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_sv.json b/Translation Editor/translation_sv.json index eb6a37d5..76dafe3e 100644 --- a/Translation Editor/translation_sv.json +++ b/Translation Editor/translation_sv.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_tr.json b/Translation Editor/translation_tr.json index a97ae469..711dfc6e 100644 --- a/Translation Editor/translation_tr.json +++ b/Translation Editor/translation_tr.json @@ -32,7 +32,10 @@ "SettingStartSolderingChar": "T", "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", - "SettingStartNoneChar": "F" + "SettingStartNoneChar": "F", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translation_uk.json b/Translation Editor/translation_uk.json index b689ef20..1803c213 100644 --- a/Translation Editor/translation_uk.json +++ b/Translation Editor/translation_uk.json @@ -34,7 +34,10 @@ "SettingStartSolderingChar": "П", "SettingStartSleepChar": "О", "SettingStartSleepOffChar": "К", - "SettingStartNoneChar": "В" + "SettingStartNoneChar": "В", + "SettingSensitivityLow":"L", + "SettingSensitivityMedium":"M", + "SettingSensitivityHigh":"H" }, "menuGroups": { "SolderingMenu": { diff --git a/Translation Editor/translations_def.js b/Translation Editor/translations_def.js index df9a3df3..a9cb11e6 100644 --- a/Translation Editor/translations_def.js +++ b/Translation Editor/translations_def.js @@ -132,6 +132,18 @@ var def = { "id": "SettingStartNoneChar", "len": 1 + }, + { + "id": "SettingSensitivityLow", + "len": 1 + }, + { + "id": "SettingSensitivityMedium", + "len": 1 + }, + { + "id": "SettingSensitivityHigh", + "len": 1 } ], "menuGroups": [ @@ -282,6 +294,11 @@ var def = "id": "TipGain", "maxLen": 6, "maxLen2": 8 + }, + { + "id": "HallEffSensitivity", + "maxLen": 6, + "maxLen2": 8 } ] } From e612c4751f720e6ff409eb827100c468b3fadf91 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 10:38:32 +1100 Subject: [PATCH 44/72] Defines for time periods for cleaning up --- workspace/TS100/Core/BSP/Defines.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Defines.h b/workspace/TS100/Core/BSP/Defines.h index 52556f99..2392b7bf 100644 --- a/workspace/TS100/Core/BSP/Defines.h +++ b/workspace/TS100/Core/BSP/Defines.h @@ -15,5 +15,7 @@ enum Orientation { //It is assumed that all hardware implements an 8Hz update period at this time #define PID_TIM_HZ (8) - +#define TICKS_SECOND configTICK_RATE_HZ +#define TICKS_MIN (60*TICKS_SECOND) +#define TICKS_100MS (TICKS_SECOND/10) #endif /* BSP_DEFINES_H_ */ From b1abe391dc1814b94f619b2c2192cad6aa2580f6 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 10:45:08 +1100 Subject: [PATCH 45/72] Hall Effect Sensitivities --- workspace/TS100/Core/Inc/Settings.h | 4 ++-- workspace/TS100/Core/Src/Settings.cpp | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index 6ade2cfb..1e5bd9a4 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -54,8 +54,7 @@ typedef struct { uint8_t ReverseButtonTempChangeEnabled; // Change the plus and minus button assigment uint16_t TempChangeLongStep; // Change the plus and minus button assigment uint16_t TempChangeShortStep; // Change the plus and minus button assigment - uint8_t hallEffectMode; //Operating mode of the hall effect sensor - int16_t hallEffectThreshold; //Threshold of the halleffect sensor + uint8_t hallEffectSensitivity; //Operating mode of the hall effect sensor uint32_t padding; // This is here for in case we are not an even divisor so // that nothing gets cut off //MUST BE LAST @@ -67,6 +66,7 @@ extern volatile systemSettingsType systemSettings; void saveSettings(); bool restoreSettings(); uint8_t lookupVoltageLevel(uint8_t level); +uint16_t lookupHallEffectThreshold(); void resetSettings(); #endif /* SETTINGS_H_ */ diff --git a/workspace/TS100/Core/Src/Settings.cpp b/workspace/TS100/Core/Src/Settings.cpp index 77cc341f..88d135b7 100644 --- a/workspace/TS100/Core/Src/Settings.cpp +++ b/workspace/TS100/Core/Src/Settings.cpp @@ -67,7 +67,7 @@ void resetSettings() { systemSettings.autoStartMode = AUTO_START_MODE; // Auto start off for safety systemSettings.coolingTempBlink = COOLING_TEMP_BLINK; // Blink the temperature on the cooling screen when its > 50C #ifdef ENABLED_FAHRENHEIT_SUPPORT - systemSettings.temperatureInF = TEMPERATURE_INF; // default to 0 + systemSettings.temperatureInF = TEMPERATURE_INF; // default to 0 #endif systemSettings.descriptionScrollSpeed = DESCRIPTION_SCROLL_SPEED; // default to slow systemSettings.CalibrationOffset = CALIBRATION_OFFSET; // the adc offset in uV @@ -77,5 +77,22 @@ void resetSettings() { systemSettings.TempChangeLongStep = TEMP_CHANGE_LONG_STEP; // systemSettings.KeepAwakePulse = POWER_PULSE_DEFAULT; systemSettings.TipGain = TIP_GAIN; + systemSettings.hallEffectSensitivity=1; saveSettings(); // Save defaults } + +uint16_t lookupHallEffectThreshold() { + // Return the threshold above which the hall effect sensor is "activated" + switch (systemSettings.hallEffectSensitivity) { + case 0: + return 0; + case 1: //Low + return 1000; + case 2: //Medium + return 500; + case 3: //High + return 100; + default: + return 0; //Off + } +} From 5e5a5ceb4273e900209ed1f13d284e39a5c34305 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 10:45:22 +1100 Subject: [PATCH 46/72] Export Sensitivities from Translations --- workspace/TS100/Core/Inc/Translation.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Inc/Translation.h b/workspace/TS100/Core/Inc/Translation.h index b0ef244b..8915d6d4 100644 --- a/workspace/TS100/Core/Inc/Translation.h +++ b/workspace/TS100/Core/Inc/Translation.h @@ -51,6 +51,9 @@ extern const char *SettingStartSolderingChar; extern const char *SettingStartSleepChar; extern const char *SettingStartSleepOffChar; extern const char *SettingStartNoneChar; +extern const char* SettingSensitivityLow; +extern const char* SettingSensitivityMedium; +extern const char* SettingSensitivityHigh; extern const char *SettingFastChar; extern const char *SettingSlowChar; @@ -62,7 +65,7 @@ extern const char *SymbolSpace; extern const char *SymbolDot; extern const char *SymbolDegC; #ifdef ENABLED_FAHRENHEIT_SUPPORT - extern const char *SymbolDegF; +extern const char *SymbolDegF; #endif extern const char *SymbolMinutes; extern const char *SymbolSeconds; From ac9f863dbafe3c19797c0df825987f7817f74862 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 11:18:00 +1100 Subject: [PATCH 47/72] Adding in new gui settings for the hall effect sensitivity --- Translation Editor/translation_bg.json | 8 + Translation Editor/translation_cs.json | 8 + Translation Editor/translation_da.json | 8 + Translation Editor/translation_de.json | 8 + Translation Editor/translation_en.json | 3 +- Translation Editor/translation_es.json | 8 + Translation Editor/translation_fi.json | 8 + Translation Editor/translation_fr.json | 8 + Translation Editor/translation_hr.json | 8 + Translation Editor/translation_hu.json | 8 + Translation Editor/translation_it.json | 8 + Translation Editor/translation_lt.json | 8 + Translation Editor/translation_nl.json | 8 + Translation Editor/translation_nl_be.json | 8 + Translation Editor/translation_no.json | 8 + Translation Editor/translation_pl.json | 8 + Translation Editor/translation_pt.json | 8 + Translation Editor/translation_ru.json | 8 + Translation Editor/translation_sk.json | 8 + Translation Editor/translation_sl.json | 8 + Translation Editor/translation_sr_cyrl.json | 8 + Translation Editor/translation_sr_latn.json | 8 + Translation Editor/translation_sv.json | 8 + Translation Editor/translation_tr.json | 8 + Translation Editor/translation_uk.json | 8 + Translation Editor/translations_def.js | 4 + workspace/TS100/Core/Inc/Translation.h | 7 +- workspace/TS100/Core/Src/gui.cpp | 172 ++++++++++---------- 28 files changed, 285 insertions(+), 93 deletions(-) diff --git a/Translation Editor/translation_bg.json b/Translation Editor/translation_bg.json index 572143e2..c6a2722d 100644 --- a/Translation Editor/translation_bg.json +++ b/Translation Editor/translation_bg.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "сила връх" ], "desc": "Усилване на върха на поялника" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_cs.json b/Translation Editor/translation_cs.json index 068d4cbd..e589e635 100755 --- a/Translation Editor/translation_cs.json +++ b/Translation Editor/translation_cs.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "zisk hr." ], "desc": "Zisk hrotu (měření)" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } \ No newline at end of file diff --git a/Translation Editor/translation_da.json b/Translation Editor/translation_da.json index 634ccd16..8545f12f 100644 --- a/Translation Editor/translation_da.json +++ b/Translation Editor/translation_da.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "D", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "S", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_de.json b/Translation Editor/translation_de.json index 96783a52..b61dc964 100644 --- a/Translation Editor/translation_de.json +++ b/Translation Editor/translation_de.json @@ -36,6 +36,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -253,6 +254,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_en.json b/Translation Editor/translation_en.json index 28d65f0e..c3d732de 100644 --- a/Translation Editor/translation_en.json +++ b/Translation Editor/translation_en.json @@ -36,6 +36,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -258,7 +259,7 @@ "Hall Eff", "Sensitivity" ], - "desc": "Sensitivity of the Hall effect sensor in detecting the stand" + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_es.json b/Translation Editor/translation_es.json index 4e737990..19b5acc5 100644 --- a/Translation Editor/translation_es.json +++ b/Translation Editor/translation_es.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "R", "SettingStartSleepOffChar": "F", "SettingStartNoneChar": "N", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "de punta" ], "desc": "Modificar el valor de ganancia de la punta." + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } \ No newline at end of file diff --git a/Translation Editor/translation_fi.json b/Translation Editor/translation_fi.json index f2ed1135..0513ba5e 100644 --- a/Translation Editor/translation_fi.json +++ b/Translation Editor/translation_fi.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_fr.json b/Translation Editor/translation_fr.json index 98ef2818..08e61b07 100644 --- a/Translation Editor/translation_fr.json +++ b/Translation Editor/translation_fr.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "V", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "D", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_hr.json b/Translation Editor/translation_hr.json index 6a206bfd..01c436ed 100644 --- a/Translation Editor/translation_hr.json +++ b/Translation Editor/translation_hr.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_hu.json b/Translation Editor/translation_hu.json index 5e7d9029..5cb7af04 100644 --- a/Translation Editor/translation_hu.json +++ b/Translation Editor/translation_hu.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_it.json b/Translation Editor/translation_it.json index 863ea218..d94b07cc 100644 --- a/Translation Editor/translation_it.json +++ b/Translation Editor/translation_it.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "D", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "punta" ], "desc": "Varia il guadagno della punta" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_lt.json b/Translation Editor/translation_lt.json index 8761a0d3..2aaddf72 100644 --- a/Translation Editor/translation_lt.json +++ b/Translation Editor/translation_lt.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_nl.json b/Translation Editor/translation_nl.json index ebf90b86..612b7028 100644 --- a/Translation Editor/translation_nl.json +++ b/Translation Editor/translation_nl.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_nl_be.json b/Translation Editor/translation_nl_be.json index d23ca854..7f913d5b 100644 --- a/Translation Editor/translation_nl_be.json +++ b/Translation Editor/translation_nl_be.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_no.json b/Translation Editor/translation_no.json index d9da9b64..3f251c58 100644 --- a/Translation Editor/translation_no.json +++ b/Translation Editor/translation_no.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "D", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "I", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_pl.json b/Translation Editor/translation_pl.json index 1b60095c..4664aa55 100644 --- a/Translation Editor/translation_pl.json +++ b/Translation Editor/translation_pl.json @@ -36,6 +36,7 @@ "SettingStartSleepChar": "Z", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "B", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -252,6 +253,13 @@ "zysk grotu" ], "desc": "Zysk grotu" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_pt.json b/Translation Editor/translation_pt.json index b4cb1927..13875cd5 100644 --- a/Translation Editor/translation_pt.json +++ b/Translation Editor/translation_pt.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_ru.json b/Translation Editor/translation_ru.json index d0b91f79..14ea0b8b 100644 --- a/Translation Editor/translation_ru.json +++ b/Translation Editor/translation_ru.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "О", "SettingStartSleepOffChar": "К", "SettingStartNoneChar": "В", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_sk.json b/Translation Editor/translation_sk.json index d3b99688..9423d33a 100644 --- a/Translation Editor/translation_sk.json +++ b/Translation Editor/translation_sk.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "K", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "N", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "hrotu" ], "desc": "Úprava zisku hrotu" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } \ No newline at end of file diff --git a/Translation Editor/translation_sl.json b/Translation Editor/translation_sl.json index 4714ae0f..7488affc 100644 --- a/Translation Editor/translation_sl.json +++ b/Translation Editor/translation_sl.json @@ -34,6 +34,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -250,6 +251,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_sr_cyrl.json b/Translation Editor/translation_sr_cyrl.json index 1d478fec..a7d8799f 100644 --- a/Translation Editor/translation_sr_cyrl.json +++ b/Translation Editor/translation_sr_cyrl.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_sr_latn.json b/Translation Editor/translation_sr_latn.json index f54d20c9..db0e41ee 100644 --- a/Translation Editor/translation_sr_latn.json +++ b/Translation Editor/translation_sr_latn.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_sv.json b/Translation Editor/translation_sv.json index 76dafe3e..2fa2e1fb 100644 --- a/Translation Editor/translation_sv.json +++ b/Translation Editor/translation_sv.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_tr.json b/Translation Editor/translation_tr.json index 711dfc6e..cdd1e561 100644 --- a/Translation Editor/translation_tr.json +++ b/Translation Editor/translation_tr.json @@ -33,6 +33,7 @@ "SettingStartSleepChar": "S", "SettingStartSleepOffChar": "O", "SettingStartNoneChar": "F", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -249,6 +250,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translation_uk.json b/Translation Editor/translation_uk.json index 1803c213..d4b5e8b9 100644 --- a/Translation Editor/translation_uk.json +++ b/Translation Editor/translation_uk.json @@ -35,6 +35,7 @@ "SettingStartSleepChar": "О", "SettingStartSleepOffChar": "К", "SettingStartNoneChar": "В", + "SettingSensitivityOff":"O", "SettingSensitivityLow":"L", "SettingSensitivityMedium":"M", "SettingSensitivityHigh":"H" @@ -251,6 +252,13 @@ "tip gain" ], "desc": "Tip gain" + }, + "HallEffSensitivity": { + "text2": [ + "Hall Eff", + "Sensitivity" + ], + "desc": "Sensitivity of the Hall effect sensor in detecting sleep " } } } diff --git a/Translation Editor/translations_def.js b/Translation Editor/translations_def.js index a9cb11e6..bcbd4296 100644 --- a/Translation Editor/translations_def.js +++ b/Translation Editor/translations_def.js @@ -133,6 +133,10 @@ var def = "id": "SettingStartNoneChar", "len": 1 }, + { + "id": "SettingSensitivityOff", + "len": 1 + }, { "id": "SettingSensitivityLow", "len": 1 diff --git a/workspace/TS100/Core/Inc/Translation.h b/workspace/TS100/Core/Inc/Translation.h index 8915d6d4..2903366e 100644 --- a/workspace/TS100/Core/Inc/Translation.h +++ b/workspace/TS100/Core/Inc/Translation.h @@ -51,9 +51,10 @@ extern const char *SettingStartSolderingChar; extern const char *SettingStartSleepChar; extern const char *SettingStartSleepOffChar; extern const char *SettingStartNoneChar; -extern const char* SettingSensitivityLow; -extern const char* SettingSensitivityMedium; -extern const char* SettingSensitivityHigh; +extern const char *SettingSensitivityOff; +extern const char *SettingSensitivityLow; +extern const char *SettingSensitivityMedium; +extern const char *SettingSensitivityHigh; extern const char *SettingFastChar; extern const char *SettingSlowChar; diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index 2431a7a9..bd22a3b1 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -68,6 +68,8 @@ static void settings_displayTempChangeLongStep(void); static bool settings_setTempChangeLongStep(void); static void settings_displayPowerPulse(void); static bool settings_setPowerPulse(void); +static void settings_displayHallEffect(void); +static bool settings_setHallEffect(void); // Menu functions static void settings_displaySolderingMenu(void); @@ -116,27 +118,24 @@ static bool settings_enterAdvancedMenu(void); * */ const menuitem rootSettingsMenu[] { - /* - * Power Source - * Soldering Menu - * Power Saving Menu - * UI Menu - * Advanced Menu - * Exit - */ +/* + * Power Source + * Soldering Menu + * Power Saving Menu + * UI Menu + * Advanced Menu + * Exit + */ #ifdef MODEL_TS100 - { (const char*) SettingsDescriptions[0], settings_setInputVRange, - settings_displayInputVRange }, /*Voltage input*/ + { (const char*) SettingsDescriptions[0], settings_setInputVRange, + settings_displayInputVRange}, /*Voltage input*/ #else - { (const char*) SettingsDescriptions[19], settings_setInputPRange, - settings_displayInputPRange }, /*Voltage input*/ + { (const char*) SettingsDescriptions[19], settings_setInputPRange, settings_displayInputPRange }, /*Voltage input*/ #endif - { (const char*) NULL, settings_enterSolderingMenu, - settings_displaySolderingMenu }, /*Soldering*/ + { (const char*) NULL, settings_enterSolderingMenu, settings_displaySolderingMenu }, /*Soldering*/ { (const char*) NULL, settings_enterPowerMenu, settings_displayPowerMenu }, /*Sleep Options Menu*/ { (const char*) NULL, settings_enterUIMenu, settings_displayUIMenu }, /*UI Menu*/ - { (const char*) NULL, settings_enterAdvancedMenu, - settings_displayAdvancedMenu }, /*Advanced Menu*/ + { (const char*) NULL, settings_enterAdvancedMenu, settings_displayAdvancedMenu }, /*Advanced Menu*/ { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; @@ -148,14 +147,10 @@ const menuitem solderingMenu[] = { * Temp change short step * Temp change long step */ -{ (const char*) SettingsDescriptions[8], settings_setBoostTemp, - settings_displayBoostTemp }, /*Boost Temp*/ -{ (const char*) SettingsDescriptions[9], settings_setAutomaticStartMode, - settings_displayAutomaticStartMode }, /*Auto start*/ -{ (const char*) SettingsDescriptions[22], settings_setTempChangeShortStep, - settings_displayTempChangeShortStep }, /*Temp change short step*/ -{ (const char*) SettingsDescriptions[23], settings_setTempChangeLongStep, - settings_displayTempChangeLongStep }, /*Temp change long step*/ +{ (const char*) SettingsDescriptions[8], settings_setBoostTemp, settings_displayBoostTemp }, /*Boost Temp*/ +{ (const char*) SettingsDescriptions[9], settings_setAutomaticStartMode, settings_displayAutomaticStartMode }, /*Auto start*/ +{ (const char*) SettingsDescriptions[22], settings_setTempChangeShortStep, settings_displayTempChangeShortStep }, /*Temp change short step*/ +{ (const char*) SettingsDescriptions[23], settings_setTempChangeLongStep, settings_displayTempChangeLongStep }, /*Temp change long step*/ { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem UIMenu[] = { @@ -168,19 +163,13 @@ const menuitem UIMenu[] = { * Reverse Temp change buttons + - */ #ifdef ENABLED_FAHRENHEIT_SUPPORT - { (const char*) SettingsDescriptions[5], settings_setTempF, - settings_displayTempF }, /* Temperature units*/ + { (const char*) SettingsDescriptions[5], settings_setTempF, + settings_displayTempF}, /* Temperature units*/ #endif - { (const char*) SettingsDescriptions[7], settings_setDisplayRotation, - settings_displayDisplayRotation }, /*Display Rotation*/ - { (const char*) SettingsDescriptions[10], - settings_setCoolingBlinkEnabled, - settings_displayCoolingBlinkEnabled }, /*Cooling blink warning*/ - { (const char*) SettingsDescriptions[15], settings_setScrollSpeed, - settings_displayScrollSpeed }, /*Scroll Speed for descriptions*/ - { (const char*) SettingsDescriptions[21], - settings_setReverseButtonTempChangeEnabled, - settings_displayReverseButtonTempChangeEnabled }, /* Reverse Temp change buttons + - */ + { (const char*) SettingsDescriptions[7], settings_setDisplayRotation, settings_displayDisplayRotation }, /*Display Rotation*/ + { (const char*) SettingsDescriptions[10], settings_setCoolingBlinkEnabled, settings_displayCoolingBlinkEnabled }, /*Cooling blink warning*/ + { (const char*) SettingsDescriptions[15], settings_setScrollSpeed, settings_displayScrollSpeed }, /*Scroll Speed for descriptions*/ + { (const char*) SettingsDescriptions[21], settings_setReverseButtonTempChangeEnabled, settings_displayReverseButtonTempChangeEnabled }, /* Reverse Temp change buttons + - */ { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem PowerMenu[] = { @@ -190,14 +179,13 @@ const menuitem PowerMenu[] = { * Shutdown Time * Motion Sensitivity */ -{ (const char*) SettingsDescriptions[1], settings_setSleepTemp, - settings_displaySleepTemp }, /*Sleep Temp*/ -{ (const char*) SettingsDescriptions[2], settings_setSleepTime, - settings_displaySleepTime }, /*Sleep Time*/ -{ (const char*) SettingsDescriptions[3], settings_setShutdownTime, - settings_displayShutdownTime }, /*Shutdown Time*/ -{ (const char*) SettingsDescriptions[4], settings_setSensitivity, - settings_displaySensitivity }, /* Motion Sensitivity*/ +{ (const char*) SettingsDescriptions[1], settings_setSleepTemp, settings_displaySleepTemp }, /*Sleep Temp*/ +{ (const char*) SettingsDescriptions[2], settings_setSleepTime, settings_displaySleepTime }, /*Sleep Time*/ +{ (const char*) SettingsDescriptions[3], settings_setShutdownTime, settings_displayShutdownTime }, /*Shutdown Time*/ +{ (const char*) SettingsDescriptions[4], settings_setSensitivity, settings_displaySensitivity }, /* Motion Sensitivity*/ +#ifdef HALL_SENSOR +{ (const char*) SettingsDescriptions[26], settings_setHallEffect, settings_displayHallEffect}, /* HallEffect Sensitivity*/ +#endif { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem advancedMenu[] = { @@ -211,22 +199,14 @@ const menuitem advancedMenu[] = { * Reset Settings * Power Pulse */ -{ (const char*) SettingsDescriptions[20], settings_setPowerLimit, - settings_displayPowerLimit }, /*Power limit*/ -{ (const char*) SettingsDescriptions[6], settings_setAdvancedIDLEScreens, - settings_displayAdvancedIDLEScreens }, /* Advanced idle screen*/ -{ (const char*) SettingsDescriptions[14], settings_setAdvancedSolderingScreens, - settings_displayAdvancedSolderingScreens }, /* Advanced soldering screen*/ -{ (const char*) SettingsDescriptions[12], settings_setResetSettings, - settings_displayResetSettings }, /*Resets settings*/ -{ (const char*) SettingsDescriptions[11], settings_setCalibrate, - settings_displayCalibrate }, /*Calibrate tip*/ -{ (const char*) SettingsDescriptions[13], settings_setCalibrateVIN, - settings_displayCalibrateVIN }, /*Voltage input cal*/ -{ (const char*) SettingsDescriptions[24], settings_setPowerPulse, - settings_displayPowerPulse }, /*Power Pulse adjustment */ -{ (const char*) SettingsDescriptions[25], settings_setTipGain, - settings_displayTipGain }, /*TipGain*/ +{ (const char*) SettingsDescriptions[20], settings_setPowerLimit, settings_displayPowerLimit }, /*Power limit*/ +{ (const char*) SettingsDescriptions[6], settings_setAdvancedIDLEScreens, settings_displayAdvancedIDLEScreens }, /* Advanced idle screen*/ +{ (const char*) SettingsDescriptions[14], settings_setAdvancedSolderingScreens, settings_displayAdvancedSolderingScreens }, /* Advanced soldering screen*/ +{ (const char*) SettingsDescriptions[12], settings_setResetSettings, settings_displayResetSettings }, /*Resets settings*/ +{ (const char*) SettingsDescriptions[11], settings_setCalibrate, settings_displayCalibrate }, /*Calibrate tip*/ +{ (const char*) SettingsDescriptions[13], settings_setCalibrateVIN, settings_displayCalibrateVIN }, /*Voltage input cal*/ +{ (const char*) SettingsDescriptions[24], settings_setPowerPulse, settings_displayPowerPulse }, /*Power Pulse adjustment */ +{ (const char*) SettingsDescriptions[25], settings_setTipGain, settings_displayTipGain }, /*TipGain*/ { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; @@ -245,8 +225,7 @@ static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) { * @param cursorCharPosition Custom cursor char position to set after printing * description. */ -static void printShortDescription(uint32_t shortDescIndex, - uint16_t cursorCharPosition) { +static void printShortDescription(uint32_t shortDescIndex, uint16_t cursorCharPosition) { // print short description (default single line, explicit double line) printShortDescriptionDoubleLine(shortDescIndex); @@ -267,8 +246,7 @@ static int userConfirmation(const char *message) { bool lcdRefresh = true; for (;;) { - int16_t messageOffset = ((xTaskGetTickCount() - messageStart) - / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); + int16_t messageOffset = ((xTaskGetTickCount() - messageStart) / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); messageOffset %= messageWidth; // Roll around at the end if (lastOffset != messageOffset) { @@ -309,7 +287,7 @@ static int userConfirmation(const char *message) { static bool settings_setInputVRange(void) { systemSettings.cutoutSetting = (systemSettings.cutoutSetting + 1) % 5; if (systemSettings.cutoutSetting) - systemSettings.powerLimit = 0; // disable power limit if switching to a lipo power source + systemSettings.powerLimit = 0; // disable power limit if switching to a lipo power source return systemSettings.cutoutSetting == 4; } @@ -355,7 +333,7 @@ static bool settings_setSleepTemp(void) { if (systemSettings.temperatureInF) { systemSettings.SleepTemp += 20; if (systemSettings.SleepTemp > 580) - systemSettings.SleepTemp = 60; + systemSettings.SleepTemp = 60; return systemSettings.SleepTemp == 580; } else #endif @@ -423,14 +401,14 @@ static bool settings_setTempF(void) { // C to F == F= ( (C*9) +160)/5 systemSettings.BoostTemp = ((systemSettings.BoostTemp * 9) + 160) / 5; systemSettings.SolderingTemp = - ((systemSettings.SolderingTemp * 9) + 160) / 5; + ((systemSettings.SolderingTemp * 9) + 160) / 5; systemSettings.SleepTemp = ((systemSettings.SleepTemp * 9) + 160) / 5; } else { // Change sleep, boost and soldering temps to the C equiv // F->C == C = ((F-32)*5)/9 systemSettings.BoostTemp = ((systemSettings.BoostTemp - 32) * 5) / 9; systemSettings.SolderingTemp = ((systemSettings.SolderingTemp - 32) * 5) - / 9; + / 9; systemSettings.SleepTemp = ((systemSettings.SleepTemp - 32) * 5) / 9; } // Rescale both to be multiples of 10 @@ -510,9 +488,7 @@ static bool settings_setScrollSpeed(void) { static void settings_displayScrollSpeed(void) { printShortDescription(15, 7); - OLED::print( - (systemSettings.descriptionScrollSpeed) ? - SettingFastChar : SettingSlowChar); + OLED::print((systemSettings.descriptionScrollSpeed) ? SettingFastChar : SettingSlowChar); } static bool settings_setDisplayRotation(void) { @@ -668,8 +644,7 @@ static void setTipOffset() { OLED::refresh(); osDelay(100); } - systemSettings.CalibrationOffset = TipThermoModel::convertTipRawADCTouV( - offset / 16); + systemSettings.CalibrationOffset = TipThermoModel::convertTipRawADCTouV(offset / 16); } OLED::clearScreen(); OLED::setCursor(0, 0); @@ -703,11 +678,9 @@ static bool settings_setCalibrateVIN(void) { for (;;) { OLED::setCursor(0, 0); - OLED::printNumber(getInputVoltageX10(systemSettings.voltageDiv, 0) / 10, - 2); + OLED::printNumber(getInputVoltageX10(systemSettings.voltageDiv, 0) / 10, 2); OLED::print(SymbolDot); - OLED::printNumber(getInputVoltageX10(systemSettings.voltageDiv, 0) % 10, - 1, false); + OLED::printNumber(getInputVoltageX10(systemSettings.voltageDiv, 0) % 10, 1, false); OLED::print(SymbolVolts); ButtonState buttons = getButtonState(); @@ -803,8 +776,7 @@ static void settings_displayTipGain(void) { } static bool settings_setReverseButtonTempChangeEnabled(void) { - systemSettings.ReverseButtonTempChangeEnabled = - !systemSettings.ReverseButtonTempChangeEnabled; + systemSettings.ReverseButtonTempChangeEnabled = !systemSettings.ReverseButtonTempChangeEnabled; return false; } @@ -855,6 +827,34 @@ static void settings_displayPowerPulse(void) { OLED::print(OffString); } +} + +static void settings_displayHallEffect(void) { + printShortDescription(26, 7); + switch (systemSettings.hallEffectSensitivity) { + case 1: + OLED::print(SettingSensitivityLow); + break; + case 2: + OLED::print(SettingSensitivityMedium); + break; + case 3: + OLED::print(SettingSensitivityHigh); + break; + case 0: + default: + OLED::print(SettingSensitivityOff); + break; + } +} +static bool settings_setHallEffect(void) { + //To keep life simpler for now, we have a few preset sensitivity levels + // Off, Low, Medium, High + systemSettings.hallEffectSensitivity++; + systemSettings.hallEffectSensitivity %= 4; + + return systemSettings.hallEffectSensitivity == 3; + } static void displayMenu(size_t index) { // Call into the menu @@ -865,8 +865,7 @@ static void displayMenu(size_t index) { // Draw symbol // 16 pixel wide image // 2 pixel wide scrolling indicator - OLED::drawArea(96 - 16 - 2, 0, 16, 16, - (&SettingsMenuIcons[(16 * 2) * index])); + OLED::drawArea(96 - 16 - 2, 0, 16, 16, (&SettingsMenuIcons[(16 * 2) * index])); } static void settings_displayCalibrateVIN(void) { @@ -941,8 +940,7 @@ void gui_Menu(const menuitem *menu) { OLED::setCursor(0, 0); // If the user has hesitated for >=3 seconds, show the long text // Otherwise "draw" the option - if ((xTaskGetTickCount() - lastButtonTime < 3000) - || menu[currentScreen].description == NULL) { + if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) { OLED::clearScreen(); menu[currentScreen].draw(); uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize; @@ -960,10 +958,7 @@ void gui_Menu(const menuitem *menu) { // lower the value - higher the speed int16_t descriptionWidth = FONT_12_WIDTH * (strlen(menu[currentScreen].description) + 7); - int16_t descriptionOffset = - ((xTaskGetTickCount() - descriptionStart) - / (systemSettings.descriptionScrollSpeed == 1 ? - 10 : 20)); + int16_t descriptionOffset = ((xTaskGetTickCount() - descriptionStart) / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); descriptionOffset %= descriptionWidth; // Roll around at the end if (lastOffset != descriptionOffset) { OLED::clearScreen(); @@ -1017,8 +1012,7 @@ void gui_Menu(const menuitem *menu) { descriptionStart = 0; break; case BUTTON_F_LONG: - if ((int) (xTaskGetTickCount() - autoRepeatTimer - + autoRepeatAcceleration) > + if ((int) (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) { if ((lastValue = menu[currentScreen].incrementHandler())) autoRepeatTimer = 1000; From a582af984ededf2ce48c70a70658a6c931e4e530 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 11:18:29 +1100 Subject: [PATCH 48/72] Pull out sleep and shutdown control into their own functions --- workspace/TS100/Core/Threads/GUIThread.cpp | 93 +++++++++++++--------- workspace/TS100/Core/Threads/MOVThread.cpp | 2 +- 2 files changed, 58 insertions(+), 37 deletions(-) diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 5563a8ae..af7d5cb7 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -25,15 +25,15 @@ extern "C" { #include "I2CBB.hpp" // File local variables extern uint32_t currentTempTargetDegC; -extern uint8_t accelInit; -extern uint32_t lastMovementTime; +extern TickType_t lastMovementTime; extern osThreadId GUITaskHandle; extern osThreadId MOVTaskHandle; extern osThreadId PIDTaskHandle; - +static bool shouldBeSleeping(); +static bool shouldShutdown(); #define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ) #define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ) - +static TickType_t lastHallEffectSleepStart = 0; static uint16_t min(uint16_t a, uint16_t b) { if (a > b) return b; @@ -272,19 +272,33 @@ static void gui_solderingTempAdjust() { GUIDelay(); } } - +static bool shouldShutdown() { + if (systemSettings.ShutdownTime) { // only allow shutdown exit if time > 0 + if (lastMovementTime) { + if (((TickType_t) (xTaskGetTickCount() - lastMovementTime)) > (TickType_t) (systemSettings.ShutdownTime * TICKS_MIN)) { + return true; + } + } + if (lastHallEffectSleepStart) { + if (((TickType_t) (xTaskGetTickCount() - lastHallEffectSleepStart)) > (TickType_t) (systemSettings.ShutdownTime * TICKS_MIN)) { + return true; + } + } + } + return false; +} static int gui_SolderingSleepingMode(bool stayOff) { // Drop to sleep temperature and display until movement or button press for (;;) { - ButtonState buttons = getButtonState(); - if (buttons) + // user moved or pressed a button, go back to soldering + if (!shouldBeSleeping()) { return 0; - if ((xTaskGetTickCount() > 1000) && ((accelInit && (xTaskGetTickCount() - lastMovementTime < 1000)) || (xTaskGetTickCount() - lastButtonTime < 1000))) - return 0; // user moved or pressed a button, go back to soldering + } + #ifdef MODEL_TS100 - if (checkVoltageForExit()) - return 1; // return non-zero on error + if (checkVoltageForExit()) + return 1; // return non-zero on error #endif #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { @@ -338,15 +352,14 @@ static int gui_SolderingSleepingMode(bool stayOff) { OLED::drawSymbol(1); } } - if (systemSettings.ShutdownTime) // only allow shutdown exit if time > 0 - if (lastMovementTime) - if (((uint32_t) (xTaskGetTickCount() - lastMovementTime)) > (uint32_t) (systemSettings.ShutdownTime * 60 * 1000)) { - // shutdown - currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode - } + OLED::refresh(); GUIDelay(); + if (shouldShutdown()) { + // shutdown + currentTempTargetDegC = 0; + return 1; // we want to exit soldering mode + } } return 0; } @@ -380,12 +393,29 @@ static uint32_t getSleepTimeout() { } static bool shouldBeSleeping() { //Return true if the iron should be in sleep mode - if ((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout() && (xTaskGetTickCount() - lastButtonTime) > getSleepTimeout()) { - return true; + if (systemSettings.sensitivity && systemSettings.SleepTime) { + if ((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout() && (xTaskGetTickCount() - lastButtonTime) > getSleepTimeout()) { + return true; + } } #ifdef HALL_SENSOR -//If the hall effect sensor is enabled in the build, check if its over threshold, and if so then we force sleep - + //If the hall effect sensor is enabled in the build, check if its over threshold, and if so then we force sleep + if (lookupHallEffectThreshold()) { + int16_t hallEffectStrength = getRawHallEffect(); + if (hallEffectStrength < 0) + hallEffectStrength = -hallEffectStrength; + //Have absolute value of measure of magnetic field strength + if (hallEffectStrength > lookupHallEffectThreshold()) { + if (lastHallEffectSleepStart == 0) { + lastHallEffectSleepStart = xTaskGetTickCount(); + } + if ((xTaskGetTickCount() - lastHallEffectSleepStart) > TICKS_SECOND) { + return true; + } + } else { + lastHallEffectSleepStart = 0; + } + } #endif return false; } @@ -531,12 +561,11 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } #endif - if (systemSettings.sensitivity && systemSettings.SleepTime) - if (shouldBeSleeping()) { - if (gui_SolderingSleepingMode(false)) { - return; // If the function returns non-0 then exit - } + if (shouldBeSleeping()) { + if (gui_SolderingSleepingMode(false)) { + return; // If the function returns non-0 then exit } + } // slow down ui update rate GUIDelay(); } @@ -598,7 +627,7 @@ void showDebugMenu(void) { break; case 10: // Print PCB ID number - OLED::printNumber(PCBVersion, 1); + OLED::printNumber(PCBVersion, 2); break; default: break; @@ -654,14 +683,6 @@ void startGUITask(void const *argument __unused) { OLED::refresh(); waitForButtonPressOrTimeout(10000); } - if (getHallSensorFitted()) { - OLED::clearScreen(); - OLED::setFont(1); - OLED::setCursor(0, 0); - OLED::printNumber(5000, 4, 0); - OLED::refresh(); - waitForButtonPressOrTimeout(10000); - } if (systemSettings.autoStartMode) { // jump directly to the autostart mode if (systemSettings.autoStartMode == 1) { diff --git a/workspace/TS100/Core/Threads/MOVThread.cpp b/workspace/TS100/Core/Threads/MOVThread.cpp index 7c09d17b..745c10fa 100644 --- a/workspace/TS100/Core/Threads/MOVThread.cpp +++ b/workspace/TS100/Core/Threads/MOVThread.cpp @@ -22,7 +22,7 @@ #include "task.h" #define MOVFilter 8 uint8_t accelInit = 0; -uint32_t lastMovementTime = 0; +TickType_t lastMovementTime = 0; void detectAccelerometerVersion() { #ifdef ACCEL_MMA if (MMA8652FC::detect()) { From bc4910a8c7aaaea1ada3a0268cf98d1ebeb01421 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 12:17:50 +1100 Subject: [PATCH 49/72] Derp --- .github/workflows/push.yml | 135 ++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6d1a9f32..2c2dfdf9 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,103 +1,98 @@ name: CI PR -on: [pull_request] +on: [push] jobs: build_TS80: - runs-on: ubuntu-latest - + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: chmod - run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh - - name: setup - run: ./setup.sh + - name: setup + run: ./setup.sh - - name: build TS80 - run: cd workspace/TS100 && ./build.sh -m TS80 + - name: build TS80 + run: cd workspace/TS100 && ./build.sh -m TS80 - - name: Archive TS80 artifacts - uses: actions/upload-artifact@v2 - with: - name: TS80 - path: | - workspace/TS100/Hexfile/TS80_*.hex - workspace/TS100/Hexfile/TS80_*.bin - if-no-files-found: error + - name: Archive TS80 artifacts + uses: actions/upload-artifact@v2 + with: + name: TS80 + path: | + workspace/TS100/Hexfile/TS80_*.hex + workspace/TS100/Hexfile/TS80_*.bin + if-no-files-found: error build_TS80P: - runs-on: ubuntu-latest - + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: chmod - run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh - - name: setup - run: ./setup.sh + - name: setup + run: ./setup.sh - - name: build TS80P - run: cd workspace/TS100 && ./build.sh -m TS80P + - name: build TS80P + run: cd workspace/TS100 && ./build.sh -m TS80P - - name: Archive TS80P artifacts - uses: actions/upload-artifact@v2 - with: - name: TS80P - path: | - workspace/TS100/Hexfile/TS80P_*.hex - workspace/TS100/Hexfile/TS80P_*.bin - if-no-files-found: error + - name: Archive TS80P artifacts + uses: actions/upload-artifact@v2 + with: + name: TS80P + path: | + workspace/TS100/Hexfile/TS80P_*.hex + workspace/TS100/Hexfile/TS80P_*.bin + if-no-files-found: error build_TS100: - runs-on: ubuntu-latest - + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: chmod - run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh - - name: setup - run: ./setup.sh + - name: setup + run: ./setup.sh - - name: build TS100 - run: cd workspace/TS100 && ./build.sh -m TS100 + - name: build TS100 + run: cd workspace/TS100 && ./build.sh -m TS100 - - name: Archive TS100 artifacts - uses: actions/upload-artifact@v2 - with: - name: TS100 - path: | - workspace/TS100/Hexfile/TS100_*.hex - workspace/TS100/Hexfile/TS100_*.bin - if-no-files-found: error + - name: Archive TS100 artifacts + uses: actions/upload-artifact@v2 + with: + name: TS100 + path: | + workspace/TS100/Hexfile/TS100_*.hex + workspace/TS100/Hexfile/TS100_*.bin + if-no-files-found: error build_Pinecil: - runs-on: ubuntu-latest - + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: chmod - run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh + - name: chmod + run: chmod +x setup.sh && chmod +x workspace/TS100/build.sh - - name: setup - run: ./setup.sh + - name: setup + run: ./setup.sh - - name: build Pinecil - run: cd workspace/TS100 && ./build.sh -m Pinecil + - name: build Pinecil + run: cd workspace/TS100 && ./build.sh -m Pinecil - - name: Archive Pinecil artifacts - uses: actions/upload-artifact@v2 - with: - name: Pinecil - path: | - workspace/TS100/Hexfile/Pinecil_*.hex - workspace/TS100/Hexfile/Pinecil_*.bin - if-no-files-found: error - \ No newline at end of file + - name: Archive Pinecil artifacts + uses: actions/upload-artifact@v2 + with: + name: Pinecil + path: | + workspace/TS100/Hexfile/Pinecil_*.hex + workspace/TS100/Hexfile/Pinecil_*.bin + if-no-files-found: error From 7c5c689d445470422f805da5850e9e8819095482 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 12:24:24 +1100 Subject: [PATCH 50/72] Cleanup & Mask unused functions --- .../TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c | 2 +- workspace/TS100/Core/Src/gui.cpp | 8 ++++---- workspace/TS100/Makefile | 7 +------ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c index 7b0e743f..5fbdf8dc 100644 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c +++ b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/gd32vf103_adc.c @@ -629,7 +629,7 @@ uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) idata = 0U; break; } - return (uint16_t)idata; + return (uint16_t)idata& 0xFFFF; } /*! diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index bd22a3b1..cdb9c22e 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -68,9 +68,10 @@ static void settings_displayTempChangeLongStep(void); static bool settings_setTempChangeLongStep(void); static void settings_displayPowerPulse(void); static bool settings_setPowerPulse(void); +#ifdef HALL_SENSOR static void settings_displayHallEffect(void); static bool settings_setHallEffect(void); - +#endif // Menu functions static void settings_displaySolderingMenu(void); static bool settings_enterSolderingMenu(void); @@ -828,7 +829,7 @@ static void settings_displayPowerPulse(void) { } } - +#ifdef HALL_SENSOR static void settings_displayHallEffect(void) { printShortDescription(26, 7); switch (systemSettings.hallEffectSensitivity) { @@ -852,10 +853,9 @@ static bool settings_setHallEffect(void) { // Off, Low, Medium, High systemSettings.hallEffectSensitivity++; systemSettings.hallEffectSensitivity %= 4; - return systemSettings.hallEffectSensitivity == 3; - } +#endif static void displayMenu(size_t index) { // Call into the menu OLED::setFont(1); diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index e9ab7293..880f1995 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -70,7 +70,7 @@ S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld DEV_LDFLAGS=-nostartfiles -Xlinker --gc-sections -DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -fabi-version=0 +DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fabi-version=0 DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" flash_size=128k @@ -173,10 +173,7 @@ LINKER_FLAGS=$(CPUFLAGS) \ -fno-rtti \ -fno-exceptions \ -fno-non-call-exceptions \ - -fno-use-cxa-atexit \ -fno-strict-aliasing \ - -fno-rtti \ - -fno-exceptions \ -fno-threadsafe-statics \ -Wl,--wrap=malloc \ -Wl,--wrap=free \ @@ -240,8 +237,6 @@ CXXFLAGS=$(CPUFLAGS) \ -fno-non-call-exceptions \ -fno-use-cxa-atexit \ -fno-strict-aliasing \ - -fno-rtti \ - -fno-exceptions \ -fno-threadsafe-statics \ $(DEV_CXXFLAGS) From 1b579febcdaae7b36cda6a647c751f9a8045841f Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 12:27:46 +1100 Subject: [PATCH 51/72] Reformat --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 160 ++- .../TS100/Core/BSP/Pine64/I2C_Wrapper.cpp | 955 +++++++++--------- workspace/TS100/Core/BSP/Pine64/Setup.c | 475 ++++----- 3 files changed, 802 insertions(+), 788 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 391c1bf6..4a9e0c92 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -11,119 +11,117 @@ #include const uint16_t powerPWM = 255; -const uint8_t holdoffTicks = 13; // delay of 7 ms -const uint8_t tempMeasureTicks = 17; +const uint8_t holdoffTicks = 25; // delay of 7 ms +const uint8_t tempMeasureTicks = 25; -uint16_t totalPWM; //htim2.Init.Period, the full PWM cycle +uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle -//2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = { { 0 }, 0, 0 }; +// 2 second filter (ADC is PID_TIM_HZ Hz) +history rawTempFilter = {{0}, 0, 0}; void resetWatchdog() { - //TODO + // TODO } uint16_t getTipInstantTemperature() { - uint16_t sum = 0; // 12 bit readings * 8 -> 15 bits + volatile uint16_t sum = 0; // 12 bit readings * 8*2 -> 16 bits - for (int i = 0; i < 4; i++) { - sum += adc_inserted_data_read(ADC0, i); - sum += adc_inserted_data_read(ADC1, i); - } - return sum; // 8x over sample + for (int i = 0; i < 4; i++) { + sum += adc_inserted_data_read(ADC0, i); + sum += adc_inserted_data_read(ADC1, i); + } + return sum; // 8x over sample } uint16_t getTipRawTemp(uint8_t refresh) { - if (refresh) { - uint16_t lastSample = getTipInstantTemperature(); - rawTempFilter.update(lastSample); - return lastSample; - } else { - return rawTempFilter.average(); - } + if (refresh) { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } else { + return rawTempFilter.average(); + } } uint16_t getHandleTemperature() { #ifdef TEMP_TMP36 - // We return the current handle temperature in X10 C - // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for - // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = - // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 - // mV per count So we need to subtract an offset of 0.5V to center on 0C - // (4964.8 counts) - // - int32_t result = getADC(0); - result -= 4965; // remove 0.5V offset - // 10mV per C - // 99.29 counts per Deg C above 0C - result *= 100; - result /= 993; - return result; + // We return the current handle temperature in X10 C + // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for + // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = + // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 + // mV per count So we need to subtract an offset of 0.5V to center on 0C + // (4964.8 counts) + // + int32_t result = getADC(0); + result -= 4965; // remove 0.5V offset + // 10mV per C + // 99.29 counts per Deg C above 0C + result *= 100; + result /= 993; + return result; #else #error #endif } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - static uint8_t preFillneeded = 10; - static uint32_t samples[BATTFILTERDEPTH]; - static uint8_t index = 0; - if (preFillneeded) { - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - samples[i] = getADC(1); - preFillneeded--; - } - if (sample) { - samples[index] = getADC(1); - index = (index + 1) % BATTFILTERDEPTH; - } - uint32_t sum = 0; + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - sum += samples[i]; + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; - sum /= BATTFILTERDEPTH; - if (divisor == 0) { - divisor = 1; - } - return sum * 4 / divisor; + sum /= BATTFILTERDEPTH; + if (divisor == 0) { + divisor = 1; + } + return sum * 4 / divisor; } void unstick_I2C() { - /* configure SDA/SCL for GPIO */ - GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin; - gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - GPIO_BOP(GPIOB) |= SCL_Pin; - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - asm ("nop"); - GPIO_BOP(GPIOB) |= SDA_Pin; - /* connect PB6 to I2C0_SCL */ - /* connect PB7 to I2C0_SDA */ - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); + /* configure SDA/SCL for GPIO */ + GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin; + gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + GPIO_BOP(GPIOB) |= SCL_Pin; + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + GPIO_BOP(GPIOB) |= SDA_Pin; + /* connect PB6 to I2C0_SCL */ + /* connect PB7 to I2C0_SDA */ + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); } uint8_t getButtonA() { - return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; } uint8_t getButtonB() { - return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; } void reboot() { - // TODO - for (;;) { - } + // TODO + for (;;) { + } } -void delay_ms(uint16_t count) { - delay_1ms(count); -} - - +void delay_ms(uint16_t count) { delay_1ms(count); } diff --git a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp index f1e9f25b..e41fc6d6 100644 --- a/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp +++ b/workspace/TS100/Core/BSP/Pine64/I2C_Wrapper.cpp @@ -12,510 +12,521 @@ SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr; StaticSemaphore_t FRToSI2C::xSemaphoreBuffer; #define I2C_TIME_OUT (uint16_t)(5000) void FRToSI2C::CpltCallback() { - //TODO + // TODO } bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { - return Mem_Write(address, reg, &data, 1); + return Mem_Write(address, reg, &data, 1); } uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) { - uint8_t temp = 0; - Mem_Read(add, reg, &temp, 1); - return temp; + uint8_t temp = 0; + Mem_Read(add, reg, &temp, 1); + return temp; } -bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - dma_parameter_struct dma_init_struct; +bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, + uint8_t *p_buffer, uint16_t number_of_byte) { + if (!lock()) + return false; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint8_t in_rx_cycle = 0; - uint16_t timeout = 0; - uint8_t tries = 0; - uint8_t i2c_timeout_flag = 0; - while (!(i2c_timeout_flag)) { - switch (state) { - case I2C_START: - tries++; - if (tries > 64) { - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - unlock(); - return false; - } - if (0 == in_rx_cycle) { - /* disable I2C0 */ - i2c_disable(I2C0); - /* enable I2C0 */ - i2c_enable(I2C0); + uint8_t state = I2C_START; + uint8_t in_rx_cycle = 0; + uint16_t timeout = 0; + uint8_t tries = 0; + uint8_t i2c_timeout_flag = 0; + while (!(i2c_timeout_flag)) { + switch (state) { + case I2C_START: + tries++; + if (tries > 64) { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + unlock(); + return false; + } + if (0 == in_rx_cycle) { + /* disable I2C0 */ + i2c_disable(I2C0); + /* enable I2C0 */ + i2c_enable(I2C0); - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the start signal */ - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - } else { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - if (RESET == in_rx_cycle) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); - state = I2C_CLEAR_ADDRESS_FLAG; - } - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_TRANSMIT_DATA; - } else { - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - break; - case I2C_TRANSMIT_DATA: - if (0 == in_rx_cycle) { - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - //Write out the 8 byte address - i2c_data_transmit(I2C0, read_address); - timeout = 0; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - /* wait until BTC bit is set */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_START; - in_rx_cycle = 1; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - } else { - /* one byte master reception procedure (polling) */ - if (number_of_byte < 2) { - /* disable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_DISABLE); - /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */ - i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - /* wait for the byte to be received */ - while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) - ; - /* read the byte received from the EEPROM */ - *p_buffer = i2c_data_receive(I2C0); - /* decrement the read bytes counter */ - number_of_byte--; - timeout = 0; - } else { /* more than one byte master reception procedure (DMA) */ - dma_deinit(DMA0, DMA_CH6); - dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_init_struct.memory_addr = (uint32_t) p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH6, &dma_init_struct); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the start signal */ + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + } else { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + if (RESET == in_rx_cycle) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(I2C0, DevAddress, I2C_RECEIVER); + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + // Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + // Address NACK'd + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + if (0 == in_rx_cycle) { + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + // Write out the 8 byte address + i2c_data_transmit(I2C0, read_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + /* wait until BTC bit is set */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_BTC)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + in_rx_cycle = 1; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + } else { + /* one byte master reception procedure (polling) */ + if (number_of_byte < 2) { + /* disable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_DISABLE); + /* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register + * (I2C_STAT0 has already been read) */ + i2c_flag_get(I2C0, I2C_FLAG_ADDSEND); + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + /* wait for the byte to be received */ + while (!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) + ; + /* read the byte received from the EEPROM */ + *p_buffer = i2c_data_receive(I2C0); + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } else { /* more than one byte master reception procedure (DMA) */ + dma_deinit(DMA0, DMA_CH6); + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_init_struct.memory_addr = (uint32_t)p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH6, &dma_init_struct); - i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH6); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { - osDelay(1); - } - /* send a stop condition to I2C bus*/ - i2c_stop_on_bus(I2C0); - } - timeout = 0; - state = I2C_STOP; - } - break; - case I2C_STOP: - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - i2c_timeout_flag = I2C_OK; - } else { - timeout = 0; - state = I2C_START; - in_rx_cycle = 0; - } - break; - default: - state = I2C_START; - in_rx_cycle = 0; - i2c_timeout_flag = I2C_OK; - timeout = 0; - break; - } - } - unlock(); - return true; + i2c_dma_last_transfer_config(I2C0, I2C_DMALST_ON); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH6); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH6, DMA_FLAG_FTF)) { + osDelay(1); + } + /* send a stop condition to I2C bus*/ + i2c_stop_on_bus(I2C0); + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + in_rx_cycle = 0; + } + break; + default: + state = I2C_START; + in_rx_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; + break; + } + } + unlock(); + return true; } -bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_buffer, uint16_t number_of_byte) { - if (!lock()) - return false; +bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, + uint8_t *p_buffer, uint16_t number_of_byte) { + if (!lock()) + return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - dma_parameter_struct dma_init_struct; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); + dma_parameter_struct dma_init_struct; - uint8_t state = I2C_START; - uint16_t timeout = 0; - bool done = false; - bool timedout = false; - while (!(done || timedout)) { - switch (state) { - case I2C_START: - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - timeout = 0; - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - timeout = 0; - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - state = I2C_TRANSMIT_DATA; - } else { - //Dont retry as this means a NAK - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - unlock(); - return false; - } - break; - case I2C_TRANSMIT_DATA: - /* wait until the transmit data buffer is empty */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - /* send the EEPROM's internal address to write to : only one byte address */ - i2c_data_transmit(I2C0, MemAddress); - timeout = 0; - } else { - timedout = true; - timeout = 0; - state = I2C_START; - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - dma_deinit(DMA0, DMA_CH5); - dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; - dma_init_struct.memory_addr = (uint32_t) p_buffer; - dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; - dma_init_struct.number = number_of_byte; - dma_init_struct.periph_addr = (uint32_t) &I2C_DATA(I2C0); - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; - dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; - dma_init(DMA0, DMA_CH5, &dma_init_struct); - /* enable I2C0 DMA */ - i2c_dma_enable(I2C0, I2C_DMA_ON); - /* enable DMA0 channel5 */ - dma_channel_enable(DMA0, DMA_CH5); - /* wait until BTC bit is set */ - while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { - osDelay(1); - } - /* wait until BTC bit is set */ - while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) - ; - state = I2C_STOP; - break; - case I2C_STOP: - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - done = true; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - default: - state = I2C_START; - timeout = 0; - break; - } - } - unlock(); - return timedout == false; + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + // Address NACK'd + unlock(); + return false; + } + } + timeout = 0; + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + state = I2C_TRANSMIT_DATA; + } else { + // Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + unlock(); + return false; + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte + * address */ + i2c_data_transmit(I2C0, MemAddress); + timeout = 0; + } else { + timedout = true; + timeout = 0; + state = I2C_START; + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + dma_deinit(DMA0, DMA_CH5); + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_addr = (uint32_t)p_buffer; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; + dma_init_struct.number = number_of_byte; + dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2C0); + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + dma_init(DMA0, DMA_CH5, &dma_init_struct); + /* enable I2C0 DMA */ + i2c_dma_enable(I2C0, I2C_DMA_ON); + /* enable DMA0 channel5 */ + dma_channel_enable(DMA0, DMA_CH5); + /* wait until BTC bit is set */ + while (!dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) { + osDelay(1); + } + /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C0, I2C_FLAG_BTC)) + ; + state = I2C_STOP; + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; } bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) { - return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); + return Mem_Write(DevAddress, pData[0], pData + 1, Size - 1); } bool FRToSI2C::probe(uint16_t DevAddress) { - uint8_t temp[1]; - return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); + uint8_t temp[1]; + return Mem_Read(DevAddress, 0x00, temp, sizeof(temp)); } -void FRToSI2C::I2C_Unstick() { - unstick_I2C(); -} +void FRToSI2C::I2C_Unstick() { unstick_I2C(); } bool FRToSI2C::lock() { - if (I2CSemaphore == nullptr) { - return false; - } - return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; + if (I2CSemaphore == nullptr) { + return false; + } + return xSemaphoreTake(I2CSemaphore, 1000) == pdTRUE; } -void FRToSI2C::unlock() { - xSemaphoreGive(I2CSemaphore); -} +void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); } -bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) { - for (int index = 0; index < registersLength; index++) { - if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) { - return false; - } - if (registers[index].pause_ms) { - delay_ms(registers[index].pause_ms); - } - } - return true; +bool FRToSI2C::writeRegistersBulk(const uint8_t address, + const I2C_REG *registers, + const uint8_t registersLength) { + for (int index = 0; index < registersLength; index++) { + if (!I2C_RegisterWrite(address, registers[index].reg, + registers[index].val)) { + return false; + } + if (registers[index].pause_ms) { + delay_ms(registers[index].pause_ms); + } + } + return true; } bool FRToSI2C::wakePart(uint16_t DevAddress) { - //wakepart is a special case where only the device address is sent - if (!lock()) - return false; + // wakepart is a special case where only the device address is sent + if (!lock()) + return false; - i2c_interrupt_disable(I2C0, I2C_INT_ERR); - i2c_interrupt_disable(I2C0, I2C_INT_EV); - i2c_interrupt_disable(I2C0, I2C_INT_BUF); - dma_parameter_struct dma_init_struct; + i2c_interrupt_disable(I2C0, I2C_INT_ERR); + i2c_interrupt_disable(I2C0, I2C_INT_EV); + i2c_interrupt_disable(I2C0, I2C_INT_BUF); - uint8_t state = I2C_START; - uint16_t timeout = 0; - bool done = false; - bool timedout = false; - while (!(done || timedout)) { - switch (state) { - case I2C_START: - /* i2c master sends start signal only when the bus is idle */ - while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_start_on_bus(I2C0); - timeout = 0; - state = I2C_SEND_ADDRESS; - } else { - I2C_Unstick(); - timeout = 0; - state = I2C_START; - } - break; - case I2C_SEND_ADDRESS: - /* i2c master sends START signal successfully */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); - timeout = 0; - state = I2C_CLEAR_ADDRESS_FLAG; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - case I2C_CLEAR_ADDRESS_FLAG: - /* address flag set means i2c slave sends ACK */ - while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT )) { - timeout++; - if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { - i2c_flag_clear(I2C0, I2C_FLAG_AERR); - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - //Address NACK'd - unlock(); - return false; - } - } - if (timeout < I2C_TIME_OUT) { - i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); - timeout = 0; - state = I2C_STOP; - } else { - //Dont retry as this means a NAK - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - unlock(); - return false; - } - break; + uint8_t state = I2C_START; + uint16_t timeout = 0; + bool done = false; + bool timedout = false; + while (!(done || timedout)) { + switch (state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_start_on_bus(I2C0); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + I2C_Unstick(); + timeout = 0; + state = I2C_START; + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_SBSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + i2c_master_addressing(I2C0, DevAddress, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while ((!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) && + (timeout < I2C_TIME_OUT)) { + timeout++; + if (i2c_flag_get(I2C0, I2C_FLAG_AERR)) { + i2c_flag_clear(I2C0, I2C_FLAG_AERR); + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + // Address NACK'd + unlock(); + return false; + } + } + if (timeout < I2C_TIME_OUT) { + i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_STOP; + } else { + // Dont retry as this means a NAK + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + unlock(); + return false; + } + break; - case I2C_STOP: - /* send a stop condition to I2C bus */ - i2c_stop_on_bus(I2C0); - /* i2c master sends STOP signal successfully */ - while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT )) { - timeout++; - } - if (timeout < I2C_TIME_OUT) { - timeout = 0; - state = I2C_END; - done = true; - } else { - timedout = true; - done = true; - timeout = 0; - state = I2C_START; - } - break; - default: - state = I2C_START; - timeout = 0; - break; - } - } - unlock(); - return timedout == false; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(I2C0); + /* i2c master sends STOP signal successfully */ + while ((I2C_CTL0(I2C0) & 0x0200) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if (timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + done = true; + } else { + timedout = true; + done = true; + timeout = 0; + state = I2C_START; + } + break; + default: + state = I2C_START; + timeout = 0; + break; + } + } + unlock(); + return timedout == false; } diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 314f894c..2319b90f 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -8,11 +8,13 @@ #include "BSP.h" #include "Pins.h" #include "gd32vf103.h" -#include #include "systick.h" +#include #define ADC_NORM_CHANNELS 2 #define ADC_NORM_SAMPLES 32 -uint16_t ADCReadings[ADC_NORM_SAMPLES * ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings +uint16_t + ADCReadings[ADC_NORM_SAMPLES * + ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings // Functions void setup_gpio(); @@ -23,272 +25,275 @@ void setup_timers(); void setup_iwdg(); void hardware_init() { + // GPIO + setup_gpio(); + // DMA + setup_dma(); + // I2C + setup_i2c(); + // ADC's + setup_adc(); + // Timers + setup_timers(); + // Watchdog + setup_iwdg(); - //GPIO - setup_gpio(); - //DMA - setup_dma(); - //I2C - setup_i2c(); - //ADC's - setup_adc(); - //Timers - setup_timers(); - //Watchdog - setup_iwdg(); - - /* enable TIMER1 - PWM control timing*/ - timer_enable(TIMER1); - timer_enable(TIMER2); - eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); - eclic_global_interrupt_enable(); + /* enable TIMER1 - PWM control timing*/ + timer_enable(TIMER1); + timer_enable(TIMER2); + eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); + eclic_global_interrupt_enable(); } // channel 0 -> temperature sensor, 1-> VIN uint16_t getADC(uint8_t channel) { - uint32_t sum = 0; - for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) - sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)]; - return sum >> 2; + uint32_t sum = 0; + for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) + sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)]; + return sum >> 2; } void setup_gpio() { - /* enable GPIOB clock */ - rcu_periph_clock_enable(RCU_GPIOA); - /* enable GPIOB clock */ - rcu_periph_clock_enable(RCU_GPIOB); - //Alternate function clock enable - rcu_periph_clock_enable(RCU_AF); - //Buttons as input - gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin); - gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin); - //OLED reset as output - gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, - OLED_RESET_Pin); - //I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, SDA_Pin | SCL_Pin); - //PWM output as AF Push Pull - gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, - PWM_Out_Pin); - //Analog Inputs ... as analog inputs - gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, - TMP36_INPUT_Pin); - gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, - TIP_TEMP_Pin); - gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, VIN_Pin); + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOA); + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOB); + // Alternate function clock enable + rcu_periph_clock_enable(RCU_AF); + // Buttons as input + gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin); + gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin); + // OLED reset as output + gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, + OLED_RESET_Pin); + // I2C as AF Open Drain + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); + // PWM output as AF Push Pull + gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); + // Analog Inputs ... as analog inputs + gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, + TMP36_INPUT_Pin); + gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, TIP_TEMP_Pin); + gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, VIN_Pin); - //Remap PB4 away from JTAG NJRST - gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); + // Remap PB4 away from JTAG NJRST + gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); - //TODO - rest of pins as floating + // TODO - rest of pins as floating } void setup_dma() { - //Setup DMA for ADC0 - { - /* enable DMA0 clock */ - rcu_periph_clock_enable(RCU_DMA0); - rcu_periph_clock_enable(RCU_DMA1); - /* ADC_DMA_channel configuration */ - dma_parameter_struct dma_data_parameter; + // Setup DMA for ADC0 + { + /* enable DMA0 clock */ + rcu_periph_clock_enable(RCU_DMA0); + rcu_periph_clock_enable(RCU_DMA1); + /* ADC_DMA_channel configuration */ + dma_parameter_struct dma_data_parameter; - /* ADC DMA_channel configuration */ - dma_deinit(DMA0, DMA_CH0); + /* ADC DMA_channel configuration */ + dma_deinit(DMA0, DMA_CH0); - /* initialize DMA data mode */ - dma_data_parameter.periph_addr = (uint32_t) (&ADC_RDATA(ADC0)); - dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_data_parameter.memory_addr = (uint32_t) (ADCReadings); - dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; - dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; - dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS; - dma_data_parameter.priority = DMA_PRIORITY_HIGH; - dma_init(DMA0, DMA_CH0, &dma_data_parameter); + /* initialize DMA data mode */ + dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0)); + dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_data_parameter.memory_addr = (uint32_t)(ADCReadings); + dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; + dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; + dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS; + dma_data_parameter.priority = DMA_PRIORITY_HIGH; + dma_init(DMA0, DMA_CH0, &dma_data_parameter); - dma_circulation_enable(DMA0, DMA_CH0); + dma_circulation_enable(DMA0, DMA_CH0); - /* enable DMA channel */ - dma_channel_enable(DMA0, DMA_CH0); - } + /* enable DMA channel */ + dma_channel_enable(DMA0, DMA_CH0); + } } void setup_i2c() { - /* enable I2C0 clock */ - rcu_periph_clock_enable(RCU_I2C0); - //Setup I20 at 400kHz - i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); - i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); - i2c_enable(I2C0); - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - eclic_irq_enable(I2C0_EV_IRQn, 1, 0); - eclic_irq_enable(I2C0_ER_IRQn, 2, 0); + /* enable I2C0 clock */ + rcu_periph_clock_enable(RCU_I2C0); + // Setup I20 at 400kHz + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); + i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); + i2c_enable(I2C0); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + eclic_irq_enable(I2C0_EV_IRQn, 1, 0); + eclic_irq_enable(I2C0_ER_IRQn, 2, 0); } void setup_adc() { - //Setup ADC in normal + injected mode - //Want it to sample handle temp and input voltage normally via dma - //Then injected trigger to sample tip temp - memset(ADCReadings, 0, sizeof(ADCReadings)); - rcu_periph_clock_enable(RCU_ADC0); - rcu_periph_clock_enable(RCU_ADC1); - adc_deinit(ADC0); - adc_deinit(ADC1); - /* config ADC clock */ - rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16); - //Run in normal parallel + inserted parallel - adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); - adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); - adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); - adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); - adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE); - //Align right - adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); - adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); - //Setup reading 2 channels on regular mode (Handle Temp + dc in) - adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); - adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); - //Setup the two channels - adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //temp sensor - adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage - adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, ADC_SAMPLETIME_71POINT5); //DC Input voltage - //Setup that we want all 4 inserted readings to be the tip temp - adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); - adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); - for (int rank = 0; rank < 4; rank++) { - adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, ADC_SAMPLETIME_1POINT5); - adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, ADC_SAMPLETIME_1POINT5); - } - //Setup timer 1 channel 0 to trigger injected measurements - adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0); - adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, ADC0_1_EXTTRIG_INSERTED_T1_CH0); + // Setup ADC in normal + injected mode + // Want it to sample handle temp and input voltage normally via dma + // Then injected trigger to sample tip temp + memset(ADCReadings, 0, sizeof(ADCReadings)); + rcu_periph_clock_enable(RCU_ADC0); + rcu_periph_clock_enable(RCU_ADC1); + adc_deinit(ADC0); + adc_deinit(ADC1); + /* config ADC clock */ + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16); + // Run in normal parallel + inserted parallel + adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); + adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE); + // Align right + adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); + adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); + // Setup reading 2 channels on regular mode (Handle Temp + dc in) + adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); + adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); + // Setup the two channels + adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, + ADC_SAMPLETIME_71POINT5); // temp sensor + adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); // temp sensor + adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, + ADC_SAMPLETIME_71POINT5); // DC Input voltage + adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); // DC Input voltage + // Setup that we want all 4 inserted readings to be the tip temp + adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); + adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); + for (int rank = 0; rank < 4; rank++) { + adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, + ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, + ADC_SAMPLETIME_1POINT5); + } + // Setup timer 1 channel 0 to trigger injected measurements + adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); + adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); - adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); - adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); - // Enable triggers for the ADC - adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); - adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); - adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); - adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE); + adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + // Enable triggers for the ADC + adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); + adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE); - adc_watchdog_disable(ADC0); - adc_watchdog_disable(ADC1); - adc_resolution_config(ADC0, ADC_RESOLUTION_12B); - adc_resolution_config(ADC1, ADC_RESOLUTION_12B); - /* clear the ADC flag */ - adc_oversample_mode_disable(ADC0); - adc_oversample_mode_disable(ADC1); - adc_enable(ADC0); - delay_1ms(1); - adc_calibration_enable(ADC0); - adc_enable(ADC1); - delay_1ms(1); - adc_calibration_enable(ADC1); - delay_1ms(1); - adc_dma_mode_enable(ADC0); - //Enable interrupt on end of injected readings - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); - adc_interrupt_enable(ADC0, ADC_INT_EOIC); - eclic_irq_enable(ADC0_1_IRQn, 2, 0); - adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); - adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); - adc_tempsensor_vrefint_disable(); + adc_watchdog_disable(ADC0); + adc_watchdog_disable(ADC1); + adc_resolution_config(ADC0, ADC_RESOLUTION_12B); + adc_resolution_config(ADC1, ADC_RESOLUTION_12B); + /* clear the ADC flag */ + adc_oversample_mode_disable(ADC0); + adc_oversample_mode_disable(ADC1); + adc_enable(ADC0); + adc_calibration_enable(ADC0); + adc_enable(ADC1); + adc_calibration_enable(ADC1); + adc_dma_mode_enable(ADC0); + // Enable interrupt on end of injected readings + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); + adc_interrupt_enable(ADC0, ADC_INT_EOIC); + eclic_irq_enable(ADC0_1_IRQn, 2, 0); + adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); + adc_tempsensor_vrefint_disable(); } void setup_timers() { - //Setup timer 1 to run the actual PWM level - /* enable timer1 clock */ - rcu_periph_clock_enable(RCU_TIMER1); - rcu_periph_clock_enable(RCU_TIMER2); - timer_oc_parameter_struct timer_ocintpara; - timer_parameter_struct timer_initpara; - { - //deinit to reset the timer - timer_deinit(TIMER1); - /* initialize TIMER init parameter struct */ - timer_struct_para_init(&timer_initpara); - /* TIMER1 configuration */ - timer_initpara.prescaler = 24000; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = powerPWM + tempMeasureTicks; - timer_initpara.clockdivision = TIMER_CKDIV_DIV4; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER1, &timer_initpara); + // Setup timer 1 to run the actual PWM level + /* enable timer1 clock */ + rcu_periph_clock_enable(RCU_TIMER1); + rcu_periph_clock_enable(RCU_TIMER2); + timer_oc_parameter_struct timer_ocintpara; + timer_parameter_struct timer_initpara; + { + // deinit to reset the timer + timer_deinit(TIMER1); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 24000; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = powerPWM + tempMeasureTicks; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER1, &timer_initpara); - /* CH0 configured to implement the PWM irq's for the output control*/ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); + /* CH0 configured to implement the PWM irq's for the output control*/ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, powerPWM + holdoffTicks); - timer_channel_output_mode_config(TIMER1, TIMER_CH_0, - TIMER_OC_MODE_PWM1); - timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, - TIMER_OC_SHADOW_DISABLE); - /* CH1 used for irq */ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, + powerPWM + holdoffTicks); + timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM1); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + /* CH1 used for irq */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0); - timer_channel_output_mode_config(TIMER1, TIMER_CH_1, - TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, - TIMER_OC_SHADOW_DISABLE); - //IRQ - timer_interrupt_enable(TIMER1, TIMER_INT_UP); - timer_interrupt_enable(TIMER1, TIMER_INT_CH1); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0); + timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, + TIMER_OC_SHADOW_DISABLE); + // IRQ + timer_interrupt_enable(TIMER1, TIMER_INT_UP); + timer_interrupt_enable(TIMER1, TIMER_INT_CH1); + } - } + eclic_irq_enable(TIMER1_IRQn, 2, 5); + // Setup timer 2 to control the output signal + { + timer_deinit(TIMER2); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 200; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 100; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER2, &timer_initpara); - eclic_irq_enable(TIMER1_IRQn, 2, 5); - //Setup timer 2 to control the output signal - { - timer_deinit(TIMER2); - /* initialize TIMER init parameter struct */ - timer_struct_para_init(&timer_initpara); - /* TIMER1 configuration */ - timer_initpara.prescaler = 200; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = 100; - timer_initpara.clockdivision = TIMER_CKDIV_DIV4; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER2, &timer_initpara); - - /* CH0 configuration in PWM mode0 */ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; - timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; - timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; - timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); - timer_channel_output_mode_config(TIMER2, TIMER_CH_0, - TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, - TIMER_OC_SHADOW_DISABLE); - timer_auto_reload_shadow_enable(TIMER2); - timer_enable(TIMER2); - } + /* CH0 configuration in PWM mode0 */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); + timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + timer_auto_reload_shadow_enable(TIMER2); + timer_enable(TIMER2); + } } void setup_iwdg() { - //TODO + // TODO } void setupFUSBIRQ() { - //Setup IRQ for USB-PD - gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, FUSB302_IRQ_Pin); - eclic_irq_enable(EXTI5_9_IRQn, 1, 1); - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); + // Setup IRQ for USB-PD + gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, + FUSB302_IRQ_Pin); + eclic_irq_enable(EXTI5_9_IRQn, 1, 1); + /* connect key EXTI line to key GPIO pin */ + gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); - /* configure key EXTI line */ - exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(EXTI_5); + /* configure key EXTI line */ + exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); + exti_interrupt_flag_clear(EXTI_5); } From f445e2771c9f3b285d9db59a1338fdd00e57a54d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 13:36:50 +1100 Subject: [PATCH 52/72] Update Makefile --- workspace/TS100/Makefile | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 880f1995..dd996c1e 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -7,11 +7,6 @@ ifndef lang lang:= EN endif - - -# Discover the source files to build - - # Enumerate all of the include directories APP_INC_DIR = ./Core/Inc INC_CMSIS_DEVICE = ./Core/BSP/Miniware/Vendor/CMSIS/Device/ST/STM32F1xx/Include @@ -48,16 +43,17 @@ S_SRCS := ./Startup/startup_stm32f103t8ux.S LDSCRIPT=stm32f103.ld DEV_GLOBAL_DEFS= -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D GCC_ARMCM3 \ -D ARM_MATH_CM3 \ - -D STM32F10X_MD -DEV_LDFLAGS=-lm -Wl,--gc-sections -DEV_AFLAGS= -DEV_CFLAGS= -DEV_CXXFLAGS= + -D STM32F10X_MD +DEV_LDFLAGS=-lm -Wl,--gc-sections -flto +DEV_AFLAGS=-flto +DEV_CFLAGS=-flto +DEV_CXXFLAGS=-flto flash_size=64k bootldr_size=0x4000 endif ifeq ($(model),Pinecil) +$(info Building for Pine64 ) DEVICE_INCLUDES = -I$(PINE_INC_DIR) \ -I$(PINE_INC_DIR)/N200 \ -I$(PINE_VENDOR_INC_DIR) \ @@ -103,7 +99,7 @@ OUTPUT_DIR=Objects # code optimisation ------------------------------------------------------------ OPTIM_AS= -Wall -OPTIM=-Os -flto -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections +OPTIM=-Os -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections # global defines --------------------------------------------------------------- @@ -134,7 +130,6 @@ endif CC=$(COMPILER_PREFIX)-gcc CPP=$(COMPILER_PREFIX)-g++ AS=$(COMPILER_PREFIX)-as -GCOV=$(COMPILER_PREFIX)-gcov OBJCOPY=$(COMPILER_PREFIX)-objcopy OBJDUMP=$(COMPILER_PREFIX)-objdump SIZE=$(COMPILER_PREFIX)-size @@ -168,8 +163,8 @@ LINKER_FLAGS=$(CPUFLAGS) \ -MMD \ -std=c++11 \ $(OPTIM) \ + -ffreestanding \ -fno-common \ - -ffreestanding \ -fno-rtti \ -fno-exceptions \ -fno-non-call-exceptions \ @@ -230,8 +225,8 @@ CXXFLAGS=$(CPUFLAGS) \ $(CHECKOPTIONS) \ -std=c++11 \ $(OPTIM) \ + -ffreestanding \ -fno-common \ - -ffreestanding \ -fno-rtti \ -fno-exceptions \ -fno-non-call-exceptions \ @@ -248,11 +243,11 @@ CFLAGS=$(CPUFLAGS) \ $(GLOBAL_DEFINES) \ -D${COMPILER} \ -MMD \ + -ffreestanding \ -std=gnu99 \ $(OPTIM) \ $(DEV_CFLAGS) \ -fno-common \ - -ffreestanding \ -c From 9f4bcf2875f8454abd7e6383df04c6c9fef59943 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 13:39:45 +1100 Subject: [PATCH 53/72] Default timer to off in setup --- workspace/TS100/Core/BSP/Pine64/IRQ.cpp | 146 ++++++++++++------------ workspace/TS100/Core/BSP/Pine64/Setup.c | 2 +- 2 files changed, 72 insertions(+), 76 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp index f9654cfd..b9a46356 100644 --- a/workspace/TS100/Core/BSP/Pine64/IRQ.cpp +++ b/workspace/TS100/Core/BSP/Pine64/IRQ.cpp @@ -12,114 +12,110 @@ volatile uint8_t i2c_read_process = 0; volatile uint8_t i2c_write_process = 0; volatile uint8_t i2c_slave_address = 0; volatile uint8_t i2c_error_code = 0; -volatile uint8_t* i2c_write; -volatile uint8_t* i2c_read; +volatile uint8_t *i2c_write; +volatile uint8_t *i2c_read; volatile uint16_t i2c_nbytes; volatile uint16_t i2c_write_dress; volatile uint16_t i2c_read_dress; volatile uint8_t i2c_process_flag = 0; void ADC0_1_IRQHandler(void) { - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); - //unblock the PID controller thread - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (pidTaskNotification) { - vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); + // unblock the PID controller thread + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (pidTaskNotification) { + vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } } volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; void TIMER1_IRQHandler(void) { - if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) { - timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP); - //rollover turn on output if required - if (PWMSafetyTimer && pendingPWM) { - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 80); - } - if (PWMSafetyTimer) { - PWMSafetyTimer--; - } - } - if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) { - timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1); - //This is triggered on pwm setpoint trigger; we want to copy the pending PWM value into the output control reg + if (timer_interrupt_flag_get(TIMER1, TIMER_INT_UP) == SET) { + timer_interrupt_flag_clear(TIMER1, TIMER_INT_UP); + // rollover turn on output if required + if (PWMSafetyTimer && pendingPWM) { + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); + } + if (PWMSafetyTimer) { + PWMSafetyTimer--; + } + } + if (timer_interrupt_flag_get(TIMER1, TIMER_INT_CH1) == SET) { + timer_interrupt_flag_clear(TIMER1, TIMER_INT_CH1); + // This is triggered on pwm setpoint trigger; we want to copy the pending + // PWM value into the output control reg - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); - if (pendingPWM) { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); - } - } + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); + if (pendingPWM) { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, pendingPWM); + } + } } void setTipPWM(uint8_t pulse) { - PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is - // disabled if the PID task is not scheduled often enough. - pendingPWM = pulse; + PWMSafetyTimer = + 10; // This is decremented in the handler for PWM so that the tip pwm is + // disabled if the PID task is not scheduled often enough. + pendingPWM = pulse; } static bool fastPWM; static void switchToFastPWM(void) { - fastPWM = true; - totalPWM = powerPWM + tempMeasureTicks * 2; - TIMER_CAR(TIMER1) = (uint32_t)totalPWM; - - // ~3.5 Hz rate - TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2; - //1 kHz tick rate - TIMER_PSC(TIMER1) = 12000; - /* generate an update event */ - TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG; + fastPWM = true; + totalPWM = powerPWM + tempMeasureTicks * 2; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + // ~3.5 Hz rate + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks * 2; + // 1 kHz tick rate + TIMER_PSC(TIMER1) = 12000; + /* generate an update event */ + TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG; } static void switchToSlowPWM(void) { - fastPWM = false; - totalPWM = powerPWM + tempMeasureTicks; - TIMER_CAR(TIMER1) = (uint32_t)totalPWM; - // ~1.84 Hz rate - TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks; - // 500 Hz tick rate - TIMER_PSC(TIMER1) = 24000; - /* generate an update event */ - TIMER_SWEVG(TIMER1) |= (uint32_t) TIMER_SWEVG_UPG; - + fastPWM = false; + totalPWM = powerPWM + tempMeasureTicks; + TIMER_CAR(TIMER1) = (uint32_t)totalPWM; + // ~1.84 Hz rate + TIMER_CH0CV(TIMER1) = powerPWM + holdoffTicks; + // 500 Hz tick rate + TIMER_PSC(TIMER1) = 24000; + /* generate an update event */ + TIMER_SWEVG(TIMER1) |= (uint32_t)TIMER_SWEVG_UPG; } bool tryBetterPWM(uint8_t pwm) { - if (fastPWM && pwm == powerPWM) { - // maximum power for fast PWM reached, need to go slower to get more - switchToSlowPWM(); - return true; - } else if (!fastPWM && pwm < 230) { - // 254 in fast PWM mode gives the same power as 239 in slow - // allow for some reasonable hysteresis by switching only when it goes - // below 230 (equivalent to 245 in fast mode) - switchToFastPWM(); - return true; - } - return false; + if (fastPWM && pwm == powerPWM) { + // maximum power for fast PWM reached, need to go slower to get more + switchToSlowPWM(); + return true; + } else if (!fastPWM && pwm < 230) { + // 254 in fast PWM mode gives the same power as 239 in slow + // allow for some reasonable hysteresis by switching only when it goes + // below 230 (equivalent to 245 in fast mode) + switchToFastPWM(); + return true; + } + return false; } void EXTI5_9_IRQHandler(void) { #ifdef POW_PD - if (RESET != exti_interrupt_flag_get(EXTI_5)) { - exti_interrupt_flag_clear(EXTI_5); + if (RESET != exti_interrupt_flag_get(EXTI_5)) { + exti_interrupt_flag_clear(EXTI_5); - if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) { - InterruptHandler::irqCallback(); - } - } + if (RESET == gpio_input_bit_get(FUSB302_IRQ_GPIO_Port, FUSB302_IRQ_Pin)) { + InterruptHandler::irqCallback(); + } + } #endif } -//These are unused for now -void I2C0_EV_IRQHandler(void) { +// These are unused for now +void I2C0_EV_IRQHandler(void) {} -} - -void I2C0_ER_IRQHandler(void) { - -} +void I2C0_ER_IRQHandler(void) {} diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 2319b90f..783a0935 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -273,7 +273,7 @@ void setup_timers() { timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 50); + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0); timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE); From 7fda7f853242a4c167b2b7abed15d98c49df7518 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 13:58:33 +1100 Subject: [PATCH 54/72] Update Makefile --- workspace/TS100/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index dd996c1e..9330f4d1 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -45,7 +45,7 @@ DEV_GLOBAL_DEFS= -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32 -D ARM_MATH_CM3 \ -D STM32F10X_MD DEV_LDFLAGS=-lm -Wl,--gc-sections -flto -DEV_AFLAGS=-flto +DEV_AFLAGS= DEV_CFLAGS=-flto DEV_CXXFLAGS=-flto flash_size=64k From 34266567c9180691e103e98bc2ce7ba99d2b8e50 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:01:56 +1100 Subject: [PATCH 55/72] Update Setup.c --- workspace/TS100/Core/BSP/Pine64/Setup.c | 478 ++++++++++++------------ 1 file changed, 239 insertions(+), 239 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/Setup.c b/workspace/TS100/Core/BSP/Pine64/Setup.c index 783a0935..98ccf7c6 100644 --- a/workspace/TS100/Core/BSP/Pine64/Setup.c +++ b/workspace/TS100/Core/BSP/Pine64/Setup.c @@ -12,9 +12,8 @@ #include #define ADC_NORM_CHANNELS 2 #define ADC_NORM_SAMPLES 32 -uint16_t - ADCReadings[ADC_NORM_SAMPLES * - ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings +uint16_t ADCReadings[ADC_NORM_SAMPLES * +ADC_NORM_CHANNELS]; // room for 32 lots of the pair of readings // Functions void setup_gpio(); @@ -25,275 +24,276 @@ void setup_timers(); void setup_iwdg(); void hardware_init() { - // GPIO - setup_gpio(); - // DMA - setup_dma(); - // I2C - setup_i2c(); - // ADC's - setup_adc(); - // Timers - setup_timers(); - // Watchdog - setup_iwdg(); + // GPIO + setup_gpio(); + // DMA + setup_dma(); + // I2C + setup_i2c(); + // ADC's + setup_adc(); + // Timers + setup_timers(); + // Watchdog + setup_iwdg(); - /* enable TIMER1 - PWM control timing*/ - timer_enable(TIMER1); - timer_enable(TIMER2); - eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); - eclic_global_interrupt_enable(); + /* enable TIMER1 - PWM control timing*/ + timer_enable(TIMER1); + timer_enable(TIMER2); + eclic_priority_group_set(ECLIC_PRIGROUP_LEVEL4_PRIO0); + eclic_global_interrupt_enable(); } // channel 0 -> temperature sensor, 1-> VIN uint16_t getADC(uint8_t channel) { - uint32_t sum = 0; - for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) - sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)]; - return sum >> 2; + uint32_t sum = 0; + for (uint8_t i = 0; i < ADC_NORM_SAMPLES; i++) + sum += ADCReadings[channel + (i * ADC_NORM_CHANNELS)]; + return sum >> 2; } void setup_gpio() { - /* enable GPIOB clock */ - rcu_periph_clock_enable(RCU_GPIOA); - /* enable GPIOB clock */ - rcu_periph_clock_enable(RCU_GPIOB); - // Alternate function clock enable - rcu_periph_clock_enable(RCU_AF); - // Buttons as input - gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin); - gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin); - // OLED reset as output - gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, - OLED_RESET_Pin); - // I2C as AF Open Drain - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, - SDA_Pin | SCL_Pin); - // PWM output as AF Push Pull - gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); - // Analog Inputs ... as analog inputs - gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, - TMP36_INPUT_Pin); - gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, TIP_TEMP_Pin); - gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, VIN_Pin); + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOA); + /* enable GPIOB clock */ + rcu_periph_clock_enable(RCU_GPIOB); + // Alternate function clock enable + rcu_periph_clock_enable(RCU_AF); + // Buttons as input + gpio_init(KEY_A_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_A_Pin); + gpio_init(KEY_B_GPIO_Port, GPIO_MODE_IPD, GPIO_OSPEED_2MHZ, KEY_B_Pin); + // OLED reset as output + gpio_init(OLED_RESET_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, + OLED_RESET_Pin); + // I2C as AF Open Drain + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); + // PWM output as AF Push Pull + gpio_init(PWM_Out_GPIO_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_Out_Pin); + // Analog Inputs ... as analog inputs + gpio_init(TMP36_INPUT_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, + TMP36_INPUT_Pin); + gpio_init(TIP_TEMP_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, TIP_TEMP_Pin); + gpio_init(VIN_GPIO_Port, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, VIN_Pin); - // Remap PB4 away from JTAG NJRST - gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); + // Remap PB4 away from JTAG NJRST + gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); - // TODO - rest of pins as floating + // TODO - rest of pins as floating } void setup_dma() { - // Setup DMA for ADC0 - { - /* enable DMA0 clock */ - rcu_periph_clock_enable(RCU_DMA0); - rcu_periph_clock_enable(RCU_DMA1); - /* ADC_DMA_channel configuration */ - dma_parameter_struct dma_data_parameter; + // Setup DMA for ADC0 + { + /* enable DMA0 clock */ + rcu_periph_clock_enable(RCU_DMA0); + rcu_periph_clock_enable(RCU_DMA1); + /* ADC_DMA_channel configuration */ + dma_parameter_struct dma_data_parameter; - /* ADC DMA_channel configuration */ - dma_deinit(DMA0, DMA_CH0); + /* ADC DMA_channel configuration */ + dma_deinit(DMA0, DMA_CH0); - /* initialize DMA data mode */ - dma_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(ADC0)); - dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; - dma_data_parameter.memory_addr = (uint32_t)(ADCReadings); - dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; - dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; - dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; - dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; - dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS; - dma_data_parameter.priority = DMA_PRIORITY_HIGH; - dma_init(DMA0, DMA_CH0, &dma_data_parameter); + /* initialize DMA data mode */ + dma_data_parameter.periph_addr = (uint32_t) (&ADC_RDATA(ADC0)); + dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE; + dma_data_parameter.memory_addr = (uint32_t) (ADCReadings); + dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_data_parameter.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; + dma_data_parameter.memory_width = DMA_MEMORY_WIDTH_16BIT; + dma_data_parameter.direction = DMA_PERIPHERAL_TO_MEMORY; + dma_data_parameter.number = ADC_NORM_SAMPLES * ADC_NORM_CHANNELS; + dma_data_parameter.priority = DMA_PRIORITY_HIGH; + dma_init(DMA0, DMA_CH0, &dma_data_parameter); - dma_circulation_enable(DMA0, DMA_CH0); + dma_circulation_enable(DMA0, DMA_CH0); - /* enable DMA channel */ - dma_channel_enable(DMA0, DMA_CH0); - } + /* enable DMA channel */ + dma_channel_enable(DMA0, DMA_CH0); + } } void setup_i2c() { - /* enable I2C0 clock */ - rcu_periph_clock_enable(RCU_I2C0); - // Setup I20 at 400kHz - i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); - i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); - i2c_enable(I2C0); - /* enable acknowledge */ - i2c_ack_config(I2C0, I2C_ACK_ENABLE); - eclic_irq_enable(I2C0_EV_IRQn, 1, 0); - eclic_irq_enable(I2C0_ER_IRQn, 2, 0); + /* enable I2C0 clock */ + rcu_periph_clock_enable(RCU_I2C0); + // Setup I20 at 400kHz + i2c_clock_config(I2C0, 400 * 1000, I2C_DTCY_16_9); + i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00); + i2c_enable(I2C0); + /* enable acknowledge */ + i2c_ack_config(I2C0, I2C_ACK_ENABLE); + eclic_irq_enable(I2C0_EV_IRQn, 1, 0); + eclic_irq_enable(I2C0_ER_IRQn, 2, 0); } void setup_adc() { - // Setup ADC in normal + injected mode - // Want it to sample handle temp and input voltage normally via dma - // Then injected trigger to sample tip temp - memset(ADCReadings, 0, sizeof(ADCReadings)); - rcu_periph_clock_enable(RCU_ADC0); - rcu_periph_clock_enable(RCU_ADC1); - adc_deinit(ADC0); - adc_deinit(ADC1); - /* config ADC clock */ - rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16); - // Run in normal parallel + inserted parallel - adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); - adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); - adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); - adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); - adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE); - // Align right - adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); - adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); - // Setup reading 2 channels on regular mode (Handle Temp + dc in) - adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); - adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); - // Setup the two channels - adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, - ADC_SAMPLETIME_71POINT5); // temp sensor - adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, - ADC_SAMPLETIME_71POINT5); // temp sensor - adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, - ADC_SAMPLETIME_71POINT5); // DC Input voltage - adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, - ADC_SAMPLETIME_71POINT5); // DC Input voltage - // Setup that we want all 4 inserted readings to be the tip temp - adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); - adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); - for (int rank = 0; rank < 4; rank++) { - adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, - ADC_SAMPLETIME_1POINT5); - adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, - ADC_SAMPLETIME_1POINT5); - } - // Setup timer 1 channel 0 to trigger injected measurements - adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, - ADC0_1_EXTTRIG_INSERTED_T1_CH0); - adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, - ADC0_1_EXTTRIG_INSERTED_T1_CH0); + // Setup ADC in normal + injected mode + // Want it to sample handle temp and input voltage normally via dma + // Then injected trigger to sample tip temp + memset(ADCReadings, 0, sizeof(ADCReadings)); + rcu_periph_clock_enable(RCU_ADC0); + rcu_periph_clock_enable(RCU_ADC1); + adc_deinit(ADC0); + adc_deinit(ADC1); + /* config ADC clock */ + rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV16); + // Run in normal parallel + inserted parallel + adc_mode_config(ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL); + adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE); + adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE); + // Align right + adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); + adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT); + // Setup reading 2 channels on regular mode (Handle Temp + dc in) + adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); + adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, ADC_NORM_CHANNELS); + // Setup the two channels + adc_regular_channel_config(ADC0, 0, TMP36_ADC0_CHANNEL, + ADC_SAMPLETIME_71POINT5); // temp sensor + adc_regular_channel_config(ADC1, 0, TMP36_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); // temp sensor + adc_regular_channel_config(ADC0, 1, VIN_ADC0_CHANNEL, + ADC_SAMPLETIME_71POINT5); // DC Input voltage + adc_regular_channel_config(ADC1, 1, VIN_ADC1_CHANNEL, + ADC_SAMPLETIME_71POINT5); // DC Input voltage + // Setup that we want all 4 inserted readings to be the tip temp + adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 4); + adc_channel_length_config(ADC1, ADC_INSERTED_CHANNEL, 4); + for (int rank = 0; rank < 4; rank++) { + adc_inserted_channel_config(ADC0, rank, TIP_TEMP_ADC0_CHANNEL, + ADC_SAMPLETIME_1POINT5); + adc_inserted_channel_config(ADC1, rank, TIP_TEMP_ADC1_CHANNEL, + ADC_SAMPLETIME_1POINT5); + } + // Setup timer 1 channel 0 to trigger injected measurements + adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); + adc_external_trigger_source_config(ADC1, ADC_INSERTED_CHANNEL, + ADC0_1_EXTTRIG_INSERTED_T1_CH0); - adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, - ADC0_1_EXTTRIG_REGULAR_NONE); - adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, - ADC0_1_EXTTRIG_REGULAR_NONE); - // Enable triggers for the ADC - adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); - adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); - adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); - adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE); + adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, + ADC0_1_EXTTRIG_REGULAR_NONE); + // Enable triggers for the ADC + adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_INSERTED_CHANNEL, ENABLE); + adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); + adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE); - adc_watchdog_disable(ADC0); - adc_watchdog_disable(ADC1); - adc_resolution_config(ADC0, ADC_RESOLUTION_12B); - adc_resolution_config(ADC1, ADC_RESOLUTION_12B); - /* clear the ADC flag */ - adc_oversample_mode_disable(ADC0); - adc_oversample_mode_disable(ADC1); - adc_enable(ADC0); - adc_calibration_enable(ADC0); - adc_enable(ADC1); - adc_calibration_enable(ADC1); - adc_dma_mode_enable(ADC0); - // Enable interrupt on end of injected readings - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); - adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); - adc_interrupt_enable(ADC0, ADC_INT_EOIC); - eclic_irq_enable(ADC0_1_IRQn, 2, 0); - adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); - adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); - adc_tempsensor_vrefint_disable(); + adc_watchdog_disable(ADC0); + adc_watchdog_disable(ADC1); + adc_resolution_config(ADC0, ADC_RESOLUTION_12B); + adc_resolution_config(ADC1, ADC_RESOLUTION_12B); + /* clear the ADC flag */ + adc_oversample_mode_disable(ADC0); + adc_oversample_mode_disable(ADC1); + adc_enable(ADC0); + adc_calibration_enable(ADC0); + adc_enable(ADC1); + adc_calibration_enable(ADC1); + adc_dma_mode_enable(ADC0); + // Enable interrupt on end of injected readings + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC); + adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC); + adc_interrupt_enable(ADC0, ADC_INT_EOIC); + eclic_irq_enable(ADC0_1_IRQn, 2, 0); + adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); + adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); + adc_tempsensor_vrefint_disable(); } void setup_timers() { - // Setup timer 1 to run the actual PWM level - /* enable timer1 clock */ - rcu_periph_clock_enable(RCU_TIMER1); - rcu_periph_clock_enable(RCU_TIMER2); - timer_oc_parameter_struct timer_ocintpara; - timer_parameter_struct timer_initpara; - { - // deinit to reset the timer - timer_deinit(TIMER1); - /* initialize TIMER init parameter struct */ - timer_struct_para_init(&timer_initpara); - /* TIMER1 configuration */ - timer_initpara.prescaler = 24000; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = powerPWM + tempMeasureTicks; - timer_initpara.clockdivision = TIMER_CKDIV_DIV4; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER1, &timer_initpara); + // Setup timer 1 to run the actual PWM level + /* enable timer1 clock */ + rcu_periph_clock_enable(RCU_TIMER1); + rcu_periph_clock_enable(RCU_TIMER2); + timer_oc_parameter_struct timer_ocintpara; + timer_parameter_struct timer_initpara; + { + // deinit to reset the timer + timer_deinit(TIMER1); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 24000; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = powerPWM + tempMeasureTicks; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER1, &timer_initpara); - /* CH0 configured to implement the PWM irq's for the output control*/ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); + /* CH0 configured to implement the PWM irq's for the output control*/ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, - powerPWM + holdoffTicks); - timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM1); - timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, - TIMER_OC_SHADOW_DISABLE); - /* CH1 used for irq */ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, powerPWM + holdoffTicks); + timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM1); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + /* CH1 used for irq */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0); - timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, - TIMER_OC_SHADOW_DISABLE); - // IRQ - timer_interrupt_enable(TIMER1, TIMER_INT_UP); - timer_interrupt_enable(TIMER1, TIMER_INT_CH1); - } + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 0); + timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, + TIMER_OC_SHADOW_DISABLE); + // IRQ + timer_interrupt_enable(TIMER1, TIMER_INT_UP); + timer_interrupt_enable(TIMER1, TIMER_INT_CH1); + } - eclic_irq_enable(TIMER1_IRQn, 2, 5); - // Setup timer 2 to control the output signal - { - timer_deinit(TIMER2); - /* initialize TIMER init parameter struct */ - timer_struct_para_init(&timer_initpara); - /* TIMER1 configuration */ - timer_initpara.prescaler = 200; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = 100; - timer_initpara.clockdivision = TIMER_CKDIV_DIV4; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER2, &timer_initpara); + eclic_irq_enable(TIMER1_IRQn, 2, 5); + // Setup timer 2 to control the output signal + { + timer_deinit(TIMER2); + /* initialize TIMER init parameter struct */ + timer_struct_para_init(&timer_initpara); + /* TIMER1 configuration */ + timer_initpara.prescaler = 200; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = 100; + timer_initpara.clockdivision = TIMER_CKDIV_DIV4; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER2, &timer_initpara); - /* CH0 configuration in PWM mode0 */ - timer_channel_output_struct_para_init(&timer_ocintpara); - timer_ocintpara.outputstate = TIMER_CCX_ENABLE; - timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; - timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; - timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; - timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; - timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; - timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); - timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); - timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0); - timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, - TIMER_OC_SHADOW_DISABLE); - timer_auto_reload_shadow_enable(TIMER2); - timer_enable(TIMER2); - } + /* CH0 configuration in PWM mode0 */ + timer_channel_output_struct_para_init(&timer_ocintpara); + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + timer_channel_output_config(TIMER2, TIMER_CH_0, &timer_ocintpara); + timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_0, 0); + timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(TIMER2, TIMER_CH_0, + TIMER_OC_SHADOW_DISABLE); + timer_auto_reload_shadow_enable(TIMER2); + timer_enable(TIMER2); + } } void setup_iwdg() { - // TODO + + fwdgt_config(0x0FFF, FWDGT_PSC_DIV256); + fwdgt_enable(); } void setupFUSBIRQ() { - // Setup IRQ for USB-PD - gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, - FUSB302_IRQ_Pin); - eclic_irq_enable(EXTI5_9_IRQn, 1, 1); - /* connect key EXTI line to key GPIO pin */ - gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); + // Setup IRQ for USB-PD + gpio_init(FUSB302_IRQ_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_2MHZ, + FUSB302_IRQ_Pin); + eclic_irq_enable(EXTI5_9_IRQn, 1, 1); + /* connect key EXTI line to key GPIO pin */ + gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_5); - /* configure key EXTI line */ - exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); - exti_interrupt_flag_clear(EXTI_5); + /* configure key EXTI line */ + exti_init(EXTI_5, EXTI_INTERRUPT, EXTI_TRIG_FALLING); + exti_interrupt_flag_clear(EXTI_5); } From 84772266fd8c910baf4bc46f37157a2651af6e36 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:04:26 +1100 Subject: [PATCH 56/72] Adding in Watchdog --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 4a9e0c92..192db1d0 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -19,7 +19,7 @@ uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle // 2 second filter (ADC is PID_TIM_HZ Hz) history rawTempFilter = {{0}, 0, 0}; void resetWatchdog() { - // TODO + fwdgt_counter_reload(); } uint16_t getTipInstantTemperature() { From 7e4187e62df1def03a5a5c108a75b28d617fa8b3 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:05:48 +1100 Subject: [PATCH 57/72] Update BSP.cpp --- workspace/TS100/Core/BSP/Pine64/BSP.cpp | 152 ++++++++++++------------ 1 file changed, 77 insertions(+), 75 deletions(-) diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 192db1d0..936f4d82 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -17,111 +17,113 @@ const uint8_t tempMeasureTicks = 25; uint16_t totalPWM; // htim2.Init.Period, the full PWM cycle // 2 second filter (ADC is PID_TIM_HZ Hz) -history rawTempFilter = {{0}, 0, 0}; +history rawTempFilter = { { 0 }, 0, 0 }; void resetWatchdog() { - fwdgt_counter_reload(); + fwdgt_counter_reload(); } uint16_t getTipInstantTemperature() { - volatile uint16_t sum = 0; // 12 bit readings * 8*2 -> 16 bits + volatile uint16_t sum = 0; // 12 bit readings * 8*2 -> 16 bits - for (int i = 0; i < 4; i++) { - sum += adc_inserted_data_read(ADC0, i); - sum += adc_inserted_data_read(ADC1, i); - } - return sum; // 8x over sample + for (int i = 0; i < 4; i++) { + sum += adc_inserted_data_read(ADC0, i); + sum += adc_inserted_data_read(ADC1, i); + } + return sum; // 8x over sample } uint16_t getTipRawTemp(uint8_t refresh) { - if (refresh) { - uint16_t lastSample = getTipInstantTemperature(); - rawTempFilter.update(lastSample); - return lastSample; - } else { - return rawTempFilter.average(); - } + if (refresh) { + uint16_t lastSample = getTipInstantTemperature(); + rawTempFilter.update(lastSample); + return lastSample; + } else { + return rawTempFilter.average(); + } } uint16_t getHandleTemperature() { #ifdef TEMP_TMP36 - // We return the current handle temperature in X10 C - // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for - // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = - // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 - // mV per count So we need to subtract an offset of 0.5V to center on 0C - // (4964.8 counts) - // - int32_t result = getADC(0); - result -= 4965; // remove 0.5V offset - // 10mV per C - // 99.29 counts per Deg C above 0C - result *= 100; - result /= 993; - return result; + // We return the current handle temperature in X10 C + // TMP36 in handle, 0.5V offset and then 10mV per deg C (0.75V @ 25C for + // example) STM32 = 4096 count @ 3.3V input -> But We oversample by 32/(2^2) = + // 8 times oversampling Therefore 32768 is the 3.3V input, so 0.1007080078125 + // mV per count So we need to subtract an offset of 0.5V to center on 0C + // (4964.8 counts) + // + int32_t result = getADC(0); + result -= 4965; // remove 0.5V offset + // 10mV per C + // 99.29 counts per Deg C above 0C + result *= 100; + result /= 993; + return result; #else #error #endif } uint16_t getInputVoltageX10(uint16_t divisor, uint8_t sample) { - static uint8_t preFillneeded = 10; - static uint32_t samples[BATTFILTERDEPTH]; - static uint8_t index = 0; - if (preFillneeded) { - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - samples[i] = getADC(1); - preFillneeded--; - } - if (sample) { - samples[index] = getADC(1); - index = (index + 1) % BATTFILTERDEPTH; - } - uint32_t sum = 0; + static uint8_t preFillneeded = 10; + static uint32_t samples[BATTFILTERDEPTH]; + static uint8_t index = 0; + if (preFillneeded) { + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + samples[i] = getADC(1); + preFillneeded--; + } + if (sample) { + samples[index] = getADC(1); + index = (index + 1) % BATTFILTERDEPTH; + } + uint32_t sum = 0; - for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) - sum += samples[i]; + for (uint8_t i = 0; i < BATTFILTERDEPTH; i++) + sum += samples[i]; - sum /= BATTFILTERDEPTH; - if (divisor == 0) { - divisor = 1; - } - return sum * 4 / divisor; + sum /= BATTFILTERDEPTH; + if (divisor == 0) { + divisor = 1; + } + return sum * 4 / divisor; } void unstick_I2C() { - /* configure SDA/SCL for GPIO */ - GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin; - gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, - SDA_Pin | SCL_Pin); - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - GPIO_BOP(GPIOB) |= SCL_Pin; - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - GPIO_BOP(GPIOB) |= SDA_Pin; - /* connect PB6 to I2C0_SCL */ - /* connect PB7 to I2C0_SDA */ - gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, - SDA_Pin | SCL_Pin); + /* configure SDA/SCL for GPIO */ + GPIO_BC(GPIOB) |= SDA_Pin | SCL_Pin; + gpio_init(SDA_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + GPIO_BOP(GPIOB) |= SCL_Pin; + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + asm("nop"); + GPIO_BOP(GPIOB) |= SDA_Pin; + /* connect PB6 to I2C0_SCL */ + /* connect PB7 to I2C0_SDA */ + gpio_init(SDA_GPIO_Port, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, + SDA_Pin | SCL_Pin); } uint8_t getButtonA() { - return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_A_GPIO_Port, KEY_A_Pin) == SET) ? 1 : 0; } uint8_t getButtonB() { - return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; + return (gpio_input_bit_get(KEY_B_GPIO_Port, KEY_B_Pin) == SET) ? 1 : 0; } void reboot() { - // TODO - for (;;) { - } + // TODO + for (;;) { + } } -void delay_ms(uint16_t count) { delay_1ms(count); } +void delay_ms(uint16_t count) { + delay_1ms(count); +} From 3146343bbb47b7c75a5e6185ee9c92f648b80a27 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:28:12 +1100 Subject: [PATCH 58/72] Split DC input and QC from being an OR :) --- .../TS100/Core/BSP/Miniware/Model_Config.h | 1 + .../TS100/Core/BSP/Pine64/Model_Config.h | 2 + workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp | 9 +- workspace/TS100/Core/Inc/Settings.h | 48 +- workspace/TS100/Core/Src/Settings.cpp | 14 +- workspace/TS100/Core/Src/gui.cpp | 524 +++++++----------- workspace/TS100/configuration.h | 2 +- 7 files changed, 241 insertions(+), 359 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Model_Config.h b/workspace/TS100/Core/BSP/Miniware/Model_Config.h index d2732c6a..f7beb79e 100644 --- a/workspace/TS100/Core/BSP/Miniware/Model_Config.h +++ b/workspace/TS100/Core/BSP/Miniware/Model_Config.h @@ -18,6 +18,7 @@ #endif #ifdef MODEL_TS100 +#define POW_DC #define ACCEL_MMA #define ACCEL_LIS #define TEMP_TMP36 diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index 2c6a0c84..c4675a40 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -18,6 +18,8 @@ #ifdef MODEL_Pinecil #define POW_PD #define POW_QC +#define POW_DC +#define POW_QC_20V #define TEMP_TMP36 #define ACCEL_BMA #define HALL_SENSOR diff --git a/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp index 6194add0..1866995b 100644 --- a/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Pine64/QC_GPIO.cpp @@ -53,6 +53,13 @@ uint8_t QC_DM_PulledDown() { #endif void QC_resync() { #ifdef POW_QC - seekQC((systemSettings.cutoutSetting) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much + uint8_t targetvoltage = 90; + if (systemSettings.QCIdealVoltage == 1) { + targetvoltage = 120; + } else if (systemSettings.QCIdealVoltage == 2) { + targetvoltage = 200; + } + + seekQC(targetvoltage, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif } diff --git a/workspace/TS100/Core/Inc/Settings.h b/workspace/TS100/Core/Inc/Settings.h index eea506f2..e9ca84e9 100644 --- a/workspace/TS100/Core/Inc/Settings.h +++ b/workspace/TS100/Core/Inc/Settings.h @@ -19,35 +19,35 @@ * This struct must be a multiple of 2 bytes as it is saved / restored from * flash in uint16_t chunks */ -typedef struct -{ +typedef struct { uint8_t version; // Used to track if a reset is needed on firmware upgrade - uint16_t SolderingTemp; // current set point for the iron - uint16_t SleepTemp; // temp to drop to in sleep - uint8_t SleepTime; // minutes timeout to sleep - uint8_t cutoutSetting; // The voltage we cut out at for under voltage OR Power level for TS80 - uint8_t OrientationMode : 2; // If true we want to invert the display for lefties - uint8_t sensitivity : 4; // Sensitivity of accelerometer (5 bits) - uint8_t autoStartMode : 2; // Should the unit automatically jump straight - // into soldering mode when power is applied - uint8_t ShutdownTime; // Time until unit shuts down if left alone + uint16_t SolderingTemp; // current set point for the iron + uint16_t SleepTemp; // temp to drop to in sleep + uint8_t SleepTime; // minutes timeout to sleep + uint8_t minDCVoltageCells; // The voltage we cut out at for under voltage when powered by DC jack + uint8_t QCIdealVoltage; // Desired QC3.0 voltage (9,12,20V) + uint8_t OrientationMode :2; // Selects between Auto,Right and left handed layouts + uint8_t sensitivity :4; // Sensitivity of accelerometer (5 bits) + uint8_t autoStartMode :2; // Should the unit automatically jump straight + // into soldering mode when power is applied + uint8_t ShutdownTime; // Time until unit shuts down if left alone - uint8_t coolingTempBlink : 1; // Should the temperature blink on the cool - // down screen until its <50C - uint8_t detailedIDLE : 1; // Detailed idle screen - uint8_t detailedSoldering : 1; // Detailed soldering screens + uint8_t coolingTempBlink :1; // Should the temperature blink on the cool + // down screen until its <50C + uint8_t detailedIDLE :1; // Detailed idle screen + uint8_t detailedSoldering :1; // Detailed soldering screens #ifdef ENABLED_FAHRENHEIT_SUPPORT - uint8_t temperatureInF : 1; // Should the temp be in F or C (true is F) + uint8_t temperatureInF : 1; // Should the temp be in F or C (true is F) #endif - uint8_t descriptionScrollSpeed : 1; // Description scroll speed - uint8_t lockingMode : 2; // Store the locking mode - uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) + uint8_t descriptionScrollSpeed :1; // Description scroll speed + uint8_t lockingMode :2; // Store the locking mode + uint8_t KeepAwakePulse; // Keep Awake pulse power in 0.1 watts (10 = 1Watt) - uint16_t voltageDiv; // Voltage divisor factor - uint16_t BoostTemp; // Boost mode set point for the iron - uint16_t CalibrationOffset; // This stores the temperature offset for this tip - // in the iron. + uint16_t voltageDiv; // Voltage divisor factor + uint16_t BoostTemp; // Boost mode set point for the iron + uint16_t CalibrationOffset; // This stores the temperature offset for this tip + // in the iron. uint8_t powerLimit; // Maximum power iron allowed to output @@ -68,7 +68,7 @@ extern volatile systemSettingsType systemSettings; void saveSettings(); bool restoreSettings(); -uint8_t lookupVoltageLevel(uint8_t level); +uint8_t lookupVoltageLevel(); uint16_t lookupHallEffectThreshold(); void resetSettings(); diff --git a/workspace/TS100/Core/Src/Settings.cpp b/workspace/TS100/Core/Src/Settings.cpp index 79996669..581a3f40 100644 --- a/workspace/TS100/Core/Src/Settings.cpp +++ b/workspace/TS100/Core/Src/Settings.cpp @@ -42,11 +42,11 @@ bool restoreSettings() { * 3=5S * 4=6S */ -uint8_t lookupVoltageLevel(uint8_t level) { - if (level == 0) +uint8_t lookupVoltageLevel() { + if (systemSettings.minDCVoltageCells == 0) return 90; // 9V since iron does not function effectively below this else - return (level * 33) + (33 * 2); + return (systemSettings.minDCVoltageCells * 33) + (33 * 2); } void resetSettings() { memset((void*) &systemSettings, 0, sizeof(systemSettingsType)); @@ -54,9 +54,9 @@ void resetSettings() { systemSettings.SleepTime = SLEEP_TIME; // How many seconds/minutes we wait until going // to sleep - default 1 min systemSettings.SolderingTemp = SOLDERING_TEMP; // Default soldering temp is 320.0 C - systemSettings.cutoutSetting = CUT_OUT_SETTING; // default to no cut-off voltage (or 18W for TS80) - systemSettings.version = - SETTINGSVERSION; // Store the version number to allow for easier upgrades + systemSettings.minDCVoltageCells = CUT_OUT_SETTING; // default to no cut-off voltage + systemSettings.QCIdealVoltage = 0; // Default to 9V for QC3.0 Voltage + systemSettings.version = SETTINGSVERSION; // Store the version number to allow for easier upgrades systemSettings.detailedSoldering = DETAILED_SOLDERING; // Detailed soldering screen systemSettings.detailedIDLE = DETAILED_IDLE; // Detailed idle screen (off for first time users) systemSettings.OrientationMode = ORIENTATION_MODE; // Default to automatic @@ -78,7 +78,7 @@ void resetSettings() { systemSettings.TempChangeLongStep = TEMP_CHANGE_LONG_STEP; // systemSettings.KeepAwakePulse = POWER_PULSE_DEFAULT; systemSettings.TipGain = TIP_GAIN; - systemSettings.hallEffectSensitivity=1; + systemSettings.hallEffectSensitivity = 1; saveSettings(); // Save defaults } diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index a0abf503..f8e2656a 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -17,12 +17,13 @@ void gui_Menu(const menuitem *menu); -#ifdef MODEL_TS100 +#ifdef POW_DC static bool settings_setInputVRange(void); static void settings_displayInputVRange(void); -#else -static bool settings_setInputPRange(void); -static void settings_displayInputPRange(void); +#endif +#ifdef POW_QC +static bool settings_setQCInputV(void); +static void settings_displayQCInputV(void); #endif static bool settings_setSleepTemp(void); static void settings_displaySleepTemp(void); @@ -121,7 +122,7 @@ static bool settings_enterAdvancedMenu(void); * Reset Settings * */ -const menuitem rootSettingsMenu[]{ +const menuitem rootSettingsMenu[] { /* * Power Source * Soldering Menu @@ -130,33 +131,33 @@ const menuitem rootSettingsMenu[]{ * Advanced Menu * Exit */ -#ifdef MODEL_TS100 - {(const char *)SettingsDescriptions[0], settings_setInputVRange, - settings_displayInputVRange}, /*Voltage input*/ -#else - {(const char *)SettingsDescriptions[19], settings_setInputPRange, settings_displayInputPRange}, /*Voltage input*/ +#ifdef POW_DC + { (const char *) SettingsDescriptions[0], settings_setInputVRange, settings_displayInputVRange }, /*Voltage input*/ #endif - {(const char *)NULL, settings_enterSolderingMenu, settings_displaySolderingMenu}, /*Soldering*/ - {(const char *)NULL, settings_enterPowerMenu, settings_displayPowerMenu}, /*Sleep Options Menu*/ - {(const char *)NULL, settings_enterUIMenu, settings_displayUIMenu}, /*UI Menu*/ - {(const char *)NULL, settings_enterAdvancedMenu, settings_displayAdvancedMenu}, /*Advanced Menu*/ - {NULL, NULL, NULL} // end of menu marker. DO NOT REMOVE +#ifdef POW_QC + { (const char *) SettingsDescriptions[19], settings_setQCInputV, settings_displayQCInputV }, /*Voltage input*/ +#endif + { (const char *) NULL, settings_enterSolderingMenu, settings_displaySolderingMenu }, /*Soldering*/ + { (const char *) NULL, settings_enterPowerMenu, settings_displayPowerMenu }, /*Sleep Options Menu*/ + { (const char *) NULL, settings_enterUIMenu, settings_displayUIMenu }, /*UI Menu*/ + { (const char *) NULL, settings_enterAdvancedMenu, settings_displayAdvancedMenu }, /*Advanced Menu*/ + { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem solderingMenu[] = { - /* +/* * Boost Mode Enabled * Boost Mode Temp * Auto Start * Temp change short step * Temp change long step */ - {(const char *)SettingsDescriptions[8], settings_setBoostTemp, settings_displayBoostTemp}, /*Boost Temp*/ - {(const char *)SettingsDescriptions[9], settings_setAutomaticStartMode, settings_displayAutomaticStartMode}, /*Auto start*/ - {(const char *)SettingsDescriptions[22], settings_setTempChangeShortStep, settings_displayTempChangeShortStep}, /*Temp change short step*/ - {(const char *)SettingsDescriptions[23], settings_setTempChangeLongStep, settings_displayTempChangeLongStep}, /*Temp change long step*/ - {(const char *)SettingsDescriptions[26], settings_setLockingMode, settings_displayLockingMode}, /*Locking Mode*/ - {NULL, NULL, NULL} // end of menu marker. DO NOT REMOVE +{ (const char *) SettingsDescriptions[8], settings_setBoostTemp, settings_displayBoostTemp }, /*Boost Temp*/ +{ (const char *) SettingsDescriptions[9], settings_setAutomaticStartMode, settings_displayAutomaticStartMode }, /*Auto start*/ +{ (const char *) SettingsDescriptions[22], settings_setTempChangeShortStep, settings_displayTempChangeShortStep }, /*Temp change short step*/ +{ (const char *) SettingsDescriptions[23], settings_setTempChangeLongStep, settings_displayTempChangeLongStep }, /*Temp change long step*/ +{ (const char *) SettingsDescriptions[26], settings_setLockingMode, settings_displayLockingMode }, /*Locking Mode*/ +{ NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem UIMenu[] = { /* @@ -168,34 +169,34 @@ const menuitem UIMenu[] = { * Reverse Temp change buttons + - */ #ifdef ENABLED_FAHRENHEIT_SUPPORT - {(const char *)SettingsDescriptions[5], settings_setTempF, - settings_displayTempF}, /* Temperature units*/ + { (const char *)SettingsDescriptions[5], settings_setTempF, + settings_displayTempF}, /* Temperature units*/ #endif - {(const char *)SettingsDescriptions[7], settings_setDisplayRotation, settings_displayDisplayRotation}, /*Display Rotation*/ - {(const char *)SettingsDescriptions[10], settings_setCoolingBlinkEnabled, settings_displayCoolingBlinkEnabled}, /*Cooling blink warning*/ - {(const char *)SettingsDescriptions[15], settings_setScrollSpeed, settings_displayScrollSpeed}, /*Scroll Speed for descriptions*/ - {(const char *)SettingsDescriptions[21], settings_setReverseButtonTempChangeEnabled, settings_displayReverseButtonTempChangeEnabled}, /* Reverse Temp change buttons + - */ - {NULL, NULL, NULL} // end of menu marker. DO NOT REMOVE + { (const char *) SettingsDescriptions[7], settings_setDisplayRotation, settings_displayDisplayRotation }, /*Display Rotation*/ + { (const char *) SettingsDescriptions[10], settings_setCoolingBlinkEnabled, settings_displayCoolingBlinkEnabled }, /*Cooling blink warning*/ + { (const char *) SettingsDescriptions[15], settings_setScrollSpeed, settings_displayScrollSpeed }, /*Scroll Speed for descriptions*/ + { (const char *) SettingsDescriptions[21], settings_setReverseButtonTempChangeEnabled, settings_displayReverseButtonTempChangeEnabled }, /* Reverse Temp change buttons + - */ + { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem PowerMenu[] = { - /* +/* * Sleep Temp * Sleep Time * Shutdown Time * Motion Sensitivity */ - {(const char *)SettingsDescriptions[1], settings_setSleepTemp, settings_displaySleepTemp}, /*Sleep Temp*/ - {(const char *)SettingsDescriptions[2], settings_setSleepTime, settings_displaySleepTime}, /*Sleep Time*/ - {(const char *)SettingsDescriptions[3], settings_setShutdownTime, settings_displayShutdownTime}, /*Shutdown Time*/ - {(const char *)SettingsDescriptions[4], settings_setSensitivity, settings_displaySensitivity}, /* Motion Sensitivity*/ +{ (const char *) SettingsDescriptions[1], settings_setSleepTemp, settings_displaySleepTemp }, /*Sleep Temp*/ +{ (const char *) SettingsDescriptions[2], settings_setSleepTime, settings_displaySleepTime }, /*Sleep Time*/ +{ (const char *) SettingsDescriptions[3], settings_setShutdownTime, settings_displayShutdownTime }, /*Shutdown Time*/ +{ (const char *) SettingsDescriptions[4], settings_setSensitivity, settings_displaySensitivity }, /* Motion Sensitivity*/ #ifdef HALL_SENSOR - {(const char *)SettingsDescriptions[26], settings_setHallEffect, settings_displayHallEffect}, /* HallEffect Sensitivity*/ + { (const char *) SettingsDescriptions[26], settings_setHallEffect, settings_displayHallEffect }, /* HallEffect Sensitivity*/ #endif - {NULL, NULL, NULL} // end of menu marker. DO NOT REMOVE + { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem advancedMenu[] = { - /* +/* * Power limit * Detailed IDLE * Detailed Soldering @@ -204,19 +205,18 @@ const menuitem advancedMenu[] = { * Reset Settings * Power Pulse */ - {(const char *)SettingsDescriptions[20], settings_setPowerLimit, settings_displayPowerLimit}, /*Power limit*/ - {(const char *)SettingsDescriptions[6], settings_setAdvancedIDLEScreens, settings_displayAdvancedIDLEScreens}, /* Advanced idle screen*/ - {(const char *)SettingsDescriptions[14], settings_setAdvancedSolderingScreens, settings_displayAdvancedSolderingScreens}, /* Advanced soldering screen*/ - {(const char *)SettingsDescriptions[12], settings_setResetSettings, settings_displayResetSettings}, /*Resets settings*/ - {(const char *)SettingsDescriptions[11], settings_setCalibrate, settings_displayCalibrate}, /*Calibrate tip*/ - {(const char *)SettingsDescriptions[13], settings_setCalibrateVIN, settings_displayCalibrateVIN}, /*Voltage input cal*/ - {(const char *)SettingsDescriptions[24], settings_setPowerPulse, settings_displayPowerPulse}, /*Power Pulse adjustment */ - {(const char *)SettingsDescriptions[25], settings_setTipGain, settings_displayTipGain}, /*TipGain*/ - {NULL, NULL, NULL} // end of menu marker. DO NOT REMOVE +{ (const char *) SettingsDescriptions[20], settings_setPowerLimit, settings_displayPowerLimit }, /*Power limit*/ +{ (const char *) SettingsDescriptions[6], settings_setAdvancedIDLEScreens, settings_displayAdvancedIDLEScreens }, /* Advanced idle screen*/ +{ (const char *) SettingsDescriptions[14], settings_setAdvancedSolderingScreens, settings_displayAdvancedSolderingScreens }, /* Advanced soldering screen*/ +{ (const char *) SettingsDescriptions[12], settings_setResetSettings, settings_displayResetSettings }, /*Resets settings*/ +{ (const char *) SettingsDescriptions[11], settings_setCalibrate, settings_displayCalibrate }, /*Calibrate tip*/ +{ (const char *) SettingsDescriptions[13], settings_setCalibrateVIN, settings_displayCalibrateVIN }, /*Voltage input cal*/ +{ (const char *) SettingsDescriptions[24], settings_setPowerPulse, settings_displayPowerPulse }, /*Power Pulse adjustment */ +{ (const char *) SettingsDescriptions[25], settings_setTipGain, settings_displayTipGain }, /*TipGain*/ +{ NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; -static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) -{ +static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) { OLED::setFont(1); OLED::setCharCursor(0, 0); OLED::print(SettingsShortNames[shortDescIndex][0]); @@ -231,8 +231,7 @@ static void printShortDescriptionDoubleLine(uint32_t shortDescIndex) * @param cursorCharPosition Custom cursor char position to set after printing * description. */ -static void printShortDescription(uint32_t shortDescIndex, uint16_t cursorCharPosition) -{ +static void printShortDescription(uint32_t shortDescIndex, uint16_t cursorCharPosition) { // print short description (default single line, explicit double line) printShortDescriptionDoubleLine(shortDescIndex); @@ -243,8 +242,7 @@ static void printShortDescription(uint32_t shortDescIndex, uint16_t cursorCharPo OLED::setCursor(OLED::getCursorX() - 2, 0); } -static int userConfirmation(const char *message) -{ +static int userConfirmation(const char *message) { uint16_t messageWidth = FONT_12_WIDTH * (strlen(message) + 7); uint32_t messageStart = xTaskGetTickCount(); @@ -253,13 +251,11 @@ static int userConfirmation(const char *message) int16_t lastOffset = -1; bool lcdRefresh = true; - for (;;) - { + for (;;) { int16_t messageOffset = ((xTaskGetTickCount() - messageStart) / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); messageOffset %= messageWidth; // Roll around at the end - if (lastOffset != messageOffset) - { + if (lastOffset != messageOffset) { OLED::clearScreen(); //^ Rolling offset based on time @@ -270,8 +266,7 @@ static int userConfirmation(const char *message) } ButtonState buttons = getButtonState(); - switch (buttons) - { + switch (buttons) { case BUTTON_F_SHORT: // User confirmed return 1; @@ -286,8 +281,7 @@ static int userConfirmation(const char *message) return 0; } - if (lcdRefresh) - { + if (lcdRefresh) { OLED::refresh(); osDelay(40); lcdRefresh = false; @@ -295,43 +289,39 @@ static int userConfirmation(const char *message) } return 0; } -#ifdef MODEL_TS100 -static bool settings_setInputVRange(void) -{ - systemSettings.cutoutSetting = (systemSettings.cutoutSetting + 1) % 5; - if (systemSettings.cutoutSetting) - systemSettings.powerLimit = 0; // disable power limit if switching to a lipo power source - return systemSettings.cutoutSetting == 4; +#ifdef POW_DC +static bool settings_setInputVRange(void) { + systemSettings.minDCVoltageCells = (systemSettings.minDCVoltageCells + 1) % 5; + return systemSettings.minDCVoltageCells == 4; } -static void settings_displayInputVRange(void) -{ +static void settings_displayInputVRange(void) { printShortDescription(0, 6); - if (systemSettings.cutoutSetting) - { - OLED::printNumber(2 + systemSettings.cutoutSetting, 1); + if (systemSettings.minDCVoltageCells) { + OLED::printNumber(2 + systemSettings.minDCVoltageCells, 1); OLED::print(SymbolCellCount); - } - else - { + } else { OLED::print(SymbolDC); } } +#endif +#ifdef POW_QC +static bool settings_setQCInputV(void) { +#ifdef POW_QC_20V + systemSettings.QCIdealVoltage = (systemSettings.QCIdealVoltage + 1) % 3; + return systemSettings.QCIdealVoltage == 2; #else -static bool settings_setInputPRange(void) -{ - systemSettings.cutoutSetting = (systemSettings.cutoutSetting + 1) % 2; - return false; + systemSettings.QCIdealVoltage = (systemSettings.QCIdealVoltage + 1) % 2; + return systemSettings.QCIdealVoltage == 1; +#endif } -static void settings_displayInputPRange(void) -{ +static void settings_displayQCInputV(void) { printShortDescription(0, 5); - //0 = 9V, 1=12V (Fixed Voltages, these imply 1.5A limits) - // These are only used in QC3.0 modes - switch (systemSettings.cutoutSetting) - { + //0 = 9V, 1=12V, 2=20V (Fixed Voltages) + // These are only used in QC modes + switch (systemSettings.QCIdealVoltage) { case 0: OLED::printNumber(9, 2); OLED::print(SymbolVolts); @@ -340,21 +330,24 @@ static void settings_displayInputPRange(void) OLED::printNumber(12, 2); OLED::print(SymbolVolts); break; + case 2: + OLED::printNumber(20, 2); + OLED::print(SymbolVolts); + break; default: break; } } #endif -static bool settings_setSleepTemp(void) -{ +static bool settings_setSleepTemp(void) { // If in C, 10 deg, if in F 20 deg #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { systemSettings.SleepTemp += 20; if (systemSettings.SleepTemp > 580) - systemSettings.SleepTemp = 60; + systemSettings.SleepTemp = 60; return systemSettings.SleepTemp == 580; } else @@ -367,17 +360,14 @@ static bool settings_setSleepTemp(void) } } -static void settings_displaySleepTemp(void) -{ +static void settings_displaySleepTemp(void) { printShortDescription(1, 5); OLED::printNumber(systemSettings.SleepTemp, 3); } -static bool settings_setSleepTime(void) -{ +static bool settings_setSleepTime(void) { systemSettings.SleepTime++; // Go up 1 minute at a time - if (systemSettings.SleepTime >= 16) - { + if (systemSettings.SleepTime >= 16) { systemSettings.SleepTime = 0; // can't set time over 10 mins } // Remember that ^ is the time of no movement @@ -386,30 +376,22 @@ static bool settings_setSleepTime(void) return systemSettings.SleepTime == 15; } -static void settings_displaySleepTime(void) -{ +static void settings_displaySleepTime(void) { printShortDescription(2, 5); - if (systemSettings.SleepTime == 0) - { + if (systemSettings.SleepTime == 0) { OLED::print(OffString); - } - else if (systemSettings.SleepTime < 6) - { + } else if (systemSettings.SleepTime < 6) { OLED::printNumber(systemSettings.SleepTime * 10, 2); OLED::print(SymbolSeconds); - } - else - { + } else { OLED::printNumber(systemSettings.SleepTime - 5, 2); OLED::print(SymbolMinutes); } } -static bool settings_setShutdownTime(void) -{ +static bool settings_setShutdownTime(void) { systemSettings.ShutdownTime++; - if (systemSettings.ShutdownTime > 60) - { + if (systemSettings.ShutdownTime > 60) { systemSettings.ShutdownTime = 0; // wrap to off } if (PCBVersion == 3) @@ -417,15 +399,11 @@ static bool settings_setShutdownTime(void) return systemSettings.ShutdownTime == 60; } -static void settings_displayShutdownTime(void) -{ +static void settings_displayShutdownTime(void) { printShortDescription(3, 5); - if (systemSettings.ShutdownTime == 0) - { + if (systemSettings.ShutdownTime == 0) { OLED::print(OffString); - } - else - { + } else { OLED::printNumber(systemSettings.ShutdownTime, 2); OLED::print(SymbolMinutes); } @@ -440,7 +418,7 @@ static bool settings_setTempF(void) // C to F == F= ( (C*9) +160)/5 systemSettings.BoostTemp = ((systemSettings.BoostTemp * 9) + 160) / 5; systemSettings.SolderingTemp = - ((systemSettings.SolderingTemp * 9) + 160) / 5; + ((systemSettings.SolderingTemp * 9) + 160) / 5; systemSettings.SleepTemp = ((systemSettings.SleepTemp * 9) + 160) / 5; } else @@ -469,69 +447,57 @@ static void settings_displayTempF(void) } #endif -static bool settings_setSensitivity(void) -{ +static bool settings_setSensitivity(void) { systemSettings.sensitivity++; systemSettings.sensitivity = systemSettings.sensitivity % 10; return systemSettings.sensitivity == 9; } -static void settings_displaySensitivity(void) -{ +static void settings_displaySensitivity(void) { printShortDescription(4, 7); OLED::printNumber(systemSettings.sensitivity, 1, false); } -static bool settings_setAdvancedSolderingScreens(void) -{ +static bool settings_setAdvancedSolderingScreens(void) { systemSettings.detailedSoldering = !systemSettings.detailedSoldering; return false; } -static void settings_displayAdvancedSolderingScreens(void) -{ +static void settings_displayAdvancedSolderingScreens(void) { printShortDescription(14, 7); OLED::drawCheckbox(systemSettings.detailedSoldering); } -static bool settings_setAdvancedIDLEScreens(void) -{ +static bool settings_setAdvancedIDLEScreens(void) { systemSettings.detailedIDLE = !systemSettings.detailedIDLE; return false; } -static void settings_displayAdvancedIDLEScreens(void) -{ +static void settings_displayAdvancedIDLEScreens(void) { printShortDescription(6, 7); OLED::drawCheckbox(systemSettings.detailedIDLE); } -static bool settings_setPowerLimit(void) -{ +static bool settings_setPowerLimit(void) { systemSettings.powerLimit += POWER_LIMIT_STEPS; if (systemSettings.powerLimit > MAX_POWER_LIMIT) systemSettings.powerLimit = 0; return systemSettings.powerLimit + POWER_LIMIT_STEPS > MAX_POWER_LIMIT; } -static void settings_displayPowerLimit(void) -{ +static void settings_displayPowerLimit(void) { printShortDescription(20, 5); - if (systemSettings.powerLimit == 0) - { + if (systemSettings.powerLimit == 0) { OLED::print(OffString); - } - else - { + } else { OLED::printNumber(systemSettings.powerLimit, 2); OLED::print(SymbolWatts); } } -static bool settings_setScrollSpeed(void) -{ +static bool settings_setScrollSpeed(void) { if (systemSettings.descriptionScrollSpeed == 0) systemSettings.descriptionScrollSpeed = 1; else @@ -539,18 +505,15 @@ static bool settings_setScrollSpeed(void) return false; } -static void settings_displayScrollSpeed(void) -{ +static void settings_displayScrollSpeed(void) { printShortDescription(15, 7); OLED::print((systemSettings.descriptionScrollSpeed) ? SettingFastChar : SettingSlowChar); } -static bool settings_setDisplayRotation(void) -{ +static bool settings_setDisplayRotation(void) { systemSettings.OrientationMode++; systemSettings.OrientationMode = systemSettings.OrientationMode % 3; - switch (systemSettings.OrientationMode) - { + switch (systemSettings.OrientationMode) { case 0: OLED::setRotation(false); break; @@ -566,12 +529,10 @@ static bool settings_setDisplayRotation(void) return systemSettings.OrientationMode == 2; } -static void settings_displayDisplayRotation(void) -{ +static void settings_displayDisplayRotation(void) { printShortDescription(7, 7); - switch (systemSettings.OrientationMode) - { + switch (systemSettings.OrientationMode) { case 0: OLED::print(SettingRightChar); break; @@ -587,8 +548,7 @@ static void settings_displayDisplayRotation(void) } } -static bool settings_setBoostTemp(void) -{ +static bool settings_setBoostTemp(void) { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { @@ -610,48 +570,37 @@ static bool settings_setBoostTemp(void) else #endif { - if (systemSettings.BoostTemp == 0) - { + if (systemSettings.BoostTemp == 0) { systemSettings.BoostTemp = 250; // loop back at 250 - } - else - { + } else { systemSettings.BoostTemp += 10; // Go up 10C at a time } - if (systemSettings.BoostTemp > 450) - { + if (systemSettings.BoostTemp > 450) { systemSettings.BoostTemp = 0; //Go to off state } return systemSettings.BoostTemp == 450; } } -static void settings_displayBoostTemp(void) -{ +static void settings_displayBoostTemp(void) { printShortDescription(8, 5); - if (systemSettings.BoostTemp) - { + if (systemSettings.BoostTemp) { OLED::printNumber(systemSettings.BoostTemp, 3); - } - else - { + } else { OLED::print(OffString); } } -static bool settings_setAutomaticStartMode(void) -{ +static bool settings_setAutomaticStartMode(void) { systemSettings.autoStartMode++; systemSettings.autoStartMode %= 4; return systemSettings.autoStartMode == 3; } -static void settings_displayAutomaticStartMode(void) -{ +static void settings_displayAutomaticStartMode(void) { printShortDescription(9, 7); - switch (systemSettings.autoStartMode) - { + switch (systemSettings.autoStartMode) { case 0: OLED::print(SettingStartNoneChar); break; @@ -670,27 +619,24 @@ static void settings_displayAutomaticStartMode(void) } } -static bool settings_setLockingMode(void) -{ +static bool settings_setLockingMode(void) { systemSettings.lockingMode++; systemSettings.lockingMode %= 3; return systemSettings.lockingMode == 2; } -static void settings_displayLockingMode(void) -{ +static void settings_displayLockingMode(void) { printShortDescription(26, 7); - switch (systemSettings.lockingMode) - { + switch (systemSettings.lockingMode) { case 0: - OLED::print(SettingLockDisableChar); + OLED::print (SettingLockDisableChar); break; case 1: - OLED::print(SettingLockBoostChar); + OLED::print (SettingLockBoostChar); break; case 2: - OLED::print(SettingLockFullChar); + OLED::print (SettingLockFullChar); break; default: OLED::print(SettingLockDisableChar); @@ -698,23 +644,19 @@ static void settings_displayLockingMode(void) } } -static bool settings_setCoolingBlinkEnabled(void) -{ +static bool settings_setCoolingBlinkEnabled(void) { systemSettings.coolingTempBlink = !systemSettings.coolingTempBlink; return false; } -static void settings_displayCoolingBlinkEnabled(void) -{ +static void settings_displayCoolingBlinkEnabled(void) { printShortDescription(10, 7); OLED::drawCheckbox(systemSettings.coolingTempBlink); } -static bool settings_setResetSettings(void) -{ - if (userConfirmation(SettingsResetWarning)) - { +static bool settings_setResetSettings(void) { + if (userConfirmation(SettingsResetWarning)) { resetSettings(); OLED::setFont(0); @@ -727,23 +669,19 @@ static bool settings_setResetSettings(void) return false; } -static void settings_displayResetSettings(void) -{ +static void settings_displayResetSettings(void) { printShortDescription(12, 7); } -static void setTipOffset() -{ +static void setTipOffset() { systemSettings.CalibrationOffset = 0; // If the thermo-couple at the end of the tip, and the handle are at // equilibrium, then the output should be zero, as there is no temperature // differential. - while (systemSettings.CalibrationOffset == 0) - { + while (systemSettings.CalibrationOffset == 0) { uint32_t offset = 0; - for (uint8_t i = 0; i < 16; i++) - { + for (uint8_t i = 0; i < 16; i++) { offset += getTipRawTemp(1); // cycle through the filter a fair bit to ensure we're stable. OLED::clearScreen(); @@ -766,11 +704,9 @@ static void setTipOffset() //Provide the user the option to tune their own tip if custom is selected //If not only do single point tuning as per usual -static bool settings_setCalibrate(void) -{ +static bool settings_setCalibrate(void) { - if (userConfirmation(SettingsCalibrationWarning)) - { + if (userConfirmation(SettingsCalibrationWarning)) { // User confirmed // So we now perform the actual calculation setTipOffset(); @@ -778,20 +714,17 @@ static bool settings_setCalibrate(void) return false; } -static void settings_displayCalibrate(void) -{ +static void settings_displayCalibrate(void) { printShortDescription(11, 5); } -static bool settings_setCalibrateVIN(void) -{ +static bool settings_setCalibrateVIN(void) { // Jump to the voltage calibration subscreen OLED::setFont(0); OLED::clearScreen(); OLED::setCursor(0, 0); - for (;;) - { + for (;;) { OLED::setCursor(0, 0); OLED::printNumber(getInputVoltageX10(systemSettings.voltageDiv, 0) / 10, 2); OLED::print(SymbolDot); @@ -799,8 +732,7 @@ static bool settings_setCalibrateVIN(void) OLED::print(SymbolVolts); ButtonState buttons = getButtonState(); - switch (buttons) - { + switch (buttons) { case BUTTON_F_SHORT: systemSettings.voltageDiv++; break; @@ -837,12 +769,9 @@ static bool settings_setCalibrateVIN(void) systemSettings.voltageDiv = 900; } #else - if (systemSettings.voltageDiv < 360) - { + if (systemSettings.voltageDiv < 360) { systemSettings.voltageDiv = 360; - } - else if (systemSettings.voltageDiv > 520) - { + } else if (systemSettings.voltageDiv > 520) { systemSettings.voltageDiv = 520; } #endif @@ -850,21 +779,18 @@ static bool settings_setCalibrateVIN(void) return false; } -static bool settings_setTipGain(void) -{ +static bool settings_setTipGain(void) { OLED::setFont(0); OLED::clearScreen(); - for (;;) - { + for (;;) { OLED::setCursor(0, 0); OLED::printNumber(systemSettings.TipGain / 10, 2); OLED::print(SymbolDot); OLED::printNumber(systemSettings.TipGain % 10, 1); ButtonState buttons = getButtonState(); - switch (buttons) - { + switch (buttons) { case BUTTON_F_SHORT: systemSettings.TipGain -= 1; break; @@ -887,94 +813,75 @@ static bool settings_setTipGain(void) osDelay(40); // Cap to sensible values - if (systemSettings.TipGain < 150) - { + if (systemSettings.TipGain < 150) { systemSettings.TipGain = 150; - } - else if (systemSettings.TipGain > 300) - { + } else if (systemSettings.TipGain > 300) { systemSettings.TipGain = 300; } } return false; } -static void settings_displayTipGain(void) -{ +static void settings_displayTipGain(void) { printShortDescription(25, 5); } -static bool settings_setReverseButtonTempChangeEnabled(void) -{ +static bool settings_setReverseButtonTempChangeEnabled(void) { systemSettings.ReverseButtonTempChangeEnabled = !systemSettings.ReverseButtonTempChangeEnabled; return false; } -static void settings_displayReverseButtonTempChangeEnabled(void) -{ +static void settings_displayReverseButtonTempChangeEnabled(void) { printShortDescription(21, 7); OLED::drawCheckbox(systemSettings.ReverseButtonTempChangeEnabled); } -static bool settings_setTempChangeShortStep(void) -{ +static bool settings_setTempChangeShortStep(void) { systemSettings.TempChangeShortStep += TEMP_CHANGE_SHORT_STEP; - if (systemSettings.TempChangeShortStep > TEMP_CHANGE_SHORT_STEP_MAX) - { + if (systemSettings.TempChangeShortStep > TEMP_CHANGE_SHORT_STEP_MAX) { systemSettings.TempChangeShortStep = TEMP_CHANGE_SHORT_STEP; // loop back at TEMP_CHANGE_SHORT_STEP_MAX } return systemSettings.TempChangeShortStep == TEMP_CHANGE_SHORT_STEP_MAX; } -static void settings_displayTempChangeShortStep(void) -{ +static void settings_displayTempChangeShortStep(void) { printShortDescription(22, 6); OLED::printNumber(systemSettings.TempChangeShortStep, 2); } -static bool settings_setTempChangeLongStep(void) -{ +static bool settings_setTempChangeLongStep(void) { systemSettings.TempChangeLongStep += TEMP_CHANGE_LONG_STEP; - if (systemSettings.TempChangeLongStep > TEMP_CHANGE_LONG_STEP_MAX) - { + if (systemSettings.TempChangeLongStep > TEMP_CHANGE_LONG_STEP_MAX) { systemSettings.TempChangeLongStep = TEMP_CHANGE_LONG_STEP; // loop back at TEMP_CHANGE_LONG_STEP_MAX } return systemSettings.TempChangeLongStep == TEMP_CHANGE_LONG_STEP_MAX; } -static void settings_displayTempChangeLongStep(void) -{ +static void settings_displayTempChangeLongStep(void) { printShortDescription(23, 6); OLED::printNumber(systemSettings.TempChangeLongStep, 2); } -static bool settings_setPowerPulse(void) -{ +static bool settings_setPowerPulse(void) { systemSettings.KeepAwakePulse += POWER_PULSE_INCREMENT; systemSettings.KeepAwakePulse %= POWER_PULSE_MAX; return systemSettings.KeepAwakePulse == POWER_PULSE_MAX - 1; } -static void settings_displayPowerPulse(void) -{ +static void settings_displayPowerPulse(void) { printShortDescription(24, 5); - if (systemSettings.KeepAwakePulse) - { + if (systemSettings.KeepAwakePulse) { OLED::printNumber(systemSettings.KeepAwakePulse / 10, 1); OLED::print(SymbolDot); OLED::printNumber(systemSettings.KeepAwakePulse % 10, 1); - } - else - { + } else { OLED::print(OffString); } } #ifdef HALL_SENSOR -static void settings_displayHallEffect(void) -{ +static void settings_displayHallEffect(void) { printShortDescription(26, 7); - switch (systemSettings.hallEffectSensitivity) - { + switch (systemSettings.hallEffectSensitivity) { case 1: OLED::print(SettingSensitivityLow); break; @@ -990,8 +897,7 @@ static void settings_displayHallEffect(void) break; } } -static bool settings_setHallEffect(void) -{ +static bool settings_setHallEffect(void) { //To keep life simpler for now, we have a few preset sensitivity levels // Off, Low, Medium, High systemSettings.hallEffectSensitivity++; @@ -999,8 +905,7 @@ static bool settings_setHallEffect(void) return systemSettings.hallEffectSensitivity == 3; } #endif -static void displayMenu(size_t index) -{ +static void displayMenu(size_t index) { // Call into the menu OLED::setFont(1); OLED::setCursor(0, 0); @@ -1012,49 +917,39 @@ static void displayMenu(size_t index) OLED::drawArea(96 - 16 - 2, 0, 16, 16, (&SettingsMenuIcons[(16 * 2) * index])); } -static void settings_displayCalibrateVIN(void) -{ +static void settings_displayCalibrateVIN(void) { printShortDescription(13, 5); } -static void settings_displaySolderingMenu(void) -{ +static void settings_displaySolderingMenu(void) { displayMenu(0); } -static bool settings_enterSolderingMenu(void) -{ +static bool settings_enterSolderingMenu(void) { gui_Menu(solderingMenu); return false; } -static void settings_displayPowerMenu(void) -{ +static void settings_displayPowerMenu(void) { displayMenu(1); } -static bool settings_enterPowerMenu(void) -{ +static bool settings_enterPowerMenu(void) { gui_Menu(PowerMenu); return false; } -static void settings_displayUIMenu(void) -{ +static void settings_displayUIMenu(void) { displayMenu(2); } -static bool settings_enterUIMenu(void) -{ +static bool settings_enterUIMenu(void) { gui_Menu(UIMenu); return false; } -static void settings_displayAdvancedMenu(void) -{ +static void settings_displayAdvancedMenu(void) { displayMenu(3); } -static bool settings_enterAdvancedMenu(void) -{ +static bool settings_enterAdvancedMenu(void) { gui_Menu(advancedMenu); return false; } -void gui_Menu(const menuitem *menu) -{ +void gui_Menu(const menuitem *menu) { // Draw the settings menu and provide iteration support etc uint8_t currentScreen = 0; uint32_t autoRepeatTimer = 0; @@ -1070,14 +965,12 @@ void gui_Menu(const menuitem *menu) bool scrollBlink = false; bool lastValue = false; - for (uint8_t i = 0; menu[i].draw != NULL; i++) - { + for (uint8_t i = 0; menu[i].draw != NULL; i++) { scrollContentSize += 1; } // Animated menu opening. - if (menu[currentScreen].draw != NULL) - { + if (menu[currentScreen].draw != NULL) { // This menu is drawn in a secondary framebuffer. // Then we play a transition from the current primary // framebuffer to the new buffer. @@ -1091,14 +984,12 @@ void gui_Menu(const menuitem *menu) OLED::transitionSecondaryFramebuffer(true); } - while ((menu[currentScreen].draw != NULL) && earlyExit == false) - { + while ((menu[currentScreen].draw != NULL) && earlyExit == false) { OLED::setFont(0); OLED::setCursor(0, 0); // If the user has hesitated for >=3 seconds, show the long text // Otherwise "draw" the option - if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) - { + if ((xTaskGetTickCount() - lastButtonTime < 3000) || menu[currentScreen].description == NULL) { OLED::clearScreen(); menu[currentScreen].draw(); uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize; @@ -1109,19 +1000,16 @@ void gui_Menu(const menuitem *menu) OLED::drawScrollIndicator(position, indicatorHeight); lastOffset = -1; lcdRefresh = true; - } - else - { + } else { // Draw description if (descriptionStart == 0) descriptionStart = xTaskGetTickCount(); // lower the value - higher the speed int16_t descriptionWidth = - FONT_12_WIDTH * (strlen(menu[currentScreen].description) + 7); + FONT_12_WIDTH * (strlen(menu[currentScreen].description) + 7); int16_t descriptionOffset = ((xTaskGetTickCount() - descriptionStart) / (systemSettings.descriptionScrollSpeed == 1 ? 10 : 20)); descriptionOffset %= descriptionWidth; // Roll around at the end - if (lastOffset != descriptionOffset) - { + if (lastOffset != descriptionOffset) { OLED::clearScreen(); OLED::setCursor((OLED_WIDTH - descriptionOffset), 0); OLED::print(menu[currentScreen].description); @@ -1132,29 +1020,24 @@ void gui_Menu(const menuitem *menu) ButtonState buttons = getButtonState(); - if (buttons != lastButtonState) - { + if (buttons != lastButtonState) { autoRepeatAcceleration = 0; lastButtonState = buttons; } - switch (buttons) - { + switch (buttons) { case BUTTON_BOTH: earlyExit = true; // will make us exit next loop descriptionStart = 0; break; case BUTTON_F_SHORT: // increment - if (descriptionStart == 0) - { - if (menu[currentScreen].incrementHandler != NULL) - { + if (descriptionStart == 0) { + if (menu[currentScreen].incrementHandler != NULL) { enterGUIMenu = false; lastValue = menu[currentScreen].incrementHandler(); - if (enterGUIMenu) - { + if (enterGUIMenu) { OLED::useSecondaryFramebuffer(true); OLED::setFont(0); OLED::setCursor(0, 0); @@ -1164,28 +1047,22 @@ void gui_Menu(const menuitem *menu) OLED::transitionSecondaryFramebuffer(false); } enterGUIMenu = true; - } - else - { + } else { earlyExit = true; } - } - else + } else descriptionStart = 0; break; case BUTTON_B_SHORT: - if (descriptionStart == 0) - { + if (descriptionStart == 0) { currentScreen++; lastValue = false; - } - else + } else descriptionStart = 0; break; case BUTTON_F_LONG: - if ((int)(xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration) > - PRESS_ACCEL_INTERVAL_MAX) - { + if ((int) (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration) > + PRESS_ACCEL_INTERVAL_MAX) { if ((lastValue = menu[currentScreen].incrementHandler())) autoRepeatTimer = 1000; else @@ -1200,8 +1077,7 @@ void gui_Menu(const menuitem *menu) break; case BUTTON_B_LONG: if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > - PRESS_ACCEL_INTERVAL_MAX) - { + PRESS_ACCEL_INTERVAL_MAX) { currentScreen++; autoRepeatTimer = xTaskGetTickCount(); descriptionStart = 0; @@ -1215,20 +1091,17 @@ void gui_Menu(const menuitem *menu) } if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < - PRESS_ACCEL_INTERVAL_MIN) - { + PRESS_ACCEL_INTERVAL_MIN) { autoRepeatAcceleration = - PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; + PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; } - if (lcdRefresh) - { + if (lcdRefresh) { OLED::refresh(); // update the LCD osDelay(40); lcdRefresh = false; } - if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) - { + if ((xTaskGetTickCount() - lastButtonTime) > (1000 * 30)) { // If user has not pressed any buttons in 30 seconds, exit back a menu layer // This will trickle the user back to the main screen eventually earlyExit = true; @@ -1237,8 +1110,7 @@ void gui_Menu(const menuitem *menu) } } -void enterSettingsMenu() -{ +void enterSettingsMenu() { gui_Menu(rootSettingsMenu); // Call the root menu saveSettings(); } diff --git a/workspace/TS100/configuration.h b/workspace/TS100/configuration.h index a60d3c77..eac4a58c 100644 --- a/workspace/TS100/configuration.h +++ b/workspace/TS100/configuration.h @@ -87,7 +87,7 @@ #define DETAILED_SOLDERING 0 // 0: Disable 1: Enable - Default 0 #define DETAILED_IDLE 0 // 0: Disable 1: Enable - Default 0 -#define CUT_OUT_SETTING 0 // default to no cut-off voltage (or 18W for TS80) +#define CUT_OUT_SETTING 0 // default to no cut-off voltage #define TEMPERATURE_INF 0 // default to 0 #define DESCRIPTION_SCROLL_SPEED 0 // 0: Slow 1: Fast - default to slow From f5644a090f0d573c3f186f7197e54debc7e29f7d Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:43:49 +1100 Subject: [PATCH 59/72] Update QC to allow 20V theoretically + allow query for power source --- workspace/TS100/Core/BSP/BSP.h | 2 + workspace/TS100/Core/BSP/Pine64/BSP.cpp | 3 +- workspace/TS100/Core/BSP/Pine64/Power.cpp | 13 +++++ workspace/TS100/Core/Inc/QC3.h | 2 +- workspace/TS100/Core/Src/{QC3.c => QC3.cpp} | 56 ++++++++++++--------- 5 files changed, 51 insertions(+), 25 deletions(-) rename workspace/TS100/Core/Src/{QC3.c => QC3.cpp} (76%) diff --git a/workspace/TS100/Core/BSP/BSP.h b/workspace/TS100/Core/BSP/BSP.h index 5fde786d..6bce9d44 100644 --- a/workspace/TS100/Core/BSP/BSP.h +++ b/workspace/TS100/Core/BSP/BSP.h @@ -68,6 +68,8 @@ bool getHallSensorFitted(); // If the sensor is single polarity (or polarity insensitive) just return 0..32768 int16_t getRawHallEffect(); +//Returns true if power is from dumb "DC" input rather than "smart" QC or PD +bool getIsPoweredByDCIN(); #ifdef __cplusplus } diff --git a/workspace/TS100/Core/BSP/Pine64/BSP.cpp b/workspace/TS100/Core/BSP/Pine64/BSP.cpp index 936f4d82..95537c7b 100644 --- a/workspace/TS100/Core/BSP/Pine64/BSP.cpp +++ b/workspace/TS100/Core/BSP/Pine64/BSP.cpp @@ -119,7 +119,7 @@ uint8_t getButtonB() { } void reboot() { - // TODO + //Spin for watchdog for (;;) { } } @@ -127,3 +127,4 @@ void reboot() { void delay_ms(uint16_t count) { delay_1ms(count); } + diff --git a/workspace/TS100/Core/BSP/Pine64/Power.cpp b/workspace/TS100/Core/BSP/Pine64/Power.cpp index 23b02783..47be7645 100644 --- a/workspace/TS100/Core/BSP/Pine64/Power.cpp +++ b/workspace/TS100/Core/BSP/Pine64/Power.cpp @@ -34,3 +34,16 @@ uint8_t usb_pd_detect() { return false; } +bool getIsPoweredByDCIN() { + //We return false until we are sure we are not using PD + if (PolicyEngine::setupCompleteOrTimedOut() == false) { + return false; + } + if (PolicyEngine::pdHasNegotiated()) { + return false; // We are using PD + } + if (hasQCNegotiated()) { + return false; // We are using QC + } + return true; +} diff --git a/workspace/TS100/Core/Inc/QC3.h b/workspace/TS100/Core/Inc/QC3.h index 0ddf1b0f..9ba9d5b4 100644 --- a/workspace/TS100/Core/Inc/QC3.h +++ b/workspace/TS100/Core/Inc/QC3.h @@ -13,7 +13,7 @@ extern "C" { #endif void seekQC(int16_t Vx10, uint16_t divisor); void startQC(uint16_t divisor); // Tries to negotiate QC for highest voltage, must be run after - +bool hasQCNegotiated();// Returns true if a QC negotiation worked (we are using QC) #ifdef __cplusplus } #endif diff --git a/workspace/TS100/Core/Src/QC3.c b/workspace/TS100/Core/Src/QC3.cpp similarity index 76% rename from workspace/TS100/Core/Src/QC3.c rename to workspace/TS100/Core/Src/QC3.cpp index 473c14b2..4eb7e1e1 100644 --- a/workspace/TS100/Core/Src/QC3.c +++ b/workspace/TS100/Core/Src/QC3.cpp @@ -52,8 +52,14 @@ void seekQC(int16_t Vx10, uint16_t divisor) { return; if (xTaskGetTickCount() < 1000) return; - if (Vx10 > 130) - Vx10 = 130; // Cap max value at 13V +#ifdef POW_QC_20V + if (Vx10 > 200) + Vx10 = 200; // Cap max value at 20V +#else + if (Vx10 > 130) + Vx10 =130; // Cap max value at 13V + +#endif // Seek the QC to the Voltage given if this adapter supports continuous mode // try and step towards the wanted value @@ -80,25 +86,25 @@ void seekQC(int16_t Vx10, uint16_t divisor) { osDelay(100); } #ifdef ENABLE_QC2 - // Re-measure - /* Disabled due to nothing to test and code space of around 1k*/ - steps = vStart - getInputVoltageX10(divisor, 1); - if (steps < 0) steps = -steps; - if (steps > 4) { - // No continuous mode, so QC2 - QCMode = 2; - // Goto nearest - if (Vx10 > 110) { - // request 12V - // D- = 0.6V, D+ = 0.6V - // Clamp PB3 - QC_Seek12V(); - - } else { - // request 9V - QC_Seek9V(); - } - } + // Re-measure + /* Disabled due to nothing to test and code space of around 1k*/ + steps = vStart - getInputVoltageX10(divisor, 1); + if (steps < 0) steps = -steps; + if (steps > 4) { + // No continuous mode, so QC2 + QCMode = 2; + // Goto nearest + if (Vx10 > 190) { + // request 20V + QC_Seek20V(); + } else if (Vx10 > 110) { + // request 12V + QC_Seek12V(); + } else { + // request 9V + QC_Seek9V(); + } + } #endif } // Must be called after FreeRToS Starts @@ -106,8 +112,8 @@ void startQC(uint16_t divisor) { // Pre check that the input could be >5V already, and if so, dont both // negotiating as someone is feeding in hv uint16_t vin = getInputVoltageX10(divisor, 1); - if (vin > 100) { - QCMode = 1; // Already at 12V, user has probably over-ridden this + if (vin > 80) { + QCMode = 0; //If over 8V something else has already negotiated return; } if (QCTries > 10) { @@ -161,3 +167,7 @@ void startQC(uint16_t divisor) { } } + +bool hasQCNegotiated() { + return QCMode > 0; +} From 57b2505ad6692177aaa5d2aa1483ab82d05f9e89 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:45:10 +1100 Subject: [PATCH 60/72] Update GUI thread to use POW_DC rather than model check --- workspace/TS100/Core/Threads/GUIThread.cpp | 71 +++++++++++----------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 006b0e65..2e179dc5 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -88,15 +88,18 @@ void gui_drawTipTemp(bool symbol) { } } -#ifdef MODEL_TS100 +#ifdef POW_DC // returns true if undervoltage has occured static bool checkVoltageForExit() { + if (!getIsPoweredByDCIN()) { + return false; + } uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); - // Dont check for first 1.5 seconds while the ADC stabilizes and the DMA fills the buffer - if (xTaskGetTickCount() > 150) { - if ((v < lookupVoltageLevel(systemSettings.cutoutSetting))) { - GUIDelay(); + // Dont check for first 2 seconds while the ADC stabilizes and the DMA fills the buffer + if (xTaskGetTickCount() > (TICKS_SECOND * 2)) { + if ((v < lookupVoltageLevel())) { + currentTempTargetDegC = 0; OLED::clearScreen(); OLED::setCursor(0, 0); if (systemSettings.detailedSoldering) { @@ -106,14 +109,13 @@ static bool checkVoltageForExit() { OLED::print(InputVoltageString); printVoltage(); OLED::print(SymbolVolts); - } else { OLED::setFont(0); OLED::print(UVLOWarningString); } OLED::refresh(); - currentTempTargetDegC = 0; + GUIDelay(); waitForButtonPress(); return true; } @@ -466,7 +468,8 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (systemSettings.BoostTemp && (systemSettings.lockingMode == 1)) { boostModeOn = true; break; - }; + } + ; // fall through case BUTTON_BOTH: case BUTTON_B_LONG: @@ -485,44 +488,44 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } } else { // Button not locked switch (buttons) { - case BUTTON_NONE: + case BUTTON_NONE: // stay boostModeOn = false; break; - case BUTTON_BOTH: + case BUTTON_BOTH: // exit return; break; - case BUTTON_B_LONG: + case BUTTON_B_LONG: return; // exit on back long hold break; - case BUTTON_F_LONG: + case BUTTON_F_LONG: // if boost mode is enabled turn it on if (systemSettings.BoostTemp) - boostModeOn = true; + boostModeOn = true; break; - case BUTTON_F_SHORT: - case BUTTON_B_SHORT: { - uint16_t oldTemp = systemSettings.SolderingTemp; - gui_solderingTempAdjust(); // goto adjust temp mode - if (oldTemp != systemSettings.SolderingTemp) { - saveSettings(); // only save on change - } + case BUTTON_F_SHORT: + case BUTTON_B_SHORT: { + uint16_t oldTemp = systemSettings.SolderingTemp; + gui_solderingTempAdjust(); // goto adjust temp mode + if (oldTemp != systemSettings.SolderingTemp) { + saveSettings(); // only save on change + } + } + break; + case BUTTON_BOTH_LONG: + if (systemSettings.lockingMode != 0) { + // Lock buttons + buttonsLocked = true; + OLED::setCursor(0, 0); + OLED::clearScreen(); + OLED::setFont(0); + OLED::print(LockingKeysString); + OLED::refresh(); + waitForButtonPressOrTimeout(1000); } break; - case BUTTON_BOTH_LONG: - if (systemSettings.lockingMode != 0) { - // Lock buttons - buttonsLocked = true; - OLED::setCursor(0, 0); - OLED::clearScreen(); - OLED::setFont(0); - OLED::print(LockingKeysString); - OLED::refresh(); - waitForButtonPressOrTimeout(1000); - } - break; - default: + default: break; } } @@ -607,7 +610,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } } -#ifdef MODEL_TS100 +#ifdef POW_DC // Undervoltage test if (checkVoltageForExit()) { lastButtonTime = xTaskGetTickCount(); From 9c712ee144ac22fbc7168c4729772c81b766cd3c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:46:04 +1100 Subject: [PATCH 61/72] Update GUIThread.cpp --- workspace/TS100/Core/Threads/GUIThread.cpp | 134 ++++++++++++--------- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 2e179dc5..1079fb0a 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -7,22 +7,22 @@ extern "C" { #include "FreeRTOSConfig.h" } -#include -#include -#include -#include "main.hpp" -#include #include "../../configuration.h" #include "Buttons.hpp" +#include "I2CBB.hpp" #include "LIS2DH12.hpp" #include "Settings.h" #include "TipThermoModel.h" #include "Translation.h" #include "cmsis_os.h" +#include "main.hpp" #include "stdlib.h" #include "string.h" #include "unit.h" -#include "I2CBB.hpp" +#include +#include +#include +#include // File local variables extern uint32_t currentTempTargetDegC; extern TickType_t lastMovementTime; @@ -66,7 +66,7 @@ void gui_drawTipTemp(bool symbol) { Temp = TipThermoModel::getTipInC(); } - OLED::printNumber(Temp, 3); // Draw the tip temp out finally + OLED::printNumber(Temp, 3); // Draw the tip temp out finally if (symbol) { if (OLED::getFont() == 0) { // Big font, can draw nice symbols @@ -96,7 +96,8 @@ static bool checkVoltageForExit() { } uint16_t v = getInputVoltageX10(systemSettings.voltageDiv, 0); - // Dont check for first 2 seconds while the ADC stabilizes and the DMA fills the buffer + // Dont check for first 2 seconds while the ADC stabilizes and the DMA fills + // the buffer if (xTaskGetTickCount() > (TICKS_SECOND * 2)) { if ((v < lookupVoltageLevel())) { currentTempTargetDegC = 0; @@ -130,7 +131,7 @@ static void gui_drawBatteryIcon() { // If <9V then show single digit, if not show duals uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); if (V % 10 >= 5) - V = V / 10 + 1; // round up + V = V / 10 + 1; // round up else V = V / 10; if (V >= 10) { @@ -149,8 +150,8 @@ static void gui_drawBatteryIcon() { // User is on a lithium battery // we need to calculate which of the 10 levels they are on uint8_t cellCount = systemSettings.cutoutSetting + 2; - uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) - / cellCount; + uint32_t cellV = + getInputVoltageX10(systemSettings.voltageDiv, 0) / cellCount; // Should give us approx cell voltage X10 // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 if (cellV < 33) @@ -160,9 +161,8 @@ static void gui_drawBatteryIcon() { cellV = 9; OLED::drawBattery(cellV + 1); } else - OLED::drawSymbol(15); // Draw the DC Logo + OLED::drawSymbol(15); // Draw the DC Logo #endif - } static void gui_solderingTempAdjust() { uint32_t lastChange = xTaskGetTickCount(); @@ -185,7 +185,8 @@ static void gui_solderingTempAdjust() { return; break; case BUTTON_B_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { + if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > + PRESS_ACCEL_INTERVAL_MAX) { if (systemSettings.ReverseButtonTempChangeEnabled) { systemSettings.SolderingTemp += systemSettings.TempChangeLongStep; } else @@ -202,7 +203,8 @@ static void gui_solderingTempAdjust() { systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; break; case BUTTON_F_LONG: - if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) { + if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > + PRESS_ACCEL_INTERVAL_MAX) { if (systemSettings.ReverseButtonTempChangeEnabled) { systemSettings.SolderingTemp -= systemSettings.TempChangeLongStep; } else @@ -213,21 +215,25 @@ static void gui_solderingTempAdjust() { break; case BUTTON_F_SHORT: if (systemSettings.ReverseButtonTempChangeEnabled) { - systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 + systemSettings.SolderingTemp -= systemSettings.TempChangeShortStep; // add 10 } else - systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 + systemSettings.SolderingTemp += systemSettings.TempChangeShortStep; // add 10 break; default: break; } - if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) { - autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; + if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < + PRESS_ACCEL_INTERVAL_MIN) { + autoRepeatAcceleration = + PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN; } // constrain between 10-450 C #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { - if (systemSettings.SolderingTemp > 850) systemSettings.SolderingTemp = 850; - if (systemSettings.SolderingTemp < 60) systemSettings.SolderingTemp = 60; + if (systemSettings.SolderingTemp > 850) + systemSettings.SolderingTemp = 850; + if (systemSettings.SolderingTemp < 60) + systemSettings.SolderingTemp = 60; } else #endif { @@ -238,7 +244,7 @@ static void gui_solderingTempAdjust() { } if (xTaskGetTickCount() - lastChange > 2000) - return; // exit if user just doesn't press anything for a bit + return; // exit if user just doesn't press anything for a bit #ifdef OLED_FLIP if (!OLED::getRotation()) { @@ -298,13 +304,17 @@ static int gui_SolderingSleepingMode(bool stayOff) { return 0; } -#ifdef MODEL_TS100 +#ifdef POW_PD if (checkVoltageForExit()) - return 1; // return non-zero on error + return 1; // return non-zero on error #endif #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) { - currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, systemSettings.SolderingTemp)); + currentTempTargetDegC = + stayOff + ? 0 + : TipThermoModel::convertFtoC(min(systemSettings.SleepTemp, + systemSettings.SolderingTemp)); } else #endif { @@ -360,7 +370,7 @@ static int gui_SolderingSleepingMode(bool stayOff) { if (shouldShutdown()) { // shutdown currentTempTargetDegC = 0; - return 1; // we want to exit soldering mode + return 1; // we want to exit soldering mode } } return 0; @@ -394,19 +404,20 @@ static uint32_t getSleepTimeout() { return 0; } static bool shouldBeSleeping() { -//Return true if the iron should be in sleep mode + // Return true if the iron should be in sleep mode if (systemSettings.sensitivity && systemSettings.SleepTime) { if ((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout() && (xTaskGetTickCount() - lastButtonTime) > getSleepTimeout()) { return true; } } #ifdef HALL_SENSOR - //If the hall effect sensor is enabled in the build, check if its over threshold, and if so then we force sleep + // If the hall effect sensor is enabled in the build, check if its over + // threshold, and if so then we force sleep if (lookupHallEffectThreshold()) { int16_t hallEffectStrength = getRawHallEffect(); if (hallEffectStrength < 0) hallEffectStrength = -hallEffectStrength; - //Have absolute value of measure of magnetic field strength + // Have absolute value of measure of magnetic field strength if (hallEffectStrength > lookupHallEffectThreshold()) { if (lastHallEffectSleepStart == 0) { lastHallEffectSleepStart = xTaskGetTickCount(); @@ -442,7 +453,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (jumpToSleep) { if (gui_SolderingSleepingMode(jumpToSleep == 2)) { lastButtonTime = xTaskGetTickCount(); - return; // If the function returns non-0 then exit + return; // If the function returns non-0 then exit } } for (;;) { @@ -459,7 +470,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::setCursor(0, 0); OLED::clearScreen(); OLED::setFont(0); - OLED::print(UnlockingKeysString); + OLED::print (UnlockingKeysString); OLED::refresh(); waitForButtonPressOrTimeout(1000); break; @@ -479,7 +490,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::setCursor(0, 0); OLED::clearScreen(); OLED::setFont(0); - OLED::print(WarningKeysLockedString); + OLED::print (WarningKeysLockedString); OLED::refresh(); waitForButtonPressOrTimeout(500); break; @@ -497,7 +508,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { return; break; case BUTTON_B_LONG: - return; // exit on back long hold + return; // exit on back long hold break; case BUTTON_F_LONG: // if boost mode is enabled turn it on @@ -507,9 +518,9 @@ static void gui_solderingMode(uint8_t jumpToSleep) { case BUTTON_F_SHORT: case BUTTON_B_SHORT: { uint16_t oldTemp = systemSettings.SolderingTemp; - gui_solderingTempAdjust(); // goto adjust temp mode + gui_solderingTempAdjust(); // goto adjust temp mode if (oldTemp != systemSettings.SolderingTemp) { - saveSettings(); // only save on change + saveSettings(); // only save on change } } break; @@ -520,7 +531,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::setCursor(0, 0); OLED::clearScreen(); OLED::setFont(0); - OLED::print(LockingKeysString); + OLED::print (LockingKeysString); OLED::refresh(); waitForButtonPressOrTimeout(1000); } @@ -536,7 +547,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { // Draw in the screen details if (systemSettings.detailedSoldering) { OLED::setFont(1); - OLED::print(SolderingAdvancedPowerPrompt); // Power: + OLED::print(SolderingAdvancedPowerPrompt); // Power: OLED::printNumber(x10WattHistory.average() / 10, 2); OLED::print(SymbolDot); OLED::printNumber(x10WattHistory.average() % 10, 1); @@ -560,7 +571,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { // battery gui_drawBatteryIcon(); OLED::print(SymbolSpace); // Space out gap between battery <-> temp - gui_drawTipTemp(true); // Draw current tip temp + gui_drawTipTemp(true); // Draw current tip temp // We draw boost arrow if boosting, or else gap temp <-> heat // indicator @@ -580,7 +591,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { OLED::drawSymbol(2); else OLED::print(SymbolSpace); - gui_drawTipTemp(true); // Draw current tip temp + gui_drawTipTemp(true); // Draw current tip temp OLED::print(SymbolSpace); // Space out gap between battery <-> temp @@ -593,7 +604,8 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (boostModeOn) { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.BoostTemp); + currentTempTargetDegC = + TipThermoModel::convertFtoC(systemSettings.BoostTemp); else #endif { @@ -602,7 +614,8 @@ static void gui_solderingMode(uint8_t jumpToSleep) { } else { #ifdef ENABLED_FAHRENHEIT_SUPPORT if (systemSettings.temperatureInF) - currentTempTargetDegC = TipThermoModel::convertFtoC(systemSettings.SolderingTemp); + currentTempTargetDegC = + TipThermoModel::convertFtoC(systemSettings.SolderingTemp); else #endif { @@ -620,7 +633,7 @@ static void gui_solderingMode(uint8_t jumpToSleep) { if (shouldBeSleeping()) { if (gui_SolderingSleepingMode(false)) { - return; // If the function returns non-0 then exit + return; // If the function returns non-0 then exit } } // slow down ui update rate @@ -632,14 +645,14 @@ void showDebugMenu(void) { uint8_t screen = 0; ButtonState b; for (;;) { - OLED::clearScreen(); // Ensure the buffer starts clean - OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) - OLED::setFont(1); // small font - OLED::print(SymbolVersionNumber); // Print version number - OLED::setCursor(0, 8); // second line + OLED::clearScreen(); // Ensure the buffer starts clean + OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left) + OLED::setFont(1); // small font + OLED::print(SymbolVersionNumber); // Print version number + OLED::setCursor(0, 8); // second line OLED::print(DebugMenu[screen]); switch (screen) { - case 0: // Just prints date + case 0: // Just prints date break; case 1: // High water mark for GUI @@ -704,30 +717,30 @@ void showDebugMenu(void) { uint8_t idleScreenBGF[sizeof(idleScreenBG)]; /* StartGUITask function */ void startGUITask(void const *argument __unused) { - OLED::initialize(); // start up the LCD + OLED::initialize(); // start up the LCD uint8_t tempWarningState = 0; bool buttonLockout = false; bool tempOnDisplay = false; { - //Generate the flipped screen into ram for later use - //flipped is generated by flipping each row + // Generate the flipped screen into ram for later use + // flipped is generated by flipping each row for (int row = 0; row < 2; row++) { for (int x = 0; x < 84; x++) { idleScreenBGF[(row * 84) + x] = idleScreenBG[(row * 84) + (83 - x)]; } } } - getTipRawTemp(1); // reset filter + getTipRawTemp(1); // reset filter OLED::setRotation(systemSettings.OrientationMode & 1); uint32_t ticks = xTaskGetTickCount(); - ticks += 4000; // 4 seconds from now + ticks += 4000; // 4 seconds from now while (xTaskGetTickCount() < ticks) { if (showBootLogoIfavailable() == false) ticks = xTaskGetTickCount(); ButtonState buttons = getButtonState(); if (buttons) - ticks = xTaskGetTickCount(); // make timeout now so we will exit + ticks = xTaskGetTickCount(); // make timeout now so we will exit GUIDelay(); } @@ -786,18 +799,18 @@ void startGUITask(void const *argument __unused) { saveSettings(); break; case BUTTON_F_SHORT: - gui_solderingMode(0); // enter soldering mode + gui_solderingMode(0); // enter soldering mode buttonLockout = true; break; case BUTTON_B_SHORT: - enterSettingsMenu(); // enter the settings menu + enterSettingsMenu(); // enter the settings menu buttonLockout = true; break; default: break; } - currentTempTargetDegC = 0; // ensure tip is off + currentTempTargetDegC = 0; // ensure tip is off getInputVoltageX10(systemSettings.voltageDiv, 0); uint32_t tipTemp = TipThermoModel::getTipInC(); @@ -807,7 +820,8 @@ void startGUITask(void const *argument __unused) { // button presses) in a while. OLED::setDisplayState(OLED::DisplayState::ON); - if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { + if ((tipTemp < 50) && systemSettings.sensitivity && (((xTaskGetTickCount() - lastMovementTime) > + MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) { OLED::setDisplayState(OLED::DisplayState::OFF); } @@ -862,12 +876,12 @@ void startGUITask(void const *argument __unused) { OLED::setCursor(56, 0); } else { - OLED::fillArea(0, 0, 41, 16, 0); // clear the area + OLED::fillArea(0, 0, 41, 16, 0); // clear the area OLED::setCursor(0, 0); } // draw in the temp if (!(systemSettings.coolingTempBlink && (xTaskGetTickCount() % 25 < 16))) - gui_drawTipTemp(false); // draw in the temp + gui_drawTipTemp(false); // draw in the temp } } OLED::refresh(); From 9fd1c957ce5567008ad0121971383da6e4efee53 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:52:55 +1100 Subject: [PATCH 62/72] Update QC_GPIO.cpp --- workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp index 5f9dee75..6dcb333c 100644 --- a/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp +++ b/workspace/TS100/Core/BSP/Miniware/QC_GPIO.cpp @@ -72,7 +72,7 @@ uint8_t QC_DM_PulledDown() { #endif void QC_resync() { #ifdef POW_QC - seekQC((systemSettings.cutoutSetting) ? 120 : 90, + seekQC((systemSettings.QCIdealVoltage) ? 120 : 90, systemSettings.voltageDiv); // Run the QC seek again if we have drifted too much #endif } From 3538acb07ddc5e077c57859bc01400cb374d8301 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 14:57:39 +1100 Subject: [PATCH 63/72] Update GUIThread.cpp --- workspace/TS100/Core/Threads/GUIThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index 1079fb0a..daa3f51b 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -304,7 +304,7 @@ static int gui_SolderingSleepingMode(bool stayOff) { return 0; } -#ifdef POW_PD +#ifdef POW_DC if (checkVoltageForExit()) return 1; // return non-zero on error #endif From f465d17bb35e5a0aaed5edf6646d4ceb797f7e7e Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 15:42:36 +1100 Subject: [PATCH 64/72] Fix QC 20V support --- workspace/TS100/Core/BSP/Miniware/Power.cpp | 14 +++++ .../TS100/Core/BSP/Pine64/Model_Config.h | 2 +- workspace/TS100/Core/Src/QC3.cpp | 11 ++-- workspace/TS100/Core/Threads/GUIThread.cpp | 62 ++++++++++--------- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/workspace/TS100/Core/BSP/Miniware/Power.cpp b/workspace/TS100/Core/BSP/Miniware/Power.cpp index 23b02783..7d3d28eb 100644 --- a/workspace/TS100/Core/BSP/Miniware/Power.cpp +++ b/workspace/TS100/Core/BSP/Miniware/Power.cpp @@ -34,3 +34,17 @@ uint8_t usb_pd_detect() { return false; } +bool getIsPoweredByDCIN() { +#ifdef MODEL_TS80 + return false; +#endif + +#ifdef MODEL_TS80P + return false; +#endif + +#ifdef MODEL_TS100 + return true; +#endif +} + diff --git a/workspace/TS100/Core/BSP/Pine64/Model_Config.h b/workspace/TS100/Core/BSP/Pine64/Model_Config.h index c4675a40..13846fc5 100644 --- a/workspace/TS100/Core/BSP/Pine64/Model_Config.h +++ b/workspace/TS100/Core/BSP/Pine64/Model_Config.h @@ -20,11 +20,11 @@ #define POW_QC #define POW_DC #define POW_QC_20V +#define ENABLE_QC2 #define TEMP_TMP36 #define ACCEL_BMA #define HALL_SENSOR #define HALL_SI7210 - #define BATTFILTERDEPTH 32 #endif diff --git a/workspace/TS100/Core/Src/QC3.cpp b/workspace/TS100/Core/Src/QC3.cpp index 4eb7e1e1..719f2c72 100644 --- a/workspace/TS100/Core/Src/QC3.cpp +++ b/workspace/TS100/Core/Src/QC3.cpp @@ -50,7 +50,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) { if (Vx10 < 45) return; - if (xTaskGetTickCount() < 1000) + if (xTaskGetTickCount() < TICKS_SECOND) return; #ifdef POW_QC_20V if (Vx10 > 200) @@ -89,7 +89,8 @@ void seekQC(int16_t Vx10, uint16_t divisor) { // Re-measure /* Disabled due to nothing to test and code space of around 1k*/ steps = vStart - getInputVoltageX10(divisor, 1); - if (steps < 0) steps = -steps; + if (steps < 0) + steps = -steps; if (steps > 4) { // No continuous mode, so QC2 QCMode = 2; @@ -111,11 +112,7 @@ void seekQC(int16_t Vx10, uint16_t divisor) { void startQC(uint16_t divisor) { // Pre check that the input could be >5V already, and if so, dont both // negotiating as someone is feeding in hv - uint16_t vin = getInputVoltageX10(divisor, 1); - if (vin > 80) { - QCMode = 0; //If over 8V something else has already negotiated - return; - } + QCMode=0; if (QCTries > 10) { return; } diff --git a/workspace/TS100/Core/Threads/GUIThread.cpp b/workspace/TS100/Core/Threads/GUIThread.cpp index daa3f51b..5af727c8 100644 --- a/workspace/TS100/Core/Threads/GUIThread.cpp +++ b/workspace/TS100/Core/Threads/GUIThread.cpp @@ -126,42 +126,45 @@ static bool checkVoltageForExit() { #endif static void gui_drawBatteryIcon() { #if defined(POW_PD) || defined(POW_QC) - - // On TS80 we replace this symbol with the voltage we are operating on - // If <9V then show single digit, if not show duals - uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); - if (V % 10 >= 5) - V = V / 10 + 1; // round up - else - V = V / 10; - if (V >= 10) { - int16_t xPos = OLED::getCursorX(); - OLED::setFont(1); - OLED::printNumber(V / 10, 1); - OLED::setCursor(xPos, 8); - OLED::printNumber(V % 10, 1); - OLED::setFont(0); - OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char - } else { - OLED::printNumber(V, 1); + if (!getIsPoweredByDCIN()) { + // On TS80 we replace this symbol with the voltage we are operating on + // If <9V then show single digit, if not show dual small ones vertically stacked + uint8_t V = getInputVoltageX10(systemSettings.voltageDiv, 0); + if (V % 10 >= 5) + V = V / 10 + 1; // round up + else + V = V / 10; + if (V >= 10) { + int16_t xPos = OLED::getCursorX(); + OLED::setFont(1); + OLED::printNumber(V / 10, 1); + OLED::setCursor(xPos, 8); + OLED::printNumber(V % 10, 1); + OLED::setFont(0); + OLED::setCursor(xPos + 12, 0); // need to reset this as if we drew a wide char + } else { + OLED::printNumber(V, 1); + } + return; } -#else - if (systemSettings.cutoutSetting) { +#endif +#ifdef POW_DC + if (systemSettings.minDCVoltageCells) { // User is on a lithium battery // we need to calculate which of the 10 levels they are on - uint8_t cellCount = systemSettings.cutoutSetting + 2; - uint32_t cellV = - getInputVoltageX10(systemSettings.voltageDiv, 0) / cellCount; + uint8_t cellCount = systemSettings.minDCVoltageCells + 2; + uint32_t cellV = getInputVoltageX10(systemSettings.voltageDiv, 0) / cellCount; // Should give us approx cell voltage X10 - // Range is 42 -> 33 = 9 steps therefore we will use battery 1-10 + // Range is 42 -> 33 = 9 steps therefore we will use battery 0-9 if (cellV < 33) - cellV = 33; - cellV -= 33;// Should leave us a number of 0-9 + cellV = 33; + cellV -= 33; // Should leave us a number of 0-9 if (cellV > 9) - cellV = 9; + cellV = 9; OLED::drawBattery(cellV + 1); - } else - OLED::drawSymbol(15); // Draw the DC Logo + } else { + OLED::drawSymbol(15); // Draw the DC Logo + } #endif } static void gui_solderingTempAdjust() { @@ -410,6 +413,7 @@ static bool shouldBeSleeping() { return true; } } + #ifdef HALL_SENSOR // If the hall effect sensor is enabled in the build, check if its over // threshold, and if so then we force sleep From f14e600e36dc223571afbee3a818f98ade77003c Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 15:48:27 +1100 Subject: [PATCH 65/72] Update gui.cpp --- workspace/TS100/Core/Src/gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index f8e2656a..f3f94382 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -156,7 +156,7 @@ const menuitem solderingMenu[] = { { (const char *) SettingsDescriptions[9], settings_setAutomaticStartMode, settings_displayAutomaticStartMode }, /*Auto start*/ { (const char *) SettingsDescriptions[22], settings_setTempChangeShortStep, settings_displayTempChangeShortStep }, /*Temp change short step*/ { (const char *) SettingsDescriptions[23], settings_setTempChangeLongStep, settings_displayTempChangeLongStep }, /*Temp change long step*/ -{ (const char *) SettingsDescriptions[26], settings_setLockingMode, settings_displayLockingMode }, /*Locking Mode*/ +{ (const char *) SettingsDescriptions[27], settings_setLockingMode, settings_displayLockingMode }, /*Locking Mode*/ { NULL, NULL, NULL } // end of menu marker. DO NOT REMOVE }; const menuitem UIMenu[] = { @@ -626,7 +626,7 @@ static bool settings_setLockingMode(void) { } static void settings_displayLockingMode(void) { - printShortDescription(26, 7); + printShortDescription(27, 7); switch (systemSettings.lockingMode) { case 0: From 2c6405da6841b6619e56e877896a28db8f56f34b Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 15:59:57 +1100 Subject: [PATCH 66/72] Update DC <-> QC descriptions --- Translation Editor/translation_bg.json | 4 ++-- Translation Editor/translation_cs.json | 4 ++-- Translation Editor/translation_da.json | 4 ++-- Translation Editor/translation_de.json | 4 ++-- Translation Editor/translation_en.json | 4 ++-- Translation Editor/translation_es.json | 4 ++-- Translation Editor/translation_fi.json | 4 ++-- Translation Editor/translation_fr.json | 4 ++-- Translation Editor/translation_hr.json | 4 ++-- Translation Editor/translation_hu.json | 4 ++-- Translation Editor/translation_it.json | 4 ++-- Translation Editor/translation_lt.json | 4 ++-- Translation Editor/translation_nl.json | 4 ++-- Translation Editor/translation_nl_be.json | 4 ++-- Translation Editor/translation_no.json | 4 ++-- Translation Editor/translation_pl.json | 4 ++-- Translation Editor/translation_pt.json | 4 ++-- Translation Editor/translation_ru.json | 4 ++-- Translation Editor/translation_sk.json | 4 ++-- Translation Editor/translation_sl.json | 4 ++-- Translation Editor/translation_sr_cyrl.json | 4 ++-- Translation Editor/translation_sr_latn.json | 4 ++-- Translation Editor/translation_sv.json | 4 ++-- Translation Editor/translation_tr.json | 4 ++-- Translation Editor/translation_uk.json | 4 ++-- Translation Editor/translations_def.js | 4 ++-- 26 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Translation Editor/translation_bg.json b/Translation Editor/translation_bg.json index b9f4252b..29830d24 100644 --- a/Translation Editor/translation_bg.json +++ b/Translation Editor/translation_bg.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Източник", "захранване" @@ -210,7 +210,7 @@ ], "desc": "Прецизна калибрация с използване на термо-двойка на върха на поялника" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Мощност на", "захранване" diff --git a/Translation Editor/translation_cs.json b/Translation Editor/translation_cs.json index b58ddcc0..98961268 100644 --- a/Translation Editor/translation_cs.json +++ b/Translation Editor/translation_cs.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Zdroj", "napájení" @@ -210,7 +210,7 @@ ], "desc": "Pokročilá kalibrace pomocí termočlánku na hrotu." }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Výkon", "ve wattech" diff --git a/Translation Editor/translation_da.json b/Translation Editor/translation_da.json index 3a18f939..8950c923 100644 --- a/Translation Editor/translation_da.json +++ b/Translation Editor/translation_da.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Power", "source" @@ -210,7 +210,7 @@ ], "desc": "Advanced calibration using thermocouple on the tip" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "Wattage" diff --git a/Translation Editor/translation_de.json b/Translation Editor/translation_de.json index 2bf34ed7..0ba7c800 100644 --- a/Translation Editor/translation_de.json +++ b/Translation Editor/translation_de.json @@ -78,7 +78,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Spannungs-", "quelle" @@ -211,7 +211,7 @@ ], "desc": "Erweiterte Kalibrierung mittels eines Thermoelements an der Lötspitze" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Leistungs-", "Aufnahme" diff --git a/Translation Editor/translation_en.json b/Translation Editor/translation_en.json index 3f29ca43..03730e9c 100644 --- a/Translation Editor/translation_en.json +++ b/Translation Editor/translation_en.json @@ -78,7 +78,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Power", "source" @@ -211,7 +211,7 @@ ], "desc": "Advanced calibration using thermocouple on the tip" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "wattage" diff --git a/Translation Editor/translation_es.json b/Translation Editor/translation_es.json index 76baa713..b5986ff9 100644 --- a/Translation Editor/translation_es.json +++ b/Translation Editor/translation_es.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Fuente", "de energía" @@ -210,7 +210,7 @@ ], "desc": "Calibrar con un termopar en la punta; más difícil." }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Potencia de", "entrada" diff --git a/Translation Editor/translation_fi.json b/Translation Editor/translation_fi.json index ef33be94..3da677f0 100644 --- a/Translation Editor/translation_fi.json +++ b/Translation Editor/translation_fi.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Virtalähde", "DC" @@ -210,7 +210,7 @@ ], "desc": "Advanced calibration using thermocouple on the tip" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "Wattage" diff --git a/Translation Editor/translation_fr.json b/Translation Editor/translation_fr.json index 11dc5728..cf64d5ed 100644 --- a/Translation Editor/translation_fr.json +++ b/Translation Editor/translation_fr.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Source", "d'alim" @@ -210,7 +210,7 @@ ], "desc": "Calibration avancées à l'aide d'un thermocouple sur la panne" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Puissance de", "l'alimentation" diff --git a/Translation Editor/translation_hr.json b/Translation Editor/translation_hr.json index 04d6095d..f19e0d8f 100644 --- a/Translation Editor/translation_hr.json +++ b/Translation Editor/translation_hr.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Izvor", "napajanja" @@ -210,7 +210,7 @@ ], "desc": "Kalibracija korištenjem termo-elementa" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Snaga", "napajanja" diff --git a/Translation Editor/translation_hu.json b/Translation Editor/translation_hu.json index 2228719b..54c7a649 100644 --- a/Translation Editor/translation_hu.json +++ b/Translation Editor/translation_hu.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Áram", "forrás" @@ -210,7 +210,7 @@ ], "desc": "Haladó kalibrálás hegyre helyezett hőelem segítségével" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Bemeneti", "teljesítmény" diff --git a/Translation Editor/translation_it.json b/Translation Editor/translation_it.json index 00a489f4..47a31a87 100644 --- a/Translation Editor/translation_it.json +++ b/Translation Editor/translation_it.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Sorgente", "alimentaz" @@ -210,7 +210,7 @@ ], "desc": "Calibra le rilevazioni di temperatura attraverso la termocoppia presente nella punta" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Potenza", "alimentaz" diff --git a/Translation Editor/translation_lt.json b/Translation Editor/translation_lt.json index 44a4e549..7de7fcda 100644 --- a/Translation Editor/translation_lt.json +++ b/Translation Editor/translation_lt.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Maitinimo", "šaltinis" @@ -210,7 +210,7 @@ ], "desc": "Išplėstinė kalibracija naudojant termoelementą" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Galia", "vatais" diff --git a/Translation Editor/translation_nl.json b/Translation Editor/translation_nl.json index a7b8bb86..adf99708 100644 --- a/Translation Editor/translation_nl.json +++ b/Translation Editor/translation_nl.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Spannings-", "bron" @@ -210,7 +210,7 @@ ], "desc": "Geavanceerde calibratie met een thermokoppel op de punt" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "Wattage" diff --git a/Translation Editor/translation_nl_be.json b/Translation Editor/translation_nl_be.json index c3450cca..9a168cb8 100644 --- a/Translation Editor/translation_nl_be.json +++ b/Translation Editor/translation_nl_be.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Spannings-", "bron" @@ -210,7 +210,7 @@ ], "desc": "Calibrering met thermokoppel" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Vermogen", "Watt" diff --git a/Translation Editor/translation_no.json b/Translation Editor/translation_no.json index 83544cff..8df24c27 100644 --- a/Translation Editor/translation_no.json +++ b/Translation Editor/translation_no.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Kilde", "" @@ -210,7 +210,7 @@ ], "desc": "Advanced calibration using thermocouple on the tip" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "Wattage" diff --git a/Translation Editor/translation_pl.json b/Translation Editor/translation_pl.json index a03bc634..cc456fdc 100644 --- a/Translation Editor/translation_pl.json +++ b/Translation Editor/translation_pl.json @@ -78,7 +78,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Źródło", "zasilania" @@ -211,7 +211,7 @@ ], "desc": "Zaawansowana kalibracja za pomocą termoelementu na grocie" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Moc", "w W" diff --git a/Translation Editor/translation_pt.json b/Translation Editor/translation_pt.json index 3297c338..e8d62a23 100644 --- a/Translation Editor/translation_pt.json +++ b/Translation Editor/translation_pt.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Fonte", "alimentação" @@ -210,7 +210,7 @@ ], "desc": "Calibração avançada com um termopar na ponta" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Potência", "Fonte" diff --git a/Translation Editor/translation_ru.json b/Translation Editor/translation_ru.json index 21a07dea..85b6e036 100644 --- a/Translation Editor/translation_ru.json +++ b/Translation Editor/translation_ru.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Источник", "питания" @@ -210,7 +210,7 @@ ], "desc": "Улучшенная калибровка с импользованием термопары жала" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Мощность", "питания" diff --git a/Translation Editor/translation_sk.json b/Translation Editor/translation_sk.json index 93a2f664..4c47b721 100644 --- a/Translation Editor/translation_sk.json +++ b/Translation Editor/translation_sk.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Zdroj", "napätia" @@ -210,7 +210,7 @@ ], "desc": "Pokročilá kalibrácia meraním teploty hrotu" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Obmedzenie", "výkonu" diff --git a/Translation Editor/translation_sl.json b/Translation Editor/translation_sl.json index 8c60f6ab..f6d99f15 100644 --- a/Translation Editor/translation_sl.json +++ b/Translation Editor/translation_sl.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Vir", "napajanja" @@ -210,7 +210,7 @@ ], "desc": "Napredna kalibracija s termočlenom na konici" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Moč napajalnega", "vira" diff --git a/Translation Editor/translation_sr_cyrl.json b/Translation Editor/translation_sr_cyrl.json index 6faf743d..570df775 100644 --- a/Translation Editor/translation_sr_cyrl.json +++ b/Translation Editor/translation_sr_cyrl.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Врста", "напајања" @@ -210,7 +210,7 @@ ], "desc": "Напредна калибрација помоћу термопара." }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Улазна", "снага" diff --git a/Translation Editor/translation_sr_latn.json b/Translation Editor/translation_sr_latn.json index 839508ef..a14cad93 100644 --- a/Translation Editor/translation_sr_latn.json +++ b/Translation Editor/translation_sr_latn.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Vrsta", "napajanja" @@ -210,7 +210,7 @@ ], "desc": "Napredna kalibracija pomoću termopara." }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Ulazna", "snaga" diff --git a/Translation Editor/translation_sv.json b/Translation Editor/translation_sv.json index d5f55b1d..1b6e039f 100644 --- a/Translation Editor/translation_sv.json +++ b/Translation Editor/translation_sv.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Ström-", "källa" @@ -210,7 +210,7 @@ ], "desc": "Advanced calibration using thermocouple on the tip" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Power", "Wattage" diff --git a/Translation Editor/translation_tr.json b/Translation Editor/translation_tr.json index be154426..995887aa 100644 --- a/Translation Editor/translation_tr.json +++ b/Translation Editor/translation_tr.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "PWRSC", "" @@ -210,7 +210,7 @@ ], "desc": "Uçtaki ısı sensörünü kullanarak gelişmiş kalibrasyon" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Güç", "Miktarı(W)" diff --git a/Translation Editor/translation_uk.json b/Translation Editor/translation_uk.json index b2351142..ab83795f 100644 --- a/Translation Editor/translation_uk.json +++ b/Translation Editor/translation_uk.json @@ -77,7 +77,7 @@ } }, "menuOptions": { - "PowerSource": { + "DCInCutoff": { "text2": [ "Джерело", "живлення" @@ -210,7 +210,7 @@ ], "desc": "Калібрування за допомогою термопари" }, - "PowerInput": { + "QCMaxVoltage": { "text2": [ "Потужність", "дж. живл." diff --git a/Translation Editor/translations_def.js b/Translation Editor/translations_def.js index f3246e2d..aae794a7 100644 --- a/Translation Editor/translations_def.js +++ b/Translation Editor/translations_def.js @@ -199,7 +199,7 @@ var def = ], "menuOptions": [ { - "id": "PowerSource", + "id": "DCInCutoff", "maxLen": 5, "maxLen2": 11 }, @@ -294,7 +294,7 @@ var def = "maxLen2": 16 }, { - "id": "PowerInput", + "id": "QCMaxVoltage", "maxLen": 8, "maxLen2": 16 }, From 8b336af3c15a469f926e53beec31439d6b81e8d5 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 16:00:19 +1100 Subject: [PATCH 67/72] Update gui.cpp --- workspace/TS100/Core/Src/gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/TS100/Core/Src/gui.cpp b/workspace/TS100/Core/Src/gui.cpp index f3f94382..616bb20c 100644 --- a/workspace/TS100/Core/Src/gui.cpp +++ b/workspace/TS100/Core/Src/gui.cpp @@ -318,7 +318,7 @@ static bool settings_setQCInputV(void) { } static void settings_displayQCInputV(void) { - printShortDescription(0, 5); + printShortDescription(19, 5); //0 = 9V, 1=12V, 2=20V (Fixed Voltages) // These are only used in QC modes switch (systemSettings.QCIdealVoltage) { From 886a4276cd91dc1c076c30c0802363e655479e53 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 16:00:47 +1100 Subject: [PATCH 68/72] Update translation_en.json --- Translation Editor/translation_en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Translation Editor/translation_en.json b/Translation Editor/translation_en.json index 03730e9c..7394907d 100644 --- a/Translation Editor/translation_en.json +++ b/Translation Editor/translation_en.json @@ -213,10 +213,10 @@ }, "QCMaxVoltage": { "text2": [ - "Power", - "wattage" + "QC", + "Voltage" ], - "desc": "Power wattage of the power adapter used" + "desc": "Desired max QC Voltage negotiated for" }, "PowerLimit": { "text2": [ From 2a3cbd1986dfdc60c739dc460cdafcd531606952 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 16:13:38 +1100 Subject: [PATCH 69/72] Update build.sh --- workspace/TS100/build.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 6b2f2feb..5004948b 100755 --- a/workspace/TS100/build.sh +++ b/workspace/TS100/build.sh @@ -10,7 +10,7 @@ AVAILABLE_MODELS=("TS100" "TS80" "TS80P" "Pinecil") BUILD_MODELS=() usage() { - echo "Usage : $(basename "$0") [-l ] [-m ] [-h] + echo "Usage : $(basename "$0") [-l ] [-m ] [-h] Parameters : -l LANG_CODE : Force a specific language (E.g. : EN, FR, NL_BE, ...) @@ -132,7 +132,9 @@ if [ ${#BUILD_LANGUAGES[@]} -gt 0 ] && [ ${#BUILD_MODELS[@]} -gt 0 ]; then make -j lang="$lang" model="$model" >/dev/null checkLastCommand echo "Cleanup Temp files for $model in $lang" - rm -rf Objects/Core/ >/dev/null + rm -rf Objects/Core/Threads >/dev/null + checkLastCommand + rm -rf Objects/Core/Src >/dev/null checkLastCommand done echo "Cleanup model change" From fa0663353921364b6702759f836ff7d2c7e61145 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 1 Nov 2020 17:06:04 +1100 Subject: [PATCH 70/72] Tweak temp files to be entirely seperate --- workspace/TS100/Makefile | 7 +++---- workspace/TS100/build.sh | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 9330f4d1..8ff8429a 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -95,8 +95,8 @@ $(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.cpp') HEXFILE_DIR=Hexfile # temporary objects folder -OUTPUT_DIR=Objects - +OUTPUT_BASE_DIR=Objects +OUTPUT_DIR=$(OUTPUT_BASE_DIR)/$(model) # code optimisation ------------------------------------------------------------ OPTIM_AS= -Wall OPTIM=-Os -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections @@ -284,7 +284,6 @@ all: $(OUT_HEXFILE).hex $(OUT_HEXFILE).bin $(OBJCOPY) $^ -O ihex $@ %.bin : %.elf - $(SIZE) $^ $(OBJCOPY) $^ -O binary $@ $(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) @@ -315,7 +314,7 @@ $(OUT_OBJS_S): $(OUTPUT_DIR)/%.o: %.S Makefile clean : - rm -Rf $(OUTPUT_DIR) + rm -Rf $(OUTPUT_BASE_DIR) rm -Rf $(HEXFILE_DIR) diff --git a/workspace/TS100/build.sh b/workspace/TS100/build.sh index 5004948b..b7928cd6 100755 --- a/workspace/TS100/build.sh +++ b/workspace/TS100/build.sh @@ -132,9 +132,9 @@ if [ ${#BUILD_LANGUAGES[@]} -gt 0 ] && [ ${#BUILD_MODELS[@]} -gt 0 ]; then make -j lang="$lang" model="$model" >/dev/null checkLastCommand echo "Cleanup Temp files for $model in $lang" - rm -rf Objects/Core/Threads >/dev/null + rm -rf Objects/*/Core/Threads >/dev/null checkLastCommand - rm -rf Objects/Core/Src >/dev/null + rm -rf Objects/*/Core/Src >/dev/null checkLastCommand done echo "Cleanup model change" From fdec7bc0a353346be482b7caf48408a4e28c14a1 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 8 Nov 2020 22:10:43 +1100 Subject: [PATCH 71/72] Collapse asm into one file Working across 4 files was a pain to figure out _exactly_ what was used. Collapsed all into one file for ease --- .../TS100/Core/BSP/Pine64/N200/portasm.S | 538 ++++++++++++++---- .../BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S | 35 -- .../Core/BSP/Pine64/Vendor/RISCV/entry.S | 291 ---------- .../Core/BSP/Pine64/Vendor/RISCV/start.S | 289 ---------- 4 files changed, 416 insertions(+), 737 deletions(-) delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S delete mode 100644 workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S diff --git a/workspace/TS100/Core/BSP/Pine64/N200/portasm.S b/workspace/TS100/Core/BSP/Pine64/N200/portasm.S index 8e34bedb..ff73e533 100644 --- a/workspace/TS100/Core/BSP/Pine64/N200/portasm.S +++ b/workspace/TS100/Core/BSP/Pine64/N200/portasm.S @@ -2,11 +2,6 @@ #include "riscv_bits.h" #include "n200_timer.h" #include "n200_eclic.h" -#include "riscv_encoding.h" -#include "riscv_bits.h" -#include "n200_timer.h" -#include "n200_eclic.h" - #define USE_MSP 1 //启用中断栈 @@ -19,8 +14,295 @@ .global vPortEndScheduler .global vPortAsmAssertSP + .section .init + + .weak eclic_msip_handler //弱定义函数,这些在编译为bin后可以看到将全部为0 + .weak eclic_mtip_handler + .weak eclic_bwei_handler + .weak eclic_pmovi_handler + .weak WWDGT_IRQHandler + .weak LVD_IRQHandler + .weak TAMPER_IRQHandler + .weak RTC_IRQHandler + .weak FMC_IRQHandler + .weak RCU_IRQHandler + .weak EXTI0_IRQHandler + .weak EXTI1_IRQHandler + .weak EXTI2_IRQHandler + .weak EXTI3_IRQHandler + .weak EXTI4_IRQHandler + .weak DMA0_Channel0_IRQHandler + .weak DMA0_Channel1_IRQHandler + .weak DMA0_Channel2_IRQHandler + .weak DMA0_Channel3_IRQHandler + .weak DMA0_Channel4_IRQHandler + .weak DMA0_Channel5_IRQHandler + .weak DMA0_Channel6_IRQHandler + .weak ADC0_1_IRQHandler + .weak CAN0_TX_IRQHandler + .weak CAN0_RX0_IRQHandler + .weak CAN0_RX1_IRQHandler + .weak CAN0_EWMC_IRQHandler + .weak EXTI5_9_IRQHandler + .weak TIMER0_BRK_IRQHandler + .weak TIMER0_UP_IRQHandler + .weak TIMER0_TRG_CMT_IRQHandler + .weak TIMER0_Channel_IRQHandler + .weak TIMER1_IRQHandler + .weak TIMER2_IRQHandler + .weak TIMER3_IRQHandler + .weak I2C0_EV_IRQHandler + .weak I2C0_ER_IRQHandler + .weak I2C1_EV_IRQHandler + .weak I2C1_ER_IRQHandler + .weak SPI0_IRQHandler + .weak SPI1_IRQHandler + .weak USART0_IRQHandler + .weak USART1_IRQHandler + .weak USART2_IRQHandler + .weak EXTI10_15_IRQHandler + .weak RTC_Alarm_IRQHandler + .weak USBFS_WKUP_IRQHandler + .weak EXMC_IRQHandler + .weak TIMER4_IRQHandler + .weak SPI2_IRQHandler + .weak UART3_IRQHandler + .weak UART4_IRQHandler + .weak TIMER5_IRQHandler + .weak TIMER6_IRQHandler + .weak DMA1_Channel0_IRQHandler + .weak DMA1_Channel1_IRQHandler + .weak DMA1_Channel2_IRQHandler + .weak DMA1_Channel3_IRQHandler + .weak DMA1_Channel4_IRQHandler + .weak CAN1_TX_IRQHandler + .weak CAN1_RX0_IRQHandler + .weak CAN1_RX1_IRQHandler + .weak CAN1_EWMC_IRQHandler + .weak USBFS_IRQHandler + +vector_base: //中断向量表 + j _start //第一条指令即跳转到_start处开始执行 + .align 2 + .word 0 + .word 0 + .word eclic_msip_handler + .word 0 + .word 0 + .word 0 + .word eclic_mtip_handler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word eclic_bwei_handler + .word eclic_pmovi_handler + .word WWDGT_IRQHandler + .word LVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FMC_IRQHandler + .word RCU_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA0_Channel0_IRQHandler + .word DMA0_Channel1_IRQHandler + .word DMA0_Channel2_IRQHandler + .word DMA0_Channel3_IRQHandler + .word DMA0_Channel4_IRQHandler + .word DMA0_Channel5_IRQHandler + .word DMA0_Channel6_IRQHandler + .word ADC0_1_IRQHandler + .word CAN0_TX_IRQHandler + .word CAN0_RX0_IRQHandler + .word CAN0_RX1_IRQHandler + .word CAN0_EWMC_IRQHandler + .word EXTI5_9_IRQHandler + .word TIMER0_BRK_IRQHandler + .word TIMER0_UP_IRQHandler + .word TIMER0_TRG_CMT_IRQHandler + .word TIMER0_Channel_IRQHandler + .word TIMER1_IRQHandler + .word TIMER2_IRQHandler + .word TIMER3_IRQHandler + .word I2C0_EV_IRQHandler + .word I2C0_ER_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word SPI0_IRQHandler + .word SPI1_IRQHandler + .word USART0_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word EXTI10_15_IRQHandler + .word RTC_Alarm_IRQHandler + .word USBFS_WKUP_IRQHandler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word EXMC_IRQHandler + .word 0 + .word TIMER4_IRQHandler + .word SPI2_IRQHandler + .word UART3_IRQHandler + .word UART4_IRQHandler + .word TIMER5_IRQHandler + .word TIMER6_IRQHandler + .word DMA1_Channel0_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word 0 + .word 0 + .word CAN1_TX_IRQHandler + .word CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_EWMC_IRQHandler + .word USBFS_IRQHandler + + .globl _start + .type _start,@function + +_start: + + csrc CSR_MSTATUS, MSTATUS_MIE //CSR_MSTATUS &= ~0x8 mstatus[3]:0屏蔽全部中断 1不屏蔽全部中断 (当然这里全部中断是除过不可屏蔽中断) + /* Jump to logical address first to ensure correct operation of RAM region */ + la a0, _start //a0 = _start + li a1, 1 //a1 = 1 + slli a1, a1, 29 //a1 = 0x20000000 raw起始地址 + bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 + srli a1, a1, 2 //a1 = 0x08000000 flash起始地址 + bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 + la a0, _start0800 //a0 = _start0800 + add a0, a0, a1 //a0 = a0+a1 + jr a0 //JUMP a0 + +_start0800: + + /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */ + li t0, 0x200 //t0 = 0x200 + csrs CSR_MMISC_CTL, t0 //mmisc_ctl |= 0x200 CSR_MMISC_CTL[9]:设置NMI的地址与mtvec相同且,mcause.EXCCODE = 0xfff + //cs开头的指令是特有的用来操作内核寄存器的的指令,内核寄存器是一组特有的12位地址 + + /* Intial the mtvt*/ + la t0, vector_base //t0 = vector_base 向量表地址 + csrw CSR_MTVT, t0 //mtvt = vector_base 中断向量表基地址 + + /* Intial the mtvt2 and enable it*/ + la t0, irq_entry //t0 = irq_entry irq_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S + csrw CSR_MTVT2, t0 //mtvt2 = irq_entry mtvt2[31:2]: 中断入口函数地址 + csrs CSR_MTVT2, 0x1 //mtvt2 |= 0x1 mtvt2[0]: 1配置mtvt2的配置有效,配0则为mtvec内地址 + + /* Intial the CSR MTVEC for the Trap ane NMI base addr*/ + la t0, trap_entry //t0 = trap_entry trap_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S + csrw CSR_MTVEC, t0 //mtvec = trap_entry mtvec[31:6]:异常入口地址 + // mtvec[5:0]:0B00011 -- ECLIC中断模式 其他:默认模式 + // 这里配置为默认模式 + // trap_entry基本上可以理解为arm里的hard/mem/use/svc等fault了, + // 这里在移植freertos时就使用了 ecall 进入trap_entry里 相当于arm里的PendSVC + + /* OS启动前配置中断栈为FHEAP的end地址 */ + la t0, ucHeap + csrw CSR_MSCRATCH, t0 + +#ifdef __riscv_flen //浮点宏 + /* Enable FPU */ + li t0, MSTATUS_FS //t0 = 0x6000 + csrs mstatus, t0 //mstatus |= 0x6000 mstatus[14:13]:非零值启用浮点单元,配置为1或2会在第一次使用浮点单元时变为3,这里直接配置为3 + csrw fcsr, x0 //fcsr = x0 = 0 ??这里x0是否指的是zero通用寄存器值? 这个寄存器0-4位是浮点异常状态标志,5-7位是浮点舍入模式配置 +#endif + +.option push +.option norelax + la gp, __global_pointer$ //__global_pointer$定义在link连接脚本内,指向所有.data段后偏移0x800的地址,0x800为2K,其值源于下文解释 + //gp 意为global pointer (全局指针)寄存器是一个解决方案, + //为了以进一步优化存储器访问单个4KB区域内。 + //链接器使用__global_pointer$符号定义来比较内存地址,如果在范围内, + //则它将绝对/相对pc寻址替换为gp相对寻址,从而使代码更有效。这个过程通过-Wl,--no-relax选项使用。 + //这里.option norelax起到-Wl,--no-relax作用,就不需要在编译选项添加了 + //上文参考自:https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register + //要让 relaxing 优化起作用,编译时要加入 -msmall-data-limit=n 参数,有了这个参数, + //编译器会把内存空间小于 n 字节的静态变量放入 .sdata 或者 .sdata.* 节, + //然后链接器将这部分静态变量集中在 __global_pointer$ +/- 2K 的范围内。 + //上文参考自:https://blog.csdn.net/zoomdy/article/details/100703451 +.option pop + la sp, _sp //sp = 主栈栈顶地址 _sp定义在link连接脚本内 + + /* Load data section */ + la a0, _data_lma //a0 = data的Load Memory Address _data_lma定义在link连接脚本内 + la a1, _data //a1 = data的Run Memory Address _data定义在link连接脚本内 + la a2, _edata //a2 = data的Run Memory Address结束地址 _edata定义在link连接脚本内 + bgeu a1, a2, 2f //if( a1 >= a2 ) JUMP 2f 原则上不会出现_data地址大于_edata地址 + //如果出现了则直接跳转到 2f 即下一个2标签 +1: + lw t0, (a0) //t0 = _data_lma + sw t0, (a1) //*_data = t0 即 *_data_lma,按word写入 + addi a0, a0, 4 //a0 = a0 + 4 下一个ward + addi a1, a1, 4 //a1 = a1 + 4 + bltu a1, a2, 1b //if( a1 < a2 ) JUMP 1b 如果未到达_edata则跳转到 1b 即上一个1标签,这里会完成一个循环 +2: + /* Clear bss section */ + la a0, __bss_start //a0 = __bss_start 初值为0的全局变量段起始地址 __bss_start定义在link连接脚本内 + la a1, _end //a1 = _end 初值为0的全局变量段结束地址 _end定义在link连接脚本内 + bgeu a0, a1, 2f //if( a0 >= a1 ) JUMP 2f 原则上不会出现__bss_start地址大于_end地址 + //如果出现了则直接跳转到 2f 即下一个2标签 +1: + sw zero, (a0) //*__bss_start = zero = 0 bss段清除为0 + addi a0, a0, 4 //a0 = a0 + 4 下一个ward + bltu a0, a1, 1b //if( a0 < a1 ) JUMP 1b 如果未到达_end则跳转到 1b 即上一个1标签,这里会完成一个循环 + + //程序执行到这里全局变量就以及处理完毕了 +2: + /*enable mcycle_minstret*/ + csrci CSR_MCOUNTINHIBIT, 0x5 //CSR_MCOUNTINHIBIT &= ~0x5 这里清零了第0bit和第1bit,使能了mcycle计数和minstret计数 + //csrci这条指令处理立即数5bit,列如0x5只是0B00101,高位不处理 + /* + * Call vendor defined SystemInit to + * initialize the micro-controller system + */ + call SystemInit + /* Call global constructors */ + la a0, __libc_fini_array //a0 = __libc_fini_array newlib中atexit函数的参数 + call atexit //调用newlib中的 void atexit(void (*func)(void)) 函数 + //功能为注册main函数结束后调用的函数,这里是__libc_fini_array + call __libc_init_array //调用newlib中的 void __libc_init_array (void) 函数 + //这里要注意__libc_init_array函数会调用_init的钩子函数,用来做c环境初始化前的一些硬件初始化 + //列如时钟的配置等,这里_init定义在init.c + + //程序执行到这里C/C++环境就初始化完成了,可以进入main函数入口了 + /* argc = argv = 0 */ + li a0, 0 //a0 = 0 main函数参数argc = 0 + li a1, 0 //a1 = 0 main函数参数argv = 0 + call main //调用 int main(int argc,char **argv) 函数 + tail exit //main返回后调用newlib的exit函数, tail指令应该是不会返回的调用函数了 + +1: + j 1b //1b 即上一次1标签,即跳转到自己,程序到这里就死循环了,原则不会运行到这里 + + .global disable_mcycle_minstret +disable_mcycle_minstret: + csrsi CSR_MCOUNTINHIBIT, 0x5 //关闭了mcycle计数和minstret计数 + ret + + .global enable_mcycle_minstret +enable_mcycle_minstret: + csrci CSR_MCOUNTINHIBIT, 0x5 //使能了mcycle计数和minstret计数 + ret + + /** - * @brife 压栈通用寄存器 + * @brief 压栈通用寄存器 * @param x 目标sp寄存器 */ .macro pushREGFILE x @@ -31,8 +313,8 @@ #endif STORE x1, 1 * REGBYTES(\x) STORE x2, 2 * REGBYTES(\x) - //STORE x3, 3 * REGBYTES(\x) - //STORE x4, 4 * REGBYTES(\x) + #STORE x3, 3 * REGBYTES(\x) + #STORE x4, 4 * REGBYTES(\x) STORE x5, 5 * REGBYTES(\x) STORE x6, 6 * REGBYTES(\x) STORE x7, 7 * REGBYTES(\x) @@ -66,7 +348,7 @@ /** - * @brife 压栈csr寄存器(CSR_MSTATUS CSR_MEPC CSR_MSUBM CSR_MCAUSE) + * @brief 压栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) * @param x 目标sp寄存器 */ .macro portSAVE_CONTEXT_EXCP x @@ -82,7 +364,109 @@ /** - * @brife 压栈浮点寄存器 + * @brief 压栈浮点寄存器 + * @param x 目标sp寄存器 + */ +.macro popVFPREGFILE x + flw f0, 36 * REGBYTES(\x) + flw f1, 37 * REGBYTES(\x) + flw f2, 38 * REGBYTES(\x) + flw f3, 39 * REGBYTES(\x) + flw f4, 40 * REGBYTES(\x) + flw f5, 41 * REGBYTES(\x) + flw f6, 42 * REGBYTES(\x) + flw f7, 43 * REGBYTES(\x) + flw f8, 44 * REGBYTES(\x) + flw f9, 45 * REGBYTES(\x) + flw f10,46 * REGBYTES(\x) + flw f11, 47 * REGBYTES(\x) + flw f12, 48 * REGBYTES(\x) + flw f13, 49 * REGBYTES(\x) + flw f14, 50 * REGBYTES(\x) + flw f15, 51 * REGBYTES(\x) + flw f16, 52 * REGBYTES(\x) + flw f17, 53 * REGBYTES(\x) + flw f18, 54 * REGBYTES(\x) + flw f19, 55 * REGBYTES(\x) + flw f20, 56 * REGBYTES(\x) + flw f21, 57 * REGBYTES(\x) + flw f22, 58 * REGBYTES(\x) + flw f23, 59 * REGBYTES(\x) + flw f24, 60 * REGBYTES(\x) + flw f25, 61 * REGBYTES(\x) + flw f26, 62 * REGBYTES(\x) + flw f27, 63 * REGBYTES(\x) + flw f28, 64 * REGBYTES(\x) + flw f29, 65 * REGBYTES(\x) + flw f30, 66 * REGBYTES(\x) + flw f31, 67 * REGBYTES(\x) +.endm + + +/** + * @brief 出栈通用寄存器 + * @param x 目标sp寄存器 + */ +.macro popREGFILE x + LOAD x1, 1 * REGBYTES(\x) + #LOAD x2, 2 * REGBYTES(\x) + #LOAD x3, 3 * REGBYTES(\x) + #LOAD x4, 4 * REGBYTES(\x) + LOAD x5, 5 * REGBYTES(\x) + LOAD x6, 6 * REGBYTES(\x) + LOAD x7, 7 * REGBYTES(\x) + LOAD x8, 8 * REGBYTES(\x) + LOAD x9, 9 * REGBYTES(\x) + LOAD x10, 10 * REGBYTES(\x) + LOAD x11, 11 * REGBYTES(\x) + LOAD x12, 12 * REGBYTES(\x) + LOAD x13, 13 * REGBYTES(\x) + LOAD x14, 14 * REGBYTES(\x) + LOAD x15, 15 * REGBYTES(\x) +#ifndef __riscv_32e + LOAD x16, 16 * REGBYTES(\x) + LOAD x17, 17 * REGBYTES(\x) + LOAD x18, 18 * REGBYTES(\x) + LOAD x19, 19 * REGBYTES(\x) + LOAD x20, 20 * REGBYTES(\x) + LOAD x21, 21 * REGBYTES(\x) + LOAD x22, 22 * REGBYTES(\x) + LOAD x23, 23 * REGBYTES(\x) + LOAD x24, 24 * REGBYTES(\x) + LOAD x25, 25 * REGBYTES(\x) + LOAD x26, 26 * REGBYTES(\x) + LOAD x27, 27 * REGBYTES(\x) + LOAD x28, 28 * REGBYTES(\x) + LOAD x29, 29 * REGBYTES(\x) + LOAD x30, 30 * REGBYTES(\x) + LOAD x31, 31 * REGBYTES(\x) +#endif +#ifdef __riscv_flen + addi \x, \x, REGBYTES * 68 //36+32 +#else + addi \x, \x, REGBYTES * 36 +#endif +.endm + + +/** + * @brief 出栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) + * @param x 目标sp寄存器 + */ +.macro portRESTORE_CONTEXT_EXCP x + LOAD t0, 35*REGBYTES(\x) + csrw CSR_MCAUSE, t0 + LOAD t0, 34*REGBYTES(\x) + csrw CSR_MSUBM, t0 + LOAD t0, 33*REGBYTES(\x) + csrw CSR_MEPC, t0 + LOAD t0, 32*REGBYTES(\x) + csrw CSR_MSTATUS, t0 +.endm + + +/** + * @brief 出栈浮点寄存器 * @param x 目标sp寄存器 */ .macro pushVFPREGFILE x @@ -122,139 +506,40 @@ /** - * @brife 出栈通用寄存器 - * @param x 目标sp寄存器 - */ -.macro popREGFILE x - LOAD x1, 1 * REGBYTES(\x) - //LOAD x2, 2 * REGBYTES(\x) - //LOAD x3, 3 * REGBYTES(\x) - //LOAD x4, 4 * REGBYTES(\x) - LOAD x5, 5 * REGBYTES(\x) - LOAD x6, 6 * REGBYTES(\x) - LOAD x7, 7 * REGBYTES(\x) - LOAD x8, 8 * REGBYTES(\x) - LOAD x9, 9 * REGBYTES(\x) - LOAD x10, 10 * REGBYTES(\x) - LOAD x11, 11 * REGBYTES(\x) - LOAD x12, 12 * REGBYTES(\x) - LOAD x13, 13 * REGBYTES(\x) - LOAD x14, 14 * REGBYTES(\x) - LOAD x15, 15 * REGBYTES(\x) -#ifndef __riscv_32e - LOAD x16, 16 * REGBYTES(\x) - LOAD x17, 17 * REGBYTES(\x) - LOAD x18, 18 * REGBYTES(\x) - LOAD x19, 19 * REGBYTES(\x) - LOAD x20, 20 * REGBYTES(\x) - LOAD x21, 21 * REGBYTES(\x) - LOAD x22, 22 * REGBYTES(\x) - LOAD x23, 23 * REGBYTES(\x) - LOAD x24, 24 * REGBYTES(\x) - LOAD x25, 25 * REGBYTES(\x) - LOAD x26, 26 * REGBYTES(\x) - LOAD x27, 27 * REGBYTES(\x) - LOAD x28, 28 * REGBYTES(\x) - LOAD x29, 29 * REGBYTES(\x) - LOAD x30, 30 * REGBYTES(\x) - LOAD x31, 31 * REGBYTES(\x) -#endif -#ifdef __riscv_flen - addi \x, \x, REGBYTES * 68 //36+32 -#else - addi \x, \x, REGBYTES * 36 -#endif -.endm - - -/** - * @brife 出栈csr寄存器(CSR_MSTATUS CSR_MEPC CSR_MSUBM CSR_MCAUSE) - * @param x 目标sp寄存器 - */ -.macro portRESTORE_CONTEXT_EXCP x - LOAD t0, 35 * REGBYTES(\x) - csrw CSR_MCAUSE, t0 - LOAD t0, 34 * REGBYTES(\x) - csrw CSR_MSUBM, t0 - LOAD t0, 33 * REGBYTES(\x) - csrw CSR_MEPC, t0 - LOAD t0, 32 * REGBYTES(\x) - csrw CSR_MSTATUS, t0 -.endm - - -/** - * @brife 出栈浮点寄存器 - * @param x 目标sp寄存器 - */ -.macro popVFPREGFILE x - flw f0, 36 * REGBYTES(\x) - flw f1, 37 * REGBYTES(\x) - flw f2, 38 * REGBYTES(\x) - flw f3, 39 * REGBYTES(\x) - flw f4, 40 * REGBYTES(\x) - flw f5, 41 * REGBYTES(\x) - flw f6, 42 * REGBYTES(\x) - flw f7, 43 * REGBYTES(\x) - flw f8, 44 * REGBYTES(\x) - flw f9, 45 * REGBYTES(\x) - flw f10, 46 * REGBYTES(\x) - flw f11, 47 * REGBYTES(\x) - flw f12, 48 * REGBYTES(\x) - flw f13, 49 * REGBYTES(\x) - flw f14, 50 * REGBYTES(\x) - flw f15, 51 * REGBYTES(\x) - flw f16, 52 * REGBYTES(\x) - flw f17, 53 * REGBYTES(\x) - flw f18, 54 * REGBYTES(\x) - flw f19, 55 * REGBYTES(\x) - flw f20, 56 * REGBYTES(\x) - flw f21, 57 * REGBYTES(\x) - flw f22, 58 * REGBYTES(\x) - flw f23, 59 * REGBYTES(\x) - flw f24, 60 * REGBYTES(\x) - flw f25, 61 * REGBYTES(\x) - flw f26, 62 * REGBYTES(\x) - flw f27, 63 * REGBYTES(\x) - flw f28, 64 * REGBYTES(\x) - flw f29, 65 * REGBYTES(\x) - flw f30, 66 * REGBYTES(\x) - flw f31, 67 * REGBYTES(\x) -.endm - - -/** - * @brife 清理fpu状态寄存器 + * @brief 清理fpu状态寄存器 */ .macro CONFIG_FS_CLEAN - li t0, (0x1 << 13) - csrc mstatus,t0 + li t0, (0x1 << 13) //配置FS为clean状态 + csrc mstatus, t0 li t0, (0x1 << 14) - csrs mstatus,t0 + csrs mstatus, t0 .endm /* -------------------------------------------------------------------------------------------------------- */ /** - * @brife trap入口函数 + * @brief trap入口函数 */ - .global trap_entry - .align 6 + .section .text.trap + .align 6// In CLIC mode, the trap entry must be 64bytes aligned + .global trap_entry + .weak trap_entry trap_entry: - pushREGFILE sp - + pushREGFILE sp //trap这里就直接使用当前栈,方便对当前位置进行异常分析, + //同时不担心(任务栈/中断栈/主栈)溢出,因为程序进入这里便不会返回了 portSAVE_CONTEXT_EXCP sp csrr a0, mcause mv a1, sp jal ulSynchTrap - mv sp,a0 + mv sp, a0 portRESTORE_CONTEXT_EXCP sp popREGFILE sp mret + /* -------------------------------------------------------------------------------------------------------- */ /** * @brife trq入口函数 @@ -434,3 +719,12 @@ xPortStartScheduler: */ vPortEndScheduler: j vPortEndScheduler + + +/* Default Handler for Exceptions / Interrupts */ +.global default_intexc_handler +.weak default_intexc_handler +Undef_Handler: +default_intexc_handler: +1: + j 1b diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S b/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S deleted file mode 100644 index e90ebaa2..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/Lib/intexc_gd32vf103.S +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Nuclei Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/****************************************************************************** - * \file intexc_gd32vf103.S - * \brief NMSIS Interrupt and Exception Handling Template File - * for Device gd32vf103 - * \version V1.00 - * \date 7 Jan 2020 - * - ******************************************************************************/ - -#include "riscv_encoding.h" - -/* Default Handler for Exceptions / Interrupts */ -.global default_intexc_handler -.weak default_intexc_handler -Undef_Handler: -default_intexc_handler: -1: - j 1b diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S deleted file mode 100644 index 67987d26..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/entry.S +++ /dev/null @@ -1,291 +0,0 @@ -#include "riscv_encoding.h" -#include "riscv_bits.h" -#include "n200_eclic.h" -#include "n200_timer.h" - -#define USE_MSP 1 //启用中断栈 - - -/** - * @brief 压栈通用寄存器 - * @param x 目标sp寄存器 - */ -.macro pushREGFILE x -#ifdef __riscv_flen - addi \x, \x, -REGBYTES * 68 //36+32 -#else - addi \x, \x, -REGBYTES * 36 -#endif - STORE x1, 1 * REGBYTES(\x) - STORE x2, 2 * REGBYTES(\x) - #STORE x3, 3 * REGBYTES(\x) - #STORE x4, 4 * REGBYTES(\x) - STORE x5, 5 * REGBYTES(\x) - STORE x6, 6 * REGBYTES(\x) - STORE x7, 7 * REGBYTES(\x) - STORE x8, 8 * REGBYTES(\x) - STORE x9, 9 * REGBYTES(\x) - STORE x10, 10 * REGBYTES(\x) - STORE x11, 11 * REGBYTES(\x) - STORE x12, 12 * REGBYTES(\x) - STORE x13, 13 * REGBYTES(\x) - STORE x14, 14 * REGBYTES(\x) - STORE x15, 15 * REGBYTES(\x) -#ifndef __riscv_32e - STORE x16, 16 * REGBYTES(\x) - STORE x17, 17 * REGBYTES(\x) - STORE x18, 18 * REGBYTES(\x) - STORE x19, 19 * REGBYTES(\x) - STORE x20, 20 * REGBYTES(\x) - STORE x21, 21 * REGBYTES(\x) - STORE x22, 22 * REGBYTES(\x) - STORE x23, 23 * REGBYTES(\x) - STORE x24, 24 * REGBYTES(\x) - STORE x25, 25 * REGBYTES(\x) - STORE x26, 26 * REGBYTES(\x) - STORE x27, 27 * REGBYTES(\x) - STORE x28, 28 * REGBYTES(\x) - STORE x29, 29 * REGBYTES(\x) - STORE x30, 30 * REGBYTES(\x) - STORE x31, 31 * REGBYTES(\x) -#endif -.endm - - -/** - * @brief 压栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) - * @param x 目标sp寄存器 - */ -.macro portSAVE_CONTEXT_EXCP x - csrr t0, CSR_MSTATUS - STORE t0, 32 * REGBYTES(\x) - csrr t0, CSR_MEPC - STORE t0, 33 * REGBYTES(\x) - csrr t0, CSR_MSUBM - STORE t0, 34 * REGBYTES(\x) - csrr t0, CSR_MCAUSE - STORE t0, 35 * REGBYTES(\x) -.endm - - -/** - * @brief 压栈浮点寄存器 - * @param x 目标sp寄存器 - */ -.macro popVFPREGFILE x - flw f0, 36 * REGBYTES(\x) - flw f1, 37 * REGBYTES(\x) - flw f2, 38 * REGBYTES(\x) - flw f3, 39 * REGBYTES(\x) - flw f4, 40 * REGBYTES(\x) - flw f5, 41 * REGBYTES(\x) - flw f6, 42 * REGBYTES(\x) - flw f7, 43 * REGBYTES(\x) - flw f8, 44 * REGBYTES(\x) - flw f9, 45 * REGBYTES(\x) - flw f10,46 * REGBYTES(\x) - flw f11, 47 * REGBYTES(\x) - flw f12, 48 * REGBYTES(\x) - flw f13, 49 * REGBYTES(\x) - flw f14, 50 * REGBYTES(\x) - flw f15, 51 * REGBYTES(\x) - flw f16, 52 * REGBYTES(\x) - flw f17, 53 * REGBYTES(\x) - flw f18, 54 * REGBYTES(\x) - flw f19, 55 * REGBYTES(\x) - flw f20, 56 * REGBYTES(\x) - flw f21, 57 * REGBYTES(\x) - flw f22, 58 * REGBYTES(\x) - flw f23, 59 * REGBYTES(\x) - flw f24, 60 * REGBYTES(\x) - flw f25, 61 * REGBYTES(\x) - flw f26, 62 * REGBYTES(\x) - flw f27, 63 * REGBYTES(\x) - flw f28, 64 * REGBYTES(\x) - flw f29, 65 * REGBYTES(\x) - flw f30, 66 * REGBYTES(\x) - flw f31, 67 * REGBYTES(\x) -.endm - - -/** - * @brief 出栈通用寄存器 - * @param x 目标sp寄存器 - */ -.macro popREGFILE x - LOAD x1, 1 * REGBYTES(\x) - #LOAD x2, 2 * REGBYTES(\x) - #LOAD x3, 3 * REGBYTES(\x) - #LOAD x4, 4 * REGBYTES(\x) - LOAD x5, 5 * REGBYTES(\x) - LOAD x6, 6 * REGBYTES(\x) - LOAD x7, 7 * REGBYTES(\x) - LOAD x8, 8 * REGBYTES(\x) - LOAD x9, 9 * REGBYTES(\x) - LOAD x10, 10 * REGBYTES(\x) - LOAD x11, 11 * REGBYTES(\x) - LOAD x12, 12 * REGBYTES(\x) - LOAD x13, 13 * REGBYTES(\x) - LOAD x14, 14 * REGBYTES(\x) - LOAD x15, 15 * REGBYTES(\x) -#ifndef __riscv_32e - LOAD x16, 16 * REGBYTES(\x) - LOAD x17, 17 * REGBYTES(\x) - LOAD x18, 18 * REGBYTES(\x) - LOAD x19, 19 * REGBYTES(\x) - LOAD x20, 20 * REGBYTES(\x) - LOAD x21, 21 * REGBYTES(\x) - LOAD x22, 22 * REGBYTES(\x) - LOAD x23, 23 * REGBYTES(\x) - LOAD x24, 24 * REGBYTES(\x) - LOAD x25, 25 * REGBYTES(\x) - LOAD x26, 26 * REGBYTES(\x) - LOAD x27, 27 * REGBYTES(\x) - LOAD x28, 28 * REGBYTES(\x) - LOAD x29, 29 * REGBYTES(\x) - LOAD x30, 30 * REGBYTES(\x) - LOAD x31, 31 * REGBYTES(\x) -#endif -#ifdef __riscv_flen - addi \x, \x, REGBYTES * 68 //36+32 -#else - addi \x, \x, REGBYTES * 36 -#endif -.endm - - -/** - * @brief 出栈csr寄存器(CSR_MSTATUS、CSR_MEPC、CSR_MSUBM、CSR_MCAUSE) - * @param x 目标sp寄存器 - */ -.macro portRESTORE_CONTEXT_EXCP x - LOAD t0, 35*REGBYTES(\x) - csrw CSR_MCAUSE, t0 - LOAD t0, 34*REGBYTES(\x) - csrw CSR_MSUBM, t0 - LOAD t0, 33*REGBYTES(\x) - csrw CSR_MEPC, t0 - LOAD t0, 32*REGBYTES(\x) - csrw CSR_MSTATUS, t0 -.endm - - -/** - * @brief 出栈浮点寄存器 - * @param x 目标sp寄存器 - */ -.macro pushVFPREGFILE x - fsw f0, 36 * REGBYTES(\x) - fsw f1, 37 * REGBYTES(\x) - fsw f2, 38 * REGBYTES(\x) - fsw f3, 39 * REGBYTES(\x) - fsw f4, 40 * REGBYTES(\x) - fsw f5, 41 * REGBYTES(\x) - fsw f6, 42 * REGBYTES(\x) - fsw f7, 43 * REGBYTES(\x) - fsw f8, 44 * REGBYTES(\x) - fsw f9, 45 * REGBYTES(\x) - fsw f10, 46 * REGBYTES(\x) - fsw f11, 47 * REGBYTES(\x) - fsw f12, 48 * REGBYTES(\x) - fsw f13, 49 * REGBYTES(\x) - fsw f14, 50 * REGBYTES(\x) - fsw f15, 51 * REGBYTES(\x) - fsw f16, 52 * REGBYTES(\x) - fsw f17, 53 * REGBYTES(\x) - fsw f18, 54 * REGBYTES(\x) - fsw f19, 55 * REGBYTES(\x) - fsw f20, 56 * REGBYTES(\x) - fsw f21, 57 * REGBYTES(\x) - fsw f22, 58 * REGBYTES(\x) - fsw f23, 59 * REGBYTES(\x) - fsw f24, 60 * REGBYTES(\x) - fsw f25, 61 * REGBYTES(\x) - fsw f26, 62 * REGBYTES(\x) - fsw f27, 63 * REGBYTES(\x) - fsw f28, 64 * REGBYTES(\x) - fsw f29, 65 * REGBYTES(\x) - fsw f30, 66 * REGBYTES(\x) - fsw f31, 67 * REGBYTES(\x) -.endm - - -/** - * @brief 清理fpu状态寄存器 - */ -.macro CONFIG_FS_CLEAN - li t0, (0x1 << 13) //配置FS为clean状态 - csrc mstatus, t0 - li t0, (0x1 << 14) - csrs mstatus, t0 -.endm - - -/* -------------------------------------------------------------------------------------------------------- */ -/** - * @brief trap入口函数 - */ - .section .text.trap - .align 6// In CLIC mode, the trap entry must be 64bytes aligned - .global trap_entry - .weak trap_entry -trap_entry: - pushREGFILE sp //trap这里就直接使用当前栈,方便对当前位置进行异常分析, - //同时不担心(任务栈/中断栈/主栈)溢出,因为程序进入这里便不会返回了 - portSAVE_CONTEXT_EXCP sp - - csrr a0, mcause - mv a1, sp - jal ulSynchTrap - mv sp, a0 - - portRESTORE_CONTEXT_EXCP sp - popREGFILE sp - mret - - -/* -------------------------------------------------------------------------------------------------------- */ -/** - * @brief irq入口函数 - */ - .section .text.irq - .align 2 - .global irq_entry - .weak irq_entry -irq_entry: -#if USE_MSP - csrrw sp, CSR_MSCRATCHCSWL, sp -#endif - pushREGFILE sp //保存通用寄存器 - portSAVE_CONTEXT_EXCP sp -#ifdef __riscv_flen - csrr t2, mstatus - li t0, (0x3 << 13) - and t1, t2, t0 - bne t1, t0, 1f //浮点寄存器状态为Dirty状态,则保存浮点寄存器, 否则不用保存 - pushVFPREGFILE sp -1: - CONFIG_FS_CLEAN -#endif - - csrrw ra, CSR_JALMNXTI, ra //跳转到中断向量表入口地址,中断处理返回时继续回到此处 - - csrc CSR_MSTATUS, MSTATUS_MIE //此时中断处理完毕,中断关闭,注意mret退出中断时将恢复从mpie恢复mie, - //因此在中断内部修改mie仅会保持中断mret前,退出中断将恢复为进中断前状态 -#ifdef __riscv_flen - csrr t2, mstatus - li t0, (0x3 << 13) - and t1, t2, t0 - bne t1, t0, 2f //浮点寄存器状态为Dirty状态,则恢复浮点寄存器, 否则不用恢复 - popVFPREGFILE sp -2: -#endif - portRESTORE_CONTEXT_EXCP sp -#ifdef __riscv_flen - CONFIG_FS_CLEAN -#endif - popREGFILE sp -#if USE_MSP - csrrw sp, CSR_MSCRATCHCSWL, sp -#endif - mret diff --git a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S b/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S deleted file mode 100644 index 0efa55b1..00000000 --- a/workspace/TS100/Core/BSP/Pine64/Vendor/RISCV/start.S +++ /dev/null @@ -1,289 +0,0 @@ -// See LICENSE for license details. - -#include "riscv_encoding.h" - - .section .init - - .weak eclic_msip_handler //弱定义函数,这些在编译为bin后可以看到将全部为0 - .weak eclic_mtip_handler - .weak eclic_bwei_handler - .weak eclic_pmovi_handler - .weak WWDGT_IRQHandler - .weak LVD_IRQHandler - .weak TAMPER_IRQHandler - .weak RTC_IRQHandler - .weak FMC_IRQHandler - .weak RCU_IRQHandler - .weak EXTI0_IRQHandler - .weak EXTI1_IRQHandler - .weak EXTI2_IRQHandler - .weak EXTI3_IRQHandler - .weak EXTI4_IRQHandler - .weak DMA0_Channel0_IRQHandler - .weak DMA0_Channel1_IRQHandler - .weak DMA0_Channel2_IRQHandler - .weak DMA0_Channel3_IRQHandler - .weak DMA0_Channel4_IRQHandler - .weak DMA0_Channel5_IRQHandler - .weak DMA0_Channel6_IRQHandler - .weak ADC0_1_IRQHandler - .weak CAN0_TX_IRQHandler - .weak CAN0_RX0_IRQHandler - .weak CAN0_RX1_IRQHandler - .weak CAN0_EWMC_IRQHandler - .weak EXTI5_9_IRQHandler - .weak TIMER0_BRK_IRQHandler - .weak TIMER0_UP_IRQHandler - .weak TIMER0_TRG_CMT_IRQHandler - .weak TIMER0_Channel_IRQHandler - .weak TIMER1_IRQHandler - .weak TIMER2_IRQHandler - .weak TIMER3_IRQHandler - .weak I2C0_EV_IRQHandler - .weak I2C0_ER_IRQHandler - .weak I2C1_EV_IRQHandler - .weak I2C1_ER_IRQHandler - .weak SPI0_IRQHandler - .weak SPI1_IRQHandler - .weak USART0_IRQHandler - .weak USART1_IRQHandler - .weak USART2_IRQHandler - .weak EXTI10_15_IRQHandler - .weak RTC_Alarm_IRQHandler - .weak USBFS_WKUP_IRQHandler - .weak EXMC_IRQHandler - .weak TIMER4_IRQHandler - .weak SPI2_IRQHandler - .weak UART3_IRQHandler - .weak UART4_IRQHandler - .weak TIMER5_IRQHandler - .weak TIMER6_IRQHandler - .weak DMA1_Channel0_IRQHandler - .weak DMA1_Channel1_IRQHandler - .weak DMA1_Channel2_IRQHandler - .weak DMA1_Channel3_IRQHandler - .weak DMA1_Channel4_IRQHandler - .weak CAN1_TX_IRQHandler - .weak CAN1_RX0_IRQHandler - .weak CAN1_RX1_IRQHandler - .weak CAN1_EWMC_IRQHandler - .weak USBFS_IRQHandler - -vector_base: //中断向量表 - j _start //第一条指令即跳转到_start处开始执行 - .align 2 - .word 0 - .word 0 - .word eclic_msip_handler - .word 0 - .word 0 - .word 0 - .word eclic_mtip_handler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word eclic_bwei_handler - .word eclic_pmovi_handler - .word WWDGT_IRQHandler - .word LVD_IRQHandler - .word TAMPER_IRQHandler - .word RTC_IRQHandler - .word FMC_IRQHandler - .word RCU_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA0_Channel0_IRQHandler - .word DMA0_Channel1_IRQHandler - .word DMA0_Channel2_IRQHandler - .word DMA0_Channel3_IRQHandler - .word DMA0_Channel4_IRQHandler - .word DMA0_Channel5_IRQHandler - .word DMA0_Channel6_IRQHandler - .word ADC0_1_IRQHandler - .word CAN0_TX_IRQHandler - .word CAN0_RX0_IRQHandler - .word CAN0_RX1_IRQHandler - .word CAN0_EWMC_IRQHandler - .word EXTI5_9_IRQHandler - .word TIMER0_BRK_IRQHandler - .word TIMER0_UP_IRQHandler - .word TIMER0_TRG_CMT_IRQHandler - .word TIMER0_Channel_IRQHandler - .word TIMER1_IRQHandler - .word TIMER2_IRQHandler - .word TIMER3_IRQHandler - .word I2C0_EV_IRQHandler - .word I2C0_ER_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word SPI0_IRQHandler - .word SPI1_IRQHandler - .word USART0_IRQHandler - .word USART1_IRQHandler - .word USART2_IRQHandler - .word EXTI10_15_IRQHandler - .word RTC_Alarm_IRQHandler - .word USBFS_WKUP_IRQHandler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word EXMC_IRQHandler - .word 0 - .word TIMER4_IRQHandler - .word SPI2_IRQHandler - .word UART3_IRQHandler - .word UART4_IRQHandler - .word TIMER5_IRQHandler - .word TIMER6_IRQHandler - .word DMA1_Channel0_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word 0 - .word 0 - .word CAN1_TX_IRQHandler - .word CAN1_RX0_IRQHandler - .word CAN1_RX1_IRQHandler - .word CAN1_EWMC_IRQHandler - .word USBFS_IRQHandler - - .globl _start - .type _start,@function - -_start: - - csrc CSR_MSTATUS, MSTATUS_MIE //CSR_MSTATUS &= ~0x8 mstatus[3]:0屏蔽全部中断 1不屏蔽全部中断 (当然这里全部中断是除过不可屏蔽中断) - /* Jump to logical address first to ensure correct operation of RAM region */ - la a0, _start //a0 = _start - li a1, 1 //a1 = 1 - slli a1, a1, 29 //a1 = 0x20000000 raw起始地址 - bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 - srli a1, a1, 2 //a1 = 0x08000000 flash起始地址 - bleu a1, a0, _start0800 //if( a1 <= a0 ) JUMP _start0800 - la a0, _start0800 //a0 = _start0800 - add a0, a0, a1 //a0 = a0+a1 - jr a0 //JUMP a0 - -_start0800: - - /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */ - li t0, 0x200 //t0 = 0x200 - csrs CSR_MMISC_CTL, t0 //mmisc_ctl |= 0x200 CSR_MMISC_CTL[9]:设置NMI的地址与mtvec相同且,mcause.EXCCODE = 0xfff - //cs开头的指令是特有的用来操作内核寄存器的的指令,内核寄存器是一组特有的12位地址 - - /* Intial the mtvt*/ - la t0, vector_base //t0 = vector_base 向量表地址 - csrw CSR_MTVT, t0 //mtvt = vector_base 中断向量表基地址 - - /* Intial the mtvt2 and enable it*/ - la t0, irq_entry //t0 = irq_entry irq_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S - csrw CSR_MTVT2, t0 //mtvt2 = irq_entry mtvt2[31:2]: 中断入口函数地址 - csrs CSR_MTVT2, 0x1 //mtvt2 |= 0x1 mtvt2[0]: 1配置mtvt2的配置有效,配0则为mtvec内地址 - - /* Intial the CSR MTVEC for the Trap ane NMI base addr*/ - la t0, trap_entry //t0 = trap_entry trap_entry定义在entry.S,有freertos操作系统情况下定义在portasm.S - csrw CSR_MTVEC, t0 //mtvec = trap_entry mtvec[31:6]:异常入口地址 - // mtvec[5:0]:0B00011 -- ECLIC中断模式 其他:默认模式 - // 这里配置为默认模式 - // trap_entry基本上可以理解为arm里的hard/mem/use/svc等fault了, - // 这里在移植freertos时就使用了 ecall 进入trap_entry里 相当于arm里的PendSVC - - /* OS启动前配置中断栈为FHEAP的end地址 */ - la t0, ucHeap - csrw CSR_MSCRATCH, t0 - -#ifdef __riscv_flen //浮点宏 - /* Enable FPU */ - li t0, MSTATUS_FS //t0 = 0x6000 - csrs mstatus, t0 //mstatus |= 0x6000 mstatus[14:13]:非零值启用浮点单元,配置为1或2会在第一次使用浮点单元时变为3,这里直接配置为3 - csrw fcsr, x0 //fcsr = x0 = 0 ??这里x0是否指的是zero通用寄存器值? 这个寄存器0-4位是浮点异常状态标志,5-7位是浮点舍入模式配置 -#endif - -.option push -.option norelax - la gp, __global_pointer$ //__global_pointer$定义在link连接脚本内,指向所有.data段后偏移0x800的地址,0x800为2K,其值源于下文解释 - //gp 意为global pointer (全局指针)寄存器是一个解决方案, - //为了以进一步优化存储器访问单个4KB区域内。 - //链接器使用__global_pointer$符号定义来比较内存地址,如果在范围内, - //则它将绝对/相对pc寻址替换为gp相对寻址,从而使代码更有效。这个过程通过-Wl,--no-relax选项使用。 - //这里.option norelax起到-Wl,--no-relax作用,就不需要在编译选项添加了 - //上文参考自:https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register - //要让 relaxing 优化起作用,编译时要加入 -msmall-data-limit=n 参数,有了这个参数, - //编译器会把内存空间小于 n 字节的静态变量放入 .sdata 或者 .sdata.* 节, - //然后链接器将这部分静态变量集中在 __global_pointer$ +/- 2K 的范围内。 - //上文参考自:https://blog.csdn.net/zoomdy/article/details/100703451 -.option pop - la sp, _sp //sp = 主栈栈顶地址 _sp定义在link连接脚本内 - - /* Load data section */ - la a0, _data_lma //a0 = data的Load Memory Address _data_lma定义在link连接脚本内 - la a1, _data //a1 = data的Run Memory Address _data定义在link连接脚本内 - la a2, _edata //a2 = data的Run Memory Address结束地址 _edata定义在link连接脚本内 - bgeu a1, a2, 2f //if( a1 >= a2 ) JUMP 2f 原则上不会出现_data地址大于_edata地址 - //如果出现了则直接跳转到 2f 即下一个2标签 -1: - lw t0, (a0) //t0 = _data_lma - sw t0, (a1) //*_data = t0 即 *_data_lma,按word写入 - addi a0, a0, 4 //a0 = a0 + 4 下一个ward - addi a1, a1, 4 //a1 = a1 + 4 - bltu a1, a2, 1b //if( a1 < a2 ) JUMP 1b 如果未到达_edata则跳转到 1b 即上一个1标签,这里会完成一个循环 -2: - /* Clear bss section */ - la a0, __bss_start //a0 = __bss_start 初值为0的全局变量段起始地址 __bss_start定义在link连接脚本内 - la a1, _end //a1 = _end 初值为0的全局变量段结束地址 _end定义在link连接脚本内 - bgeu a0, a1, 2f //if( a0 >= a1 ) JUMP 2f 原则上不会出现__bss_start地址大于_end地址 - //如果出现了则直接跳转到 2f 即下一个2标签 -1: - sw zero, (a0) //*__bss_start = zero = 0 bss段清除为0 - addi a0, a0, 4 //a0 = a0 + 4 下一个ward - bltu a0, a1, 1b //if( a0 < a1 ) JUMP 1b 如果未到达_end则跳转到 1b 即上一个1标签,这里会完成一个循环 - - //程序执行到这里全局变量就以及处理完毕了 -2: - /*enable mcycle_minstret*/ - csrci CSR_MCOUNTINHIBIT, 0x5 //CSR_MCOUNTINHIBIT &= ~0x5 这里清零了第0bit和第1bit,使能了mcycle计数和minstret计数 - //csrci这条指令处理立即数5bit,列如0x5只是0B00101,高位不处理 - /* - * Call vendor defined SystemInit to - * initialize the micro-controller system - */ - call SystemInit - /* Call global constructors */ - la a0, __libc_fini_array //a0 = __libc_fini_array newlib中atexit函数的参数 - call atexit //调用newlib中的 void atexit(void (*func)(void)) 函数 - //功能为注册main函数结束后调用的函数,这里是__libc_fini_array - call __libc_init_array //调用newlib中的 void __libc_init_array (void) 函数 - //这里要注意__libc_init_array函数会调用_init的钩子函数,用来做c环境初始化前的一些硬件初始化 - //列如时钟的配置等,这里_init定义在init.c - - //程序执行到这里C/C++环境就初始化完成了,可以进入main函数入口了 - /* argc = argv = 0 */ - li a0, 0 //a0 = 0 main函数参数argc = 0 - li a1, 0 //a1 = 0 main函数参数argv = 0 - call main //调用 int main(int argc,char **argv) 函数 - tail exit //main返回后调用newlib的exit函数, tail指令应该是不会返回的调用函数了 - -1: - j 1b //1b 即上一次1标签,即跳转到自己,程序到这里就死循环了,原则不会运行到这里 - - .global disable_mcycle_minstret -disable_mcycle_minstret: - csrsi CSR_MCOUNTINHIBIT, 0x5 //关闭了mcycle计数和minstret计数 - ret - - .global enable_mcycle_minstret -enable_mcycle_minstret: - csrci CSR_MCOUNTINHIBIT, 0x5 //使能了mcycle计数和minstret计数 - ret From d1758a882664af929b9717250a43778fd0d5efc6 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" Date: Sun, 8 Nov 2020 22:10:50 +1100 Subject: [PATCH 72/72] Update Makefile --- workspace/TS100/Makefile | 153 ++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/workspace/TS100/Makefile b/workspace/TS100/Makefile index 8ff8429a..177f8dec 100644 --- a/workspace/TS100/Makefile +++ b/workspace/TS100/Makefile @@ -15,6 +15,7 @@ HAL_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc HAL_LEGACY_INC_DIR = ./Core/BSP/Miniware/Vendor/STM32F1xx_HAL_Driver/Inc/Legacy FRTOS_CMIS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS FRTOS_INC_DIR = ./Middlewares/Third_Party/FreeRTOS/Source/include +MINIWARE_STARTUP_DIR = ./Startup DRIVER_INC_DIR =./Core/Drivers BSP_INC_DIR = ./Core/BSP THREADS_INC_DIR = ./Core/Threads @@ -39,15 +40,22 @@ DEVICE_INCLUDES = -I$(MINIWARE_INC_DIR) \ -I$(HAL_LEGACY_INC_DIR) \ -I$(INC_PD_DRIVERS_DIR) DEVICE_BSP_DIR = ./Core/BSP/Miniware -S_SRCS := ./Startup/startup_stm32f103t8ux.S +S_SRCS := $(shell find $(MINIWARE_STARTUP_DIR) -type f -name '*.S') LDSCRIPT=stm32f103.ld DEV_GLOBAL_DEFS= -D STM32F103T8Ux -D STM32F1 -D STM32 -D USE_HAL_DRIVER -D STM32F103xB -D USE_RTOS_SYSTICK -D GCC_ARMCM3 \ -D ARM_MATH_CM3 \ -D STM32F10X_MD DEV_LDFLAGS=-lm -Wl,--gc-sections -flto DEV_AFLAGS= -DEV_CFLAGS=-flto -DEV_CXXFLAGS=-flto +DEV_CFLAGS=-flto -D GCC_ARMCM3 \ + -D ARM_MATH_CM3 \ + -D STM32F10X_MD +DEV_CXXFLAGS=-flto -D GCC_ARMCM3 \ + -D ARM_MATH_CM3 \ + -D STM32F10X_MD +CPUFLAGS= -mcpu=cortex-m3 \ + -mthumb \ + -mfloat-abi=soft flash_size=64k bootldr_size=0x4000 endif @@ -62,15 +70,24 @@ DEVICE_INCLUDES = -I$(PINE_INC_DIR) \ -I$(INC_PD_DRIVERS_DIR) DEVICE_BSP_DIR = ./Core/BSP/Pine64 -S_SRCS := $(shell find $(PINE_INC_DIR) -type f -name '*.S') +S_SRCS := ./Core/BSP/Pine64/N200/portasm.S +$(info $(S_SRCS) ) ASM_INC = -I$(PINE_RISCV_INC_DIR) LDSCRIPT=GD32VF103xB.ld -DEV_LDFLAGS=-nostartfiles -Xlinker --gc-sections +flash_size=128k +bootldr_size=0x0 +# Flags +CPUFLAGS= -march=rv32imac \ + -mabi=ilp32 \ + -mtune=size \ + -mcmodel=medany \ + -DGD32VF103C_START \ + -DUSE_STDPERIPH_DRIVER +DEV_LDFLAGS= -nostartfiles -Xlinker --gc-sections +DEV_AFLAGS= -nostartfiles -ffreestanding DEV_GLOBAL_DEFS=-msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fabi-version=0 DEV_CFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" DEV_CXXFLAGS= -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -flash_size=128k -bootldr_size=0x0 endif INCLUDES = -I$(APP_INC_DIR) \ @@ -95,15 +112,14 @@ $(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.cpp') HEXFILE_DIR=Hexfile # temporary objects folder -OUTPUT_BASE_DIR=Objects -OUTPUT_DIR=$(OUTPUT_BASE_DIR)/$(model) +OUTPUT_DIR=Objects + # code optimisation ------------------------------------------------------------ -OPTIM_AS= -Wall OPTIM=-Os -finline-small-functions -findirect-inlining -fdiagnostics-color -ffunction-sections -fdata-sections # global defines --------------------------------------------------------------- -GLOBAL_DEFINES += -D LANG_$(lang) -D LANG -D MODEL_$(model) $(DEV_GLOBAL_DEFS) +GLOBAL_DEFINES += $(DEV_GLOBAL_DEFS) -D USE_RTOS_SYSTICK -D LANG_$(lang) -D LANG -D MODEL_$(model) -D VECT_TAB_OFFSET=$(bootldr_size)U ifdef swd_enable GLOBAL_DEFINES += -DSWD_ENABLE @@ -111,11 +127,13 @@ endif # Enable debug code generation DEBUG=-g3 - +# Without debug code +#DEBUG= + + # libs ------------------------------------------------------------------------- LIBS= - # ------------------------------------------------------------------------------ COMPILER=gcc # arm-none-eabi is the general ARM compiler, @@ -136,51 +154,26 @@ SIZE=$(COMPILER_PREFIX)-size SREC=srec_cat SREC_INFO=srec_info +# For the Pinecil, use GCC rather than as? (Copying other makefiles) ifeq ($(model),Pinecil) AS=$(COMPILER_PREFIX)-gcc -x assembler-with-cpp endif -# compiler flags --------------------------------------------------------------- -ifeq ($(model),$(filter $(model),TS100 TS80 TS80P)) -CPUFLAGS= -mthumb \ - -mcpu=cortex-m3 \ - -mfloat-abi=soft -endif -ifeq ($(model),Pinecil) -CPUFLAGS= -march=rv32imac \ - -mabi=ilp32 \ - -mtune=size \ - -mcmodel=medany \ - -DGD32VF103C_START \ - -DUSE_STDPERIPH_DRIVER -endif - - # linker flags ----------------------------------------------------------------- -LINKER_FLAGS=$(CPUFLAGS) \ - $(GLOBAL_DEFINES) \ - -D${COMPILER} \ - -MMD \ - -std=c++11 \ - $(OPTIM) \ - -ffreestanding \ - -fno-common \ - -fno-rtti \ - -fno-exceptions \ - -fno-non-call-exceptions \ - -fno-strict-aliasing \ - -fno-threadsafe-statics \ - -Wl,--wrap=malloc \ - -Wl,--wrap=free \ - -Wl,-Map=$(OUT_HEXFILE).map \ - -Wl,--undefined=vTaskSwitchContext \ - -T $(LDSCRIPT) \ - -Wl,--defsym=__FLASH_SIZE__=$(flash_size) \ - -Wl,--defsym=__BOOTLDR_SIZE__=$(bootldr_size) \ - --specs=nano.specs \ - $(DEV_LDFLAGS) \ - -o$(OUT_HEXFILE).elf \ +LINKER_FLAGS= -Wl,--gc-sections \ + -Wl,--wrap=malloc \ + -Wl,--wrap=free \ + -o$(OUT_HEXFILE).elf \ + -Wl,-Map=$(OUT_HEXFILE).map \ + -lm \ + -Wl,--undefined=vTaskSwitchContext \ + -Wl,--undefined=pxCurrentTCB \ + -Wl,--defsym=__FLASH_SIZE__=$(flash_size) \ + -Wl,--defsym=__BOOTLDR_SIZE__=$(bootldr_size) \ + $(DEV_LDFLAGS) \ + --specs=nano.specs +# compiler flags --------------------------------------------------------------- CHECKOPTIONS= -Wall \ @@ -210,13 +203,15 @@ CHECKOPTIONS= -Wall \ -Wshadow \ -Wno-unused-parameter \ -Wdouble-promotion \ - -Werror + -Werror + CHECKOPTIONS_C= -Wbad-function-cast -CXXFLAGS=$(CPUFLAGS) \ +CXXFLAGS=$(DEV_CXXFLAGS) \ + $(CPUFLAGS) \ $(DEBUG) \ $(INCLUDES) \ $(GLOBAL_DEFINES) \ @@ -225,39 +220,44 @@ CXXFLAGS=$(CPUFLAGS) \ $(CHECKOPTIONS) \ -std=c++11 \ $(OPTIM) \ - -ffreestanding \ -fno-common \ + -ffreestanding \ -fno-rtti \ -fno-exceptions \ -fno-non-call-exceptions \ -fno-use-cxa-atexit \ -fno-strict-aliasing \ + -fno-rtti \ + -fno-exceptions \ -fno-threadsafe-statics \ - $(DEV_CXXFLAGS) + -T$(LDSCRIPT) -CFLAGS=$(CPUFLAGS) \ +CFLAGS=$(DEV_CFLAGS) \ + $(CPUFLAGS) \ $(DEBUG) \ - $(INCLUDES) \ - $(CHECKOPTIONS_C) \ - $(GLOBAL_DEFINES) \ - -D${COMPILER} \ + $(INCLUDES) \ + $(CHECKOPTIONS_C) \ + $(GLOBAL_DEFINES) \ + -D${COMPILER} \ -MMD \ - -ffreestanding \ -std=gnu99 \ $(OPTIM) \ - $(DEV_CFLAGS) \ -fno-common \ - -c + -ffreestanding \ + -T$(LDSCRIPT) \ + -c -AFLAGS=$(CPUFLAGS) \ - $(OPTIM_AS) \ - $(DEBUG) \ - $(ASM_INC) \ - $(DEV_AFLAGS) +AFLAGS= $(CPUFLAGS) \ + $(DEV_AFLAGS) \ + $(DEBUG) \ + $(ASM_INC) \ + $(INCLUDES) +CFLAGS += -ffunction-sections -fdata-sections +CXXFLAGS += -ffunction-sections -fdata-sections @@ -284,13 +284,14 @@ all: $(OUT_HEXFILE).hex $(OUT_HEXFILE).bin $(OBJCOPY) $^ -O ihex $@ %.bin : %.elf + $(SIZE) $^ $(OBJCOPY) $^ -O binary $@ -$(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) +$(OUT_HEXFILE).elf : $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) Makefile $(LDSCRIPT) @test -d $(@D) || mkdir -p $(@D) @echo Linking $(OUTPUT_EXE).elf - @echo $(CPP) $(LINKER_FLAGS) - @$(CPP) $(LINKER_FLAGS) $(OUT_OBJS) $(OUT_OBJS_CPP) $(OUT_OBJS_S) $(LIBS) + @echo $(LINKER_FLAGS) + @$(CPP) $(CXXFLAGS) $(OUT_OBJS_S) $(OUT_OBJS) $(OUT_OBJS_CPP) $(LIBS) $(LINKER_FLAGS) $(OUT_OBJS): $(OUTPUT_DIR)/%.o : %.c Makefile @test -d $(@D) || mkdir -p $(@D) @@ -303,21 +304,21 @@ $(OUT_OBJS_CPP): $(OUTPUT_DIR)/%.o : %.cpp Makefile @echo Compiling ${<} @$(CPP) -c $(CXXFLAGS) $< -o $@ @$(OBJDUMP) -d -S $@ > $@.lst - + $(OUT_OBJS_S): $(OUTPUT_DIR)/%.o: %.S Makefile @test -d $(@D) || mkdir -p $(@D) @echo 'Building file: $<' @echo 'Invoking: MCU GCC Assembler' - @$(AS) -c $(AFLAGS) $< -o $@ + @echo @$(AS) -c $(AFLAGS) $< -o $@ + @$(AS) -c $(AFLAGS) $< -o $@ @echo 'Finished building: $<' @echo ' ' clean : - rm -Rf $(OUTPUT_BASE_DIR) + rm -Rf $(OUTPUT_DIR) rm -Rf $(HEXFILE_DIR) - # pull in dependency info for *existing* .o files -include $(OUT_OBJS:.o=.d) -include $(OUT_OBJS_CPP:.o=.d)