From a32d749c601c66210f564e732623eb56e5bd0a8d Mon Sep 17 00:00:00 2001 From: KLASSENTS Date: Tue, 4 Feb 2025 11:47:20 +0700 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B5=D1=89=D0=B5=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=BF=D1=80=D0=B5=D1=80=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=20=D0=B5=D1=89=D0=B5=20=D0=B4=D0=B2=D1=83=D1=85?= =?UTF-8?q?=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=BE=D0=B2=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=A8=D0=98=D0=9C=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BB?= =?UTF-8?q?=D0=B0=D1=82=D1=8B=20Elbear.=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=84=D0=BB=D0=B0=D0=B3=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86=D0=B8=D0=B8,?= =?UTF-8?q?=20=D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D1=8B=20=D0=B2=20ArduinoIDE=20v1.8.19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- boards.txt | 4 + cores/arduino/Tone.cpp | 2 +- cores/arduino/WInterrupts.c | 9 ++ cores/arduino/WInterrupts.h | 2 + cores/arduino/board.cpp | 8 +- cores/arduino/board.h | 3 +- cores/arduino/main.cpp | 1 - .../peripherals/Include/mik32_hal_timer16.h | 4 +- .../hal/peripherals/Include/mik32_hal_tsens.h | 4 +- .../hal/peripherals/Include/mik32_hal_wdt.h | 2 +- .../hal/peripherals/Source/mik32_hal_wdt.c | 68 +++++++++---- cores/arduino/wiring_LL.h | 8 +- docs/Elbear_description.md | 22 ++++- .../SoftwareSerial/src/SoftwareSerial.cpp | 2 + platform.txt | 3 + variants/elbear_ace_uno/pins_arduino.h | 2 +- variants/elbear_ace_uno/variant.c | 29 ++---- variants/start/pins_arduino.h | 96 ++++++++++--------- variants/start/variant.c | 19 +--- 19 files changed, 172 insertions(+), 116 deletions(-) diff --git a/boards.txt b/boards.txt index 0e5ff7b..407bcde 100644 --- a/boards.txt +++ b/boards.txt @@ -16,6 +16,7 @@ aceUno8Mb.bootloader.tool=mik32_upload aceUno8Mb.bootloader.tool.default=mik32_upload aceUno8Mb.bootloader.file=ace-uno/bootloader.hex aceUno8Mb.bootloader.interface=ftdi/mikron-link.cfg +aceUno8Mb.bootloader.params.verbose= # build options aceUno8Mb.build.mcu=MIK32_Amur @@ -42,6 +43,7 @@ aceUno16Mb.bootloader.tool=mik32_upload aceUno16Mb.bootloader.tool.default=mik32_upload aceUno16Mb.bootloader.file=ace-uno/bootloader.hex aceUno16Mb.bootloader.interface=ftdi/mikron-link.cfg +aceUno16Mb.bootloader.params.verbose= # build options aceUno16Mb.build.mcu=MIK32_Amur @@ -68,6 +70,7 @@ aceUno32Mb.bootloader.tool=mik32_upload aceUno32Mb.bootloader.tool.default=mik32_upload aceUno32Mb.bootloader.file=ace-uno/bootloader.hex aceUno32Mb.bootloader.interface=ftdi/mikron-link.cfg +aceUno32Mb.bootloader.params.verbose= # build options aceUno32Mb.build.mcu=MIK32_Amur @@ -94,6 +97,7 @@ start-mik32-v1.bootloader.tool=mik32_upload start-mik32-v1.bootloader.tool.default=mik32_upload start-mik32-v1.bootloader.file=start-mik32/bootloader.hex start-mik32-v1.bootloader.interface=start-link.cfg +start-mik32-v1.bootloader.params.verbose= # build options start-mik32-v1.build.mcu=MIK32_Amur diff --git a/cores/arduino/Tone.cpp b/cores/arduino/Tone.cpp index 8dba4e1..6c9f04d 100644 --- a/cores/arduino/Tone.cpp +++ b/cores/arduino/Tone.cpp @@ -45,7 +45,7 @@ static void Timer16_Init(uint8_t prescaler) htimer16_1.Trigger.TimeOut = TIMER16_TIMEOUT_DISABLE; htimer16_1.Filter.ExternalClock = TIMER16_FILTER_NONE; htimer16_1.Filter.Trigger = TIMER16_FILTER_NONE; - htimer16_1.Waveform.Enable = TIMER16_WAVEFORM_GENERATION_ENABLE; + htimer16_1.Waveform.Enable = TIMER16_WAVEFORM_GENERATION_DISABLE; htimer16_1.Waveform.Polarity = TIMER16_WAVEFORM_POLARITY_NONINVERTED; htimer16_1.EncoderMode = TIMER16_ENCODER_DISABLE; HAL_Timer16_Init(&htimer16_1); diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 6b4783f..0f63b22 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -6,6 +6,9 @@ #include "WInterrupts.h" #include "wiring_LL.h" +// interrupts are enabled by default after setup() +static bool intIsEnabled = true; + typedef void (*voidFuncPtr)(void); // empty irq handler @@ -18,14 +21,20 @@ static void nothing(void) void interrupts(void) { GLOBAL_IRQ_ENABLE(); + intIsEnabled = true; } // disable global interrupts void noInterrupts(void) { GLOBAL_IRQ_DISABLE(); + intIsEnabled = false; } +bool isInterruptsEnabled(void) +{ + return intIsEnabled; +} // we can provide no more than 8 interrupts on gpio at the same time static volatile voidFuncPtr intFunc[EXTERNAL_INTERRUPTS_QTY] = { diff --git a/cores/arduino/WInterrupts.h b/cores/arduino/WInterrupts.h index 4bab44e..50b3b9b 100644 --- a/cores/arduino/WInterrupts.h +++ b/cores/arduino/WInterrupts.h @@ -6,10 +6,12 @@ extern "C" { #endif #include +#include "stdbool.h" // enable/disable interrupts void interrupts(void); void noInterrupts(void); +bool isInterruptsEnabled(void); // attach/detach interrupt to pin void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode); diff --git a/cores/arduino/board.cpp b/cores/arduino/board.cpp index 876cb87..591676c 100644 --- a/cores/arduino/board.cpp +++ b/cores/arduino/board.cpp @@ -4,8 +4,8 @@ #include "Arduino.h" // --------------------- init --------------------- // -// called before setup() -void pre_init(void) +// called from crt0.S before constructors initialization +extern "C" void SystemInit(void) { // set irq vector to ram region write_csr(mtvec, 0x02000000); @@ -25,8 +25,8 @@ void pre_init(void) // called after setup() void post_init(void) { - // enable global interrupts by default - interrupts(); + if(isInterruptsEnabled()) // if user has called noInterrupts() in setup(), this value is false + interrupts(); // enable global interrupts } // --------------------- other --------------------- // diff --git a/cores/arduino/board.h b/cores/arduino/board.h index 61599a0..ac36c47 100644 --- a/cores/arduino/board.h +++ b/cores/arduino/board.h @@ -5,8 +5,7 @@ extern volatile bool use_error_messages; #define DISABLE_ERROR_MESSAGES() (use_error_messages = false) #define ENABLE_ERROR_MESSAGES() (use_error_messages = true) -// functions for init called before and after setup() -void pre_init(void) ; +// function for init called after setup() void post_init(void); #endif /* _BOARD_H_ */ diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index b85dab3..6535748 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -4,7 +4,6 @@ int main() { - pre_init(); setup(); post_init(); diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_timer16.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_timer16.h index 60dcc2c..5798938 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_timer16.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_timer16.h @@ -144,8 +144,8 @@ typedef enum __HAL_Timer16_EncoderTypeDef */ typedef enum __HAL_Timer16_WaveformGenTypeDef { - TIMER16_WAVEFORM_GENERATION_ENABLE = 0, /**< Выключить генерацию волновой формы. */ - TIMER16_WAVEFORM_GENERATION_DISABLE = 1 /**< Включить генерацию волновой формы. */ + TIMER16_WAVEFORM_GENERATION_ENABLE = 0, /**< Включить генерацию волновой формы. */ + TIMER16_WAVEFORM_GENERATION_DISABLE = 1 /**< Выключить генерацию волновой формы. */ } HAL_Timer16_WaveformGenTypeDef; /** diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_tsens.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_tsens.h index 661c10b..b7a3814 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_tsens.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_tsens.h @@ -105,7 +105,7 @@ typedef enum __HAL_TSENS_ClockTypeDef /** * @brief Определение структуры TSENS Handle. */ -typedef struct __SPI_HandleTypeDef +typedef struct __TSENS_HandleTypeDef { ANALOG_REG_TypeDef *Instance; /**< Адрес регистров блока управления аналоговой подсистемой. */ @@ -119,7 +119,7 @@ typedef struct __SPI_HandleTypeDef /** * @brief Возвращаемая структура для функции @ref HAL_TSENS_SingleStart. */ -typedef struct __WDT_ClockTypeDef +typedef struct __TSENS_ValueTypeDef { HAL_StatusTypeDef statusHAL; /**< Статус HAL. */ diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h index 9708e0f..a89626a 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_wdt.h @@ -105,7 +105,7 @@ typedef struct __WDT_ClockTypeDef } WDT_ClockTypeDef; -void HAL_RTC_MspInit(WDT_HandleTypeDef* hwdt); +void HAL_WDT_MspInit(WDT_HandleTypeDef* hwdt); HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout); HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout); HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout); diff --git a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c index 7c39985..9b12a7a 100644 --- a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c +++ b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_wdt.c @@ -3,14 +3,56 @@ uint16_t TimeOut = 20; uint16_t WDT_prescale[] = {1, 2, 4, 16, 64, 256, 1024, 4096}; +/** + * @brief Запись слова в регистр CON (конфигурация WDT) + * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит + * информацию о конфигурации для модуля WDT. + * @param conValue 32-х битное слово + */ +static void __attribute__( ( noinline, section(".ram_text") ) ) HAL_WDT_Write_Word_To_CON(WDT_HandleTypeDef* hwdt, uint32_t conValue) +{ + //Если позволить компилятору inlining, станет невозможно выделить функцию в отдельную секцию. + intptr_t ptr = (intptr_t)(hwdt->Instance); + /** + * Попытки избежать использования отдельной переменной-указателя, такие как: + * "sb a0,0x9C(%a0)\n\t" + * : "m" (*(hwdt->Instance)) + * не работают из-за бага GCC (internal compiler error <...> riscv_print_operand_address) + * */ + asm volatile( + "li a0,0x1E\n\t" //Store unlock byte somewhere + "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register + "sw %1,0x84(%0)\n\t" //Write payload + : + : "r" (ptr), "r" (conValue) + : "a0" + ); +} +/** + * @brief Запись байта в регистр KEY (пуск/остановка WDT) + * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит + * информацию о конфигурации для модуля WDT. + * @param key байт для записи ( @ref WDT_KEY_START или @ref WDT_KEY_STOP ) + */ +static void __attribute__( ( noinline, section(".ram_text") ) ) HAL_WDT_Write_Byte_To_KEY(WDT_HandleTypeDef* hwdt, uint8_t key) +{ + intptr_t ptr = (intptr_t)(hwdt->Instance); + asm volatile( + "li a0,0x1E\n\t" //Store unlock byte somewhere + "sb a0,0x9C(%0)\n\t" //Write UNLOCK byte into WDT KEY register + "sb %1,0x9C(%0)\n\t" //Write payload + : + : "r" (ptr), "r" (key) + : "a0" + ); +} + /** * @brief Инициализация WDT MSP. * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит * информацию о конфигурации для модуля WDT. - * - * информацию о конфигурации для модуля WDT. */ -__attribute__((weak)) void HAL_RTC_MspInit(WDT_HandleTypeDef *hwdt) +__attribute__((weak)) void HAL_WDT_MspInit(WDT_HandleTypeDef *hwdt) { __HAL_PCC_WDT_CLK_ENABLE(); } @@ -82,7 +124,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) return HAL_ERROR; } - HAL_RTC_MspInit(hwdt); + HAL_WDT_MspInit(hwdt); if (HAL_WDT_Stop(hwdt, timeout) != HAL_OK) @@ -100,8 +142,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) } uint32_t conValue = (wdtClock.divIndex << WDT_CON_PRESCALE_S) | WDT_CON_PRELOAD(wdtClock.tick); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); return HAL_OK; } @@ -115,8 +156,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_START; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START); while (timeout--) { @@ -139,8 +179,7 @@ HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_START; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START); while (timeout--) { @@ -162,8 +201,7 @@ HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout) */ HAL_StatusTypeDef HAL_WDT_Stop(WDT_HandleTypeDef *hwdt, uint32_t timeout) { - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->KEY = WDT_KEY_STOP; + HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_STOP); while (timeout--) { @@ -185,8 +223,7 @@ HAL_StatusTypeDef HAL_WDT_Stop(WDT_HandleTypeDef *hwdt, uint32_t timeout) void HAL_WDT_SetPrescale(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale prescale) { uint32_t conValue = (hwdt->Instance->CON & (~WDT_CON_PRESCALE_M)) | ((prescale << WDT_CON_PRESCALE_S) & WDT_CON_PRESCALE_M); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); } /** @@ -198,6 +235,5 @@ void HAL_WDT_SetPrescale(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale prescale) void HAL_WDT_SetPreload(WDT_HandleTypeDef *hwdt, HAL_WDT_Prescale preload) { uint32_t conValue = (hwdt->Instance->CON & (~WDT_CON_PRELOAD_M)) | WDT_CON_PRELOAD(preload); - hwdt->Instance->KEY = WDT_KEY_UNLOCK; - hwdt->Instance->CON = conValue; + HAL_WDT_Write_Word_To_CON(hwdt, conValue); } \ No newline at end of file diff --git a/cores/arduino/wiring_LL.h b/cores/arduino/wiring_LL.h index 4e2723e..687371c 100644 --- a/cores/arduino/wiring_LL.h +++ b/cores/arduino/wiring_LL.h @@ -5,6 +5,7 @@ #include "mik32_hal_gpio.h" #include "mik32_hal_scr1_timer.h" #include "mik32_hal_timer16.h" +#include "pad_config.h" // ----------------- COMMON ----------------- // // convert pin mask from HAL_PinsTypeDef to pin number @@ -32,6 +33,7 @@ #define TIM16_DISABLE_INT_BY_MASK(htim16,intMask) (htim16.Instance->IER &= ~(intMask)) // ----------------- EPIC ----------------- // +#define EPIC_LEVEL_SET_BY_MASK(mask) (EPIC->MASK_LEVEL_SET |= mask) #define EPIC_LEVEL_CLEAR_BY_MASK(mask) (EPIC->MASK_LEVEL_CLEAR |= mask) #define EPIC_CLEAR_ALL() (EPIC->CLEAR = 0xFFFFFFFF) @@ -41,6 +43,8 @@ set_csr(mie, MIE_MEIE) // ----------------- GPIO ----------------- // +#define GPIO_INPUT_MODE_PIN(GPIO_x, pinMask) ((GPIO_x)->DIRECTION_IN = (pinMask)) +#define GPIO_OUTPUT_MODE_PIN(GPIO_x, pinMask) ((GPIO_x)->DIRECTION_OUT = (pinMask)) #define GPIO_SET_PIN(GPIO_x, pinMask) ((GPIO_x)->SET = (pinMask)) #define GPIO_CLEAR_PIN(GPIO_x, pinMask) ((GPIO_x)->CLEAR = (pinMask)) #define GPIO_TOGGLE_PIN(GPIO_x, pinMask) ((GPIO_x)->OUTPUT_ ^= pinMask) @@ -58,8 +62,6 @@ // return config of pin with pinNumber(0...16) in portReg (config, pupd, ds for ports 0...2) #define PIN_GET_PAD_CONFIG(portReg, pinNumber) ((PAD_CONFIG->portReg >> (pinNumber<<1)) & 0b11) #define PIN_SET_PAD_CONFIG(portReg, pinNumber, value) (PAD_CONFIG->portReg = (PAD_CONFIG->portReg & (~PAD_CONFIG_PIN_M(pinNumber))) \ - | PAD_CONFIG_PIN(pinNumber, value)) - - + | PAD_CONFIG_PIN(pinNumber, value)) #endif /* _WIRING_LL_H_ */ \ No newline at end of file diff --git a/docs/Elbear_description.md b/docs/Elbear_description.md index 150508e..c8be9f2 100644 --- a/docs/Elbear_description.md +++ b/docs/Elbear_description.md @@ -4,11 +4,24 @@ ![Pinout](pinout.PNG) ### Цифровые выводы На плате Elbear Ace-Uno доступны встроенные светодиод и кнопка. Для их использования необходимо воспользоваться макросами `LED_BUILTIN` и `BTN_BUILTIN`, передавая их в качестве аргументов функции вместо номера цифрового вывода. Макросу `LED_BUILTIN` соответствует номер вывода D22, а макросу `BTN_BUILTIN` - D23. +### Аналоговые выводы +Выводы A0...A5 на плате могут использоваться как в аналоговом, так и в цифровом режиме. +Для использования вывода в качестве аналогового необходимо перевести соответствующий DIP-переключатель, расположенный рядом с аналоговыми выводами, в положение OFF. В этом режиме внешнее напряжение, подаваемое на вывод, будет понижаться резистивным делителем перед подачей на микроконтроллер. +Для использования вывода в качестве цифрового нужно перевести переключатель в положение ON. В этом случае напряжение с вывода платы передается на микроконтроллер без изменений. +Таблица соответствия выводов платы и номера DIP-переключателя представлена ниже. Переключатель 5 относится сразу к двум аналоговым выводам - А4, А5. +|Вывод|Номер переключателя| +|---------|---------| +|А0|1| +|А1|2| +|А2|3| +|А3|4| +|А4|5| +|А5|5| #### ШИМ -На плате Elbear Ace-Uno доступны следующие выводы для формирования ШИМ-сигнала: D3, D5, D6, D9, D10, D11. Генерация сигнала осуществляется с помощью 32-битного таймера. Выводы D3, D5, D6, D9 подключены к таймеру 1, выводы D10, D11 подключены к таймеру 2. Выводы, подключенные к одному и тому же таймеру, выдают ШИМ-сигнал одинаковой частоты. +На плате Elbear Ace-Uno доступно 8 выводов для формирования ШИМ-сигнала: D3, D5, D6, D9...D13. Генерация сигнала осуществляется с помощью 32-битного таймера. Выводы D3, D5, D6, D9 подключены к таймеру 1, выводы D10...D13 подключены к таймеру 2. Выводы, подключенные к одному и тому же таймеру, выдают ШИМ-сигнал одинаковой частоты. Цифровой вывод D10 не может быть использован для генерации ШИМ, если одновременно активен интерфейс SPI. Это ограничение связано с особенностями работы микроконтроллера. Ограничение не распространяется на использование D10 в качестве цифрового вывода при активном SPI. ### Прерывания -На плате Elbear Ace-Uno доступно 7 прерываний, настраиваемых функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`: +На плате Elbear Ace-Uno доступно 8 прерываний, настраиваемых функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`: |Цифровой вывод|Номер прерывания| |---------|---------| @@ -18,7 +31,10 @@ |D5|3| |D8|4| |D9|5| -|`BTN_BUILTIN`|6| +|A1|6| +|`BTN_BUILTIN`|7| + +При использовании аналогового вывода A1 для работы с прерываниями необходимо предварительно перевести вывод в режим цифрового. Для этого нужно перевести DIP-переключатель номер 2 в положение ON. ### Serial Интерфейс UART0 доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`. diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 0f312a2..bf7dacf 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -205,6 +205,8 @@ void SoftwareSerial::setRX(uint8_t rx) PIN_SET_PAD_CONFIG(PORT_0_PUPD, pinNumber, HAL_GPIO_PULL_UP); else if (((GPIO_TypeDef*)_receivePortRegister) == GPIO_1) PIN_SET_PAD_CONFIG(PORT_1_PUPD, pinNumber, HAL_GPIO_PULL_UP); + else if (((GPIO_TypeDef*)_receivePortRegister) == GPIO_2) + PIN_SET_PAD_CONFIG(PORT_2_PUPD, pinNumber, HAL_GPIO_PULL_UP); } // turn off int line for while (it turning on in attachInterrupt()) GPIO_IRQ_LINE_DISABLE(_int_maskLine); diff --git a/platform.txt b/platform.txt index d356c9b..8eb738f 100644 --- a/platform.txt +++ b/platform.txt @@ -65,6 +65,7 @@ tools.elbear_uploader.cmd.windows=elbear_uploader.exe tools.elbear_uploader.path={runtime.tools.elbear_uploader.path} tools.elbear_uploader.upload.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --com={serial.port} --baudrate={upload.speed} tools.elbear_uploader.upload.params.quiet= +tools.elbear_uploader.upload.params.verbose= # Set elbear_uploader as programmer programmers.elbear_uploader.name=Elbear Uploader @@ -80,6 +81,7 @@ tools.mik32_upload.path={runtime.tools.mik32_upload.path} # Bootloader can not be burnt if there is no erase command, even if it's empty tools.mik32_upload.erase.pattern= tools.mik32_upload.erase.params.quiet= +tools.mik32_upload.erase.params.verbose= # For Tools > Burn Bootloader tools.mik32_upload.bootloader.pattern={path}/{cmd} {runtime.platform.path}/bootloaders/{bootloader.file} --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/{bootloader.interface} --openocd-target={path}/openocd-scripts/target/mik32.cfg @@ -88,3 +90,4 @@ tools.mik32_upload.bootloader.params.quiet= # For Sketch > Upload Using Programmer tools.mik32_upload.program.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/{bootloader.interface} --openocd-target={path}/openocd-scripts/target/mik32.cfg tools.mik32_upload.program.params.quiet= +tools.mik32_upload.program.params.verbose= diff --git a/variants/elbear_ace_uno/pins_arduino.h b/variants/elbear_ace_uno/pins_arduino.h index 9e02c16..bdafdd1 100644 --- a/variants/elbear_ace_uno/pins_arduino.h +++ b/variants/elbear_ace_uno/pins_arduino.h @@ -111,7 +111,7 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define WIRE_FREQ_1000K 1000000 // interrupts -#define EXTERNAL_INTERRUPTS_QTY 7 +#define EXTERNAL_INTERRUPTS_QTY 8 extern uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3]; // determines the board pin number by interrupt number #define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0]) diff --git a/variants/elbear_ace_uno/variant.c b/variants/elbear_ace_uno/variant.c index 1d5e306..86b7305 100644 --- a/variants/elbear_ace_uno/variant.c +++ b/variants/elbear_ace_uno/variant.c @@ -153,25 +153,14 @@ uint32_t analogInputToChannelNumber(uint32_t PinNumber) // ---------------------- PWM ---------------------- // // use only if digitalPinHasPWM() == true -#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin==10)||(pin==11)) ? 1:0) -// use only if digitalPinHasPWM() == true -static inline uint8_t pwmPinToGpioPinShift(uint8_t digitalPin) -{ - if (digitalPin == 3) - return 0; - else if ((digitalPin == 5) || (digitalPin == 11)) - return 1; - else if (digitalPin == 6) - return 2; - else // pins 9 10 - return 3; -} +#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin==10)||(pin==11)||(pin==12)||(pin==13)) ? 1:0) + // use only if digitalPinHasPWM() == true // return true if digitalPin configured as pwm bool digitalPinPwmIsOn(uint8_t digitalPin) { uint8_t config = 0; - uint8_t pinShift = pwmPinToGpioPinShift(digitalPin); + uint8_t pinShift = PIN_MASK_TO_PIN_NUMBER(digitalPinToBitMask(digitalPin)); if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0) config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift); @@ -190,7 +179,7 @@ bool digitalPinHasPWM(uint8_t p) // if spi is in use D10 cannot work as pwm if (spiNssPinIsBlocked && (p == 10)) ret = false; - else if ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11) + else if (p == 3 || p == 5 || p == 6 || (p >= 9 && p <= 13)) ret = true; return ret; } @@ -204,7 +193,7 @@ TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber) if (digPinNumber == 3 || digPinNumber == 5 || digPinNumber == 6 || digPinNumber == 9) timerNum = TIMER32_1; // timer 2 - else if (digPinNumber == 10 || digPinNumber == 11) + else if (digPinNumber == 10 || digPinNumber == 11 || digPinNumber == 12 || digPinNumber == 13) timerNum = TIMER32_2; return timerNum; @@ -214,9 +203,9 @@ TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber) HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber) { HAL_TIMER32_CHANNEL_IndexTypeDef channel = 0; - if (digPinNumber == 3) channel = TIMER32_CHANNEL_0; + if (digPinNumber == 3 || digPinNumber == 12) channel = TIMER32_CHANNEL_0; else if (digPinNumber == 5 || digPinNumber == 11) channel = TIMER32_CHANNEL_1; - else if (digPinNumber == 6) channel = TIMER32_CHANNEL_2; + else if (digPinNumber == 6 || digPinNumber == 13) channel = TIMER32_CHANNEL_2; else if (digPinNumber == 9 || digPinNumber == 10) channel = TIMER32_CHANNEL_3; return channel; } @@ -232,7 +221,9 @@ uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3] = { 5, GPIO_LINE_1, GPIO_MUX_LINE_1_PORT0_1}, // INT3 { 8, GPIO_LINE_5, GPIO_MUX_LINE_5_PORT1_9}, // INT4 { 9, GPIO_LINE_3, GPIO_MUX_LINE_3_PORT0_3}, // INT5 - {BTN_BUILTIN, GPIO_LINE_6, GPIO_MUX_LINE_6_PORT2_6}, // INT6 (button) + { A1, GPIO_LINE_7, GPIO_MUX_LINE_7_PORT1_7}, // INT6 + {BTN_BUILTIN, GPIO_LINE_6, GPIO_MUX_LINE_6_PORT2_6}, // INT7 (button) + }; int8_t digitalPinToGpioIntMux(uint8_t digPinNumber) diff --git a/variants/start/pins_arduino.h b/variants/start/pins_arduino.h index 4669d9f..50d45fc 100644 --- a/variants/start/pins_arduino.h +++ b/variants/start/pins_arduino.h @@ -32,49 +32,51 @@ extern "C" { #include "mik32_hal_gpio.h" #include "mik32_hal_timer32.h" -#define PORT_PIN_MASK 0xF - // digital pins -#define P0_0 0 -#define P0_1 1 -#define P0_2 2 -#define P0_3 3 -#define P0_4 4 -#define P0_5 5 -#define P0_6 6 -#define P0_7 7 -#define P0_8 8 -#define P0_9 9 -#define P0_10 10 -#define P0_11 11 -#define P0_12 12 -#define P0_13 13 -#define P0_14 14 -#define P0_15 15 -#define P1_0 16 -#define P1_1 17 -#define P1_2 18 -#define P1_3 19 -#define P1_4 20 -#define P1_5 21 -#define P1_6 22 -#define P1_7 23 -#define P1_8 24 -#define P1_9 25 -#define P1_10 26 -#define P1_11 27 -#define P1_12 28 -#define P1_13 29 -#define P1_14 30 -#define P1_15 31 -#define P2_0 32 -#define P2_1 33 -#define P2_2 34 -#define P2_3 35 -#define P2_4 36 -#define P2_5 37 -#define P2_6 38 -#define P2_7 39 +typedef enum +{ + P0_0 = 0, // 0 + P0_1, // 1 + P0_2, // 2 + P0_3, // 3 + P0_4, // 4 + P0_5, // 5 + P0_6, // 6 + P0_7, // 7 + P0_8, // 8 + P0_9, // 9 + P0_10, // 10 + P0_11, // 11 + P0_12, // 12 + P0_13, // 13 + P0_14, // 14 + P0_15, // 15 + P1_0, // 16 + P1_1, // 17 + P1_2, // 18 + P1_3, // 19 + P1_4, // 20 + P1_5, // 21 + P1_6, // 22 + P1_7, // 23 + P1_8, // 24 + P1_9, // 25 + P1_10, // 26 + P1_11, // 27 + P1_12, // 28 + P1_13, // 29 + P1_14, // 30 + P1_15, // 31 + P2_0, // 32 + P2_1, // 33 + P2_2, // 34 + P2_3, // 35 + P2_4, // 36 + P2_5, // 37 + P2_6, // 38 + P2_7, // 39 + PINS_COMMON_QTY, // 40 +} DigitalPinsTypeDef; // analog pins #define PIN_A0 (P1_5) @@ -105,9 +107,15 @@ static const uint8_t A7 = PIN_A7; // determines the address of the port by the board pin number to which this pin belongs on the MCU GPIO_TypeDef* digitalPinToPort(uint32_t digPinNumber); // determines the pin address inside the port by the board pin number -HAL_PinsTypeDef digitalPinToBitMask(uint32_t digPinNumber); +static inline HAL_PinsTypeDef digitalPinToBitMask(uint32_t digitalPinNumber) +{ + return (HAL_PinsTypeDef)(1 << (digitalPinNumber & 0xF)); +} // total number of pins available for initialization -uint16_t pinCommonQty(void); +static inline uint16_t pinCommonQty(void) +{ + return (uint16_t)PINS_COMMON_QTY; +} // the function returns a reference to the OUTPUT address of the GPIO register volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x); // the function returns a reference to the STATE address of the GPIO register diff --git a/variants/start/variant.c b/variants/start/variant.c index 6d8ece7..82e8e90 100644 --- a/variants/start/variant.c +++ b/variants/start/variant.c @@ -41,17 +41,6 @@ GPIO_TypeDef *digitalPinToPort(uint32_t digitalPinNumber) } } -// determines the pin address inside the port by the board pin number -HAL_PinsTypeDef digitalPinToBitMask(uint32_t digitalPinNumber) -{ - return 1 << (digitalPinNumber & 0xF); -} - -uint16_t pinCommonQty(void) -{ - return (uint16_t)40; -} - // the function returns a reference to the OUTPUT address of the GPIO register volatile uint32_t *portOutputRegister(GPIO_TypeDef *GPIO_x) { @@ -105,17 +94,13 @@ uint32_t analogInputToChannelNumber(uint32_t PinNumber) // ---------------------- PWM ---------------------- // // use only if digitalPinHasPWM() == true #define PWM_PIN_TO_PORT_NUMBER(pin) (((pin) & 16) ? 1 : 0) -// use only if digitalPinHasPWM() == true -static inline uint8_t pwmPinToGpioPinShift(uint8_t digitalPin) -{ - return digitalPin & 3; -} + // use only if digitalPinHasPWM() == true // return true if digitalPin configured as pwm bool digitalPinPwmIsOn(uint8_t digitalPin) { uint8_t config = 0; - uint8_t pinShift = pwmPinToGpioPinShift(digitalPin); + uint8_t pinShift = digitalPin & 3; if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0) config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift);