добавлена поддержка еще одного прерывания и еще двух выводов для ШИМ для

платы Elbear. добавлены флаги компиляции, необходимые для работы в
ArduinoIDE v1.8.19
This commit is contained in:
KLASSENTS 2025-02-04 11:47:20 +07:00
parent f06650400b
commit a32d749c60
19 changed files with 172 additions and 116 deletions

View File

@ -16,6 +16,7 @@ aceUno8Mb.bootloader.tool=mik32_upload
aceUno8Mb.bootloader.tool.default=mik32_upload aceUno8Mb.bootloader.tool.default=mik32_upload
aceUno8Mb.bootloader.file=ace-uno/bootloader.hex aceUno8Mb.bootloader.file=ace-uno/bootloader.hex
aceUno8Mb.bootloader.interface=ftdi/mikron-link.cfg aceUno8Mb.bootloader.interface=ftdi/mikron-link.cfg
aceUno8Mb.bootloader.params.verbose=
# build options # build options
aceUno8Mb.build.mcu=MIK32_Amur aceUno8Mb.build.mcu=MIK32_Amur
@ -42,6 +43,7 @@ aceUno16Mb.bootloader.tool=mik32_upload
aceUno16Mb.bootloader.tool.default=mik32_upload aceUno16Mb.bootloader.tool.default=mik32_upload
aceUno16Mb.bootloader.file=ace-uno/bootloader.hex aceUno16Mb.bootloader.file=ace-uno/bootloader.hex
aceUno16Mb.bootloader.interface=ftdi/mikron-link.cfg aceUno16Mb.bootloader.interface=ftdi/mikron-link.cfg
aceUno16Mb.bootloader.params.verbose=
# build options # build options
aceUno16Mb.build.mcu=MIK32_Amur aceUno16Mb.build.mcu=MIK32_Amur
@ -68,6 +70,7 @@ aceUno32Mb.bootloader.tool=mik32_upload
aceUno32Mb.bootloader.tool.default=mik32_upload aceUno32Mb.bootloader.tool.default=mik32_upload
aceUno32Mb.bootloader.file=ace-uno/bootloader.hex aceUno32Mb.bootloader.file=ace-uno/bootloader.hex
aceUno32Mb.bootloader.interface=ftdi/mikron-link.cfg aceUno32Mb.bootloader.interface=ftdi/mikron-link.cfg
aceUno32Mb.bootloader.params.verbose=
# build options # build options
aceUno32Mb.build.mcu=MIK32_Amur 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.tool.default=mik32_upload
start-mik32-v1.bootloader.file=start-mik32/bootloader.hex start-mik32-v1.bootloader.file=start-mik32/bootloader.hex
start-mik32-v1.bootloader.interface=start-link.cfg start-mik32-v1.bootloader.interface=start-link.cfg
start-mik32-v1.bootloader.params.verbose=
# build options # build options
start-mik32-v1.build.mcu=MIK32_Amur start-mik32-v1.build.mcu=MIK32_Amur

View File

@ -45,7 +45,7 @@ static void Timer16_Init(uint8_t prescaler)
htimer16_1.Trigger.TimeOut = TIMER16_TIMEOUT_DISABLE; htimer16_1.Trigger.TimeOut = TIMER16_TIMEOUT_DISABLE;
htimer16_1.Filter.ExternalClock = TIMER16_FILTER_NONE; htimer16_1.Filter.ExternalClock = TIMER16_FILTER_NONE;
htimer16_1.Filter.Trigger = 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.Waveform.Polarity = TIMER16_WAVEFORM_POLARITY_NONINVERTED;
htimer16_1.EncoderMode = TIMER16_ENCODER_DISABLE; htimer16_1.EncoderMode = TIMER16_ENCODER_DISABLE;
HAL_Timer16_Init(&htimer16_1); HAL_Timer16_Init(&htimer16_1);

View File

@ -6,6 +6,9 @@
#include "WInterrupts.h" #include "WInterrupts.h"
#include "wiring_LL.h" #include "wiring_LL.h"
// interrupts are enabled by default after setup()
static bool intIsEnabled = true;
typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtr)(void);
// empty irq handler // empty irq handler
@ -18,14 +21,20 @@ static void nothing(void)
void interrupts(void) void interrupts(void)
{ {
GLOBAL_IRQ_ENABLE(); GLOBAL_IRQ_ENABLE();
intIsEnabled = true;
} }
// disable global interrupts // disable global interrupts
void noInterrupts(void) void noInterrupts(void)
{ {
GLOBAL_IRQ_DISABLE(); GLOBAL_IRQ_DISABLE();
intIsEnabled = false;
} }
bool isInterruptsEnabled(void)
{
return intIsEnabled;
}
// we can provide no more than 8 interrupts on gpio at the same time // we can provide no more than 8 interrupts on gpio at the same time
static volatile voidFuncPtr intFunc[EXTERNAL_INTERRUPTS_QTY] = static volatile voidFuncPtr intFunc[EXTERNAL_INTERRUPTS_QTY] =
{ {

View File

@ -6,10 +6,12 @@ extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
#include "stdbool.h"
// enable/disable interrupts // enable/disable interrupts
void interrupts(void); void interrupts(void);
void noInterrupts(void); void noInterrupts(void);
bool isInterruptsEnabled(void);
// attach/detach interrupt to pin // attach/detach interrupt to pin
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode); void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);

View File

@ -4,8 +4,8 @@
#include "Arduino.h" #include "Arduino.h"
// --------------------- init --------------------- // // --------------------- init --------------------- //
// called before setup() // called from crt0.S before constructors initialization
void pre_init(void) extern "C" void SystemInit(void)
{ {
// set irq vector to ram region // set irq vector to ram region
write_csr(mtvec, 0x02000000); write_csr(mtvec, 0x02000000);
@ -25,8 +25,8 @@ void pre_init(void)
// called after setup() // called after setup()
void post_init(void) void post_init(void)
{ {
// enable global interrupts by default if(isInterruptsEnabled()) // if user has called noInterrupts() in setup(), this value is false
interrupts(); interrupts(); // enable global interrupts
} }
// --------------------- other --------------------- // // --------------------- other --------------------- //

View File

@ -5,8 +5,7 @@ extern volatile bool use_error_messages;
#define DISABLE_ERROR_MESSAGES() (use_error_messages = false) #define DISABLE_ERROR_MESSAGES() (use_error_messages = false)
#define ENABLE_ERROR_MESSAGES() (use_error_messages = true) #define ENABLE_ERROR_MESSAGES() (use_error_messages = true)
// functions for init called before and after setup() // function for init called after setup()
void pre_init(void) ;
void post_init(void); void post_init(void);
#endif /* _BOARD_H_ */ #endif /* _BOARD_H_ */

View File

@ -4,7 +4,6 @@
int main() int main()
{ {
pre_init();
setup(); setup();
post_init(); post_init();

View File

@ -144,8 +144,8 @@ typedef enum __HAL_Timer16_EncoderTypeDef
*/ */
typedef enum __HAL_Timer16_WaveformGenTypeDef typedef enum __HAL_Timer16_WaveformGenTypeDef
{ {
TIMER16_WAVEFORM_GENERATION_ENABLE = 0, /**< Выключить генерацию волновой формы. */ TIMER16_WAVEFORM_GENERATION_ENABLE = 0, /**< Включить генерацию волновой формы. */
TIMER16_WAVEFORM_GENERATION_DISABLE = 1 /**< Включить генерацию волновой формы. */ TIMER16_WAVEFORM_GENERATION_DISABLE = 1 /**< Выключить генерацию волновой формы. */
} HAL_Timer16_WaveformGenTypeDef; } HAL_Timer16_WaveformGenTypeDef;
/** /**

View File

@ -105,7 +105,7 @@ typedef enum __HAL_TSENS_ClockTypeDef
/** /**
* @brief Определение структуры TSENS Handle. * @brief Определение структуры TSENS Handle.
*/ */
typedef struct __SPI_HandleTypeDef typedef struct __TSENS_HandleTypeDef
{ {
ANALOG_REG_TypeDef *Instance; /**< Адрес регистров блока управления аналоговой подсистемой. */ ANALOG_REG_TypeDef *Instance; /**< Адрес регистров блока управления аналоговой подсистемой. */
@ -119,7 +119,7 @@ typedef struct __SPI_HandleTypeDef
/** /**
* @brief Возвращаемая структура для функции @ref HAL_TSENS_SingleStart. * @brief Возвращаемая структура для функции @ref HAL_TSENS_SingleStart.
*/ */
typedef struct __WDT_ClockTypeDef typedef struct __TSENS_ValueTypeDef
{ {
HAL_StatusTypeDef statusHAL; /**< Статус HAL. */ HAL_StatusTypeDef statusHAL; /**< Статус HAL. */

View File

@ -105,7 +105,7 @@ typedef struct __WDT_ClockTypeDef
} 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_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout);
HAL_StatusTypeDef HAL_WDT_Refresh(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); HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout);

View File

@ -3,14 +3,56 @@
uint16_t TimeOut = 20; uint16_t TimeOut = 20;
uint16_t WDT_prescale[] = {1, 2, 4, 16, 64, 256, 1024, 4096}; 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. * @brief Инициализация WDT MSP.
* @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит * @param hwdt указатель на структуру WDT_HandleTypeDef, которая содержит
* информацию о конфигурации для модуля WDT. * информацию о конфигурации для модуля 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(); __HAL_PCC_WDT_CLK_ENABLE();
} }
@ -82,7 +124,7 @@ HAL_StatusTypeDef HAL_WDT_Init(WDT_HandleTypeDef *hwdt, uint32_t timeout)
return HAL_ERROR; return HAL_ERROR;
} }
HAL_RTC_MspInit(hwdt); HAL_WDT_MspInit(hwdt);
if (HAL_WDT_Stop(hwdt, timeout) != HAL_OK) 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); uint32_t conValue = (wdtClock.divIndex << WDT_CON_PRESCALE_S) | WDT_CON_PRELOAD(wdtClock.tick);
hwdt->Instance->KEY = WDT_KEY_UNLOCK; HAL_WDT_Write_Word_To_CON(hwdt, conValue);
hwdt->Instance->CON = conValue;
return HAL_OK; 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) HAL_StatusTypeDef HAL_WDT_Refresh(WDT_HandleTypeDef *hwdt, uint32_t timeout)
{ {
hwdt->Instance->KEY = WDT_KEY_UNLOCK; HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START);
hwdt->Instance->KEY = WDT_KEY_START;
while (timeout--) 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) HAL_StatusTypeDef HAL_WDT_Start(WDT_HandleTypeDef *hwdt, uint32_t timeout)
{ {
hwdt->Instance->KEY = WDT_KEY_UNLOCK; HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_START);
hwdt->Instance->KEY = WDT_KEY_START;
while (timeout--) 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) HAL_StatusTypeDef HAL_WDT_Stop(WDT_HandleTypeDef *hwdt, uint32_t timeout)
{ {
hwdt->Instance->KEY = WDT_KEY_UNLOCK; HAL_WDT_Write_Byte_To_KEY(hwdt, WDT_KEY_STOP);
hwdt->Instance->KEY = WDT_KEY_STOP;
while (timeout--) 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) 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); 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; HAL_WDT_Write_Word_To_CON(hwdt, conValue);
hwdt->Instance->CON = 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) 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); uint32_t conValue = (hwdt->Instance->CON & (~WDT_CON_PRELOAD_M)) | WDT_CON_PRELOAD(preload);
hwdt->Instance->KEY = WDT_KEY_UNLOCK; HAL_WDT_Write_Word_To_CON(hwdt, conValue);
hwdt->Instance->CON = conValue;
} }

View File

@ -5,6 +5,7 @@
#include "mik32_hal_gpio.h" #include "mik32_hal_gpio.h"
#include "mik32_hal_scr1_timer.h" #include "mik32_hal_scr1_timer.h"
#include "mik32_hal_timer16.h" #include "mik32_hal_timer16.h"
#include "pad_config.h"
// ----------------- COMMON ----------------- // // ----------------- COMMON ----------------- //
// convert pin mask from HAL_PinsTypeDef to pin number // 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)) #define TIM16_DISABLE_INT_BY_MASK(htim16,intMask) (htim16.Instance->IER &= ~(intMask))
// ----------------- EPIC ----------------- // // ----------------- 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_LEVEL_CLEAR_BY_MASK(mask) (EPIC->MASK_LEVEL_CLEAR |= mask)
#define EPIC_CLEAR_ALL() (EPIC->CLEAR = 0xFFFFFFFF) #define EPIC_CLEAR_ALL() (EPIC->CLEAR = 0xFFFFFFFF)
@ -41,6 +43,8 @@
set_csr(mie, MIE_MEIE) set_csr(mie, MIE_MEIE)
// ----------------- GPIO ----------------- // // ----------------- 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_SET_PIN(GPIO_x, pinMask) ((GPIO_x)->SET = (pinMask))
#define GPIO_CLEAR_PIN(GPIO_x, pinMask) ((GPIO_x)->CLEAR = (pinMask)) #define GPIO_CLEAR_PIN(GPIO_x, pinMask) ((GPIO_x)->CLEAR = (pinMask))
#define GPIO_TOGGLE_PIN(GPIO_x, pinMask) ((GPIO_x)->OUTPUT_ ^= pinMask) #define GPIO_TOGGLE_PIN(GPIO_x, pinMask) ((GPIO_x)->OUTPUT_ ^= pinMask)
@ -60,6 +64,4 @@
#define PIN_SET_PAD_CONFIG(portReg, pinNumber, value) (PAD_CONFIG->portReg = (PAD_CONFIG->portReg & (~PAD_CONFIG_PIN_M(pinNumber))) \ #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_ */ #endif /* _WIRING_LL_H_ */

View File

@ -4,11 +4,24 @@
![Pinout](pinout.PNG) ![Pinout](pinout.PNG)
### Цифровые выводы ### Цифровые выводы
На плате Elbear Ace-Uno доступны встроенные светодиод и кнопка. Для их использования необходимо воспользоваться макросами `LED_BUILTIN` и `BTN_BUILTIN`, передавая их в качестве аргументов функции вместо номера цифрового вывода. Макросу `LED_BUILTIN` соответствует номер вывода D22, а макросу `BTN_BUILTIN` - D23. На плате 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. Цифровой вывод 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| |D5|3|
|D8|4| |D8|4|
|D9|5| |D9|5|
|`BTN_BUILTIN`|6| |A1|6|
|`BTN_BUILTIN`|7|
При использовании аналогового вывода A1 для работы с прерываниями необходимо предварительно перевести вывод в режим цифрового. Для этого нужно перевести DIP-переключатель номер 2 в положение ON.
### Serial ### Serial
Интерфейс UART0 доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`. Интерфейс UART0 доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`.

View File

@ -205,6 +205,8 @@ void SoftwareSerial::setRX(uint8_t rx)
PIN_SET_PAD_CONFIG(PORT_0_PUPD, pinNumber, HAL_GPIO_PULL_UP); PIN_SET_PAD_CONFIG(PORT_0_PUPD, pinNumber, HAL_GPIO_PULL_UP);
else if (((GPIO_TypeDef*)_receivePortRegister) == GPIO_1) else if (((GPIO_TypeDef*)_receivePortRegister) == GPIO_1)
PIN_SET_PAD_CONFIG(PORT_1_PUPD, pinNumber, HAL_GPIO_PULL_UP); 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()) // turn off int line for while (it turning on in attachInterrupt())
GPIO_IRQ_LINE_DISABLE(_int_maskLine); GPIO_IRQ_LINE_DISABLE(_int_maskLine);

View File

@ -65,6 +65,7 @@ tools.elbear_uploader.cmd.windows=elbear_uploader.exe
tools.elbear_uploader.path={runtime.tools.elbear_uploader.path} 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.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.quiet=
tools.elbear_uploader.upload.params.verbose=
# Set elbear_uploader as programmer # Set elbear_uploader as programmer
programmers.elbear_uploader.name=Elbear Uploader 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 # 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.pattern=
tools.mik32_upload.erase.params.quiet= tools.mik32_upload.erase.params.quiet=
tools.mik32_upload.erase.params.verbose=
# For Tools > Burn Bootloader # 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 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 # 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.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.quiet=
tools.mik32_upload.program.params.verbose=

View File

@ -111,7 +111,7 @@ static const uint8_t SCL = PIN_WIRE_SCL;
#define WIRE_FREQ_1000K 1000000 #define WIRE_FREQ_1000K 1000000
// interrupts // interrupts
#define EXTERNAL_INTERRUPTS_QTY 7 #define EXTERNAL_INTERRUPTS_QTY 8
extern uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3]; extern uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3];
// determines the board pin number by interrupt number // determines the board pin number by interrupt number
#define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0]) #define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0])

View File

@ -153,25 +153,14 @@ uint32_t analogInputToChannelNumber(uint32_t PinNumber)
// ---------------------- PWM ---------------------- // // ---------------------- PWM ---------------------- //
// use only if digitalPinHasPWM() == true // use only if digitalPinHasPWM() == true
#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin==10)||(pin==11)) ? 1:0) #define PWM_PIN_TO_PORT_NUMBER(pin) (((pin==10)||(pin==11)||(pin==12)||(pin==13)) ? 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;
}
// use only if digitalPinHasPWM() == true // use only if digitalPinHasPWM() == true
// return true if digitalPin configured as pwm // return true if digitalPin configured as pwm
bool digitalPinPwmIsOn(uint8_t digitalPin) bool digitalPinPwmIsOn(uint8_t digitalPin)
{ {
uint8_t config = 0; 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) if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0)
config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift); 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 spi is in use D10 cannot work as pwm
if (spiNssPinIsBlocked && (p == 10)) if (spiNssPinIsBlocked && (p == 10))
ret = false; 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; ret = true;
return ret; return ret;
} }
@ -204,7 +193,7 @@ TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber)
if (digPinNumber == 3 || digPinNumber == 5 || digPinNumber == 6 || digPinNumber == 9) if (digPinNumber == 3 || digPinNumber == 5 || digPinNumber == 6 || digPinNumber == 9)
timerNum = TIMER32_1; timerNum = TIMER32_1;
// timer 2 // timer 2
else if (digPinNumber == 10 || digPinNumber == 11) else if (digPinNumber == 10 || digPinNumber == 11 || digPinNumber == 12 || digPinNumber == 13)
timerNum = TIMER32_2; timerNum = TIMER32_2;
return timerNum; return timerNum;
@ -214,9 +203,9 @@ TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber)
HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber) HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber)
{ {
HAL_TIMER32_CHANNEL_IndexTypeDef channel = 0; 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 == 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; else if (digPinNumber == 9 || digPinNumber == 10) channel = TIMER32_CHANNEL_3;
return channel; return channel;
} }
@ -232,7 +221,9 @@ uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3] =
{ 5, GPIO_LINE_1, GPIO_MUX_LINE_1_PORT0_1}, // INT3 { 5, GPIO_LINE_1, GPIO_MUX_LINE_1_PORT0_1}, // INT3
{ 8, GPIO_LINE_5, GPIO_MUX_LINE_5_PORT1_9}, // INT4 { 8, GPIO_LINE_5, GPIO_MUX_LINE_5_PORT1_9}, // INT4
{ 9, GPIO_LINE_3, GPIO_MUX_LINE_3_PORT0_3}, // INT5 { 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) int8_t digitalPinToGpioIntMux(uint8_t digPinNumber)

View File

@ -32,49 +32,51 @@ extern "C" {
#include "mik32_hal_gpio.h" #include "mik32_hal_gpio.h"
#include "mik32_hal_timer32.h" #include "mik32_hal_timer32.h"
#define PORT_PIN_MASK 0xF
// digital pins // digital pins
#define P0_0 0 typedef enum
#define P0_1 1 {
#define P0_2 2 P0_0 = 0, // 0
#define P0_3 3 P0_1, // 1
#define P0_4 4 P0_2, // 2
#define P0_5 5 P0_3, // 3
#define P0_6 6 P0_4, // 4
#define P0_7 7 P0_5, // 5
#define P0_8 8 P0_6, // 6
#define P0_9 9 P0_7, // 7
#define P0_10 10 P0_8, // 8
#define P0_11 11 P0_9, // 9
#define P0_12 12 P0_10, // 10
#define P0_13 13 P0_11, // 11
#define P0_14 14 P0_12, // 12
#define P0_15 15 P0_13, // 13
#define P1_0 16 P0_14, // 14
#define P1_1 17 P0_15, // 15
#define P1_2 18 P1_0, // 16
#define P1_3 19 P1_1, // 17
#define P1_4 20 P1_2, // 18
#define P1_5 21 P1_3, // 19
#define P1_6 22 P1_4, // 20
#define P1_7 23 P1_5, // 21
#define P1_8 24 P1_6, // 22
#define P1_9 25 P1_7, // 23
#define P1_10 26 P1_8, // 24
#define P1_11 27 P1_9, // 25
#define P1_12 28 P1_10, // 26
#define P1_13 29 P1_11, // 27
#define P1_14 30 P1_12, // 28
#define P1_15 31 P1_13, // 29
#define P2_0 32 P1_14, // 30
#define P2_1 33 P1_15, // 31
#define P2_2 34 P2_0, // 32
#define P2_3 35 P2_1, // 33
#define P2_4 36 P2_2, // 34
#define P2_5 37 P2_3, // 35
#define P2_6 38 P2_4, // 36
#define P2_7 39 P2_5, // 37
P2_6, // 38
P2_7, // 39
PINS_COMMON_QTY, // 40
} DigitalPinsTypeDef;
// analog pins // analog pins
#define PIN_A0 (P1_5) #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 // 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); GPIO_TypeDef* digitalPinToPort(uint32_t digPinNumber);
// determines the pin address inside the port by the board pin number // 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 // 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 // the function returns a reference to the OUTPUT address of the GPIO register
volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x); volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x);
// the function returns a reference to the STATE address of the GPIO register // the function returns a reference to the STATE address of the GPIO register

View File

@ -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 // the function returns a reference to the OUTPUT address of the GPIO register
volatile uint32_t *portOutputRegister(GPIO_TypeDef *GPIO_x) volatile uint32_t *portOutputRegister(GPIO_TypeDef *GPIO_x)
{ {
@ -105,17 +94,13 @@ uint32_t analogInputToChannelNumber(uint32_t PinNumber)
// ---------------------- PWM ---------------------- // // ---------------------- PWM ---------------------- //
// use only if digitalPinHasPWM() == true // use only if digitalPinHasPWM() == true
#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin) & 16) ? 1 : 0) #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 // use only if digitalPinHasPWM() == true
// return true if digitalPin configured as pwm // return true if digitalPin configured as pwm
bool digitalPinPwmIsOn(uint8_t digitalPin) bool digitalPinPwmIsOn(uint8_t digitalPin)
{ {
uint8_t config = 0; uint8_t config = 0;
uint8_t pinShift = pwmPinToGpioPinShift(digitalPin); uint8_t pinShift = digitalPin & 3;
if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0) if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0)
config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift); config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift);