dev0.2_halRevision (#1)

- Реализация части функций в библиотеках hal перенесена в заголовочный файл, функции определены как inline.
- В модулях Tone, SPI, Wire работа с регистрами вынесена в библиотеку hal или в платозависимые файлы pins_arduino.h, variants.c
- В модуле wiring_analog при отключении работы ШИМ сначала проверяется, включен ли ШИМ на указанной ноге. Если включен, вывод после отключения таймера конфигурируется на вход.

Reviewed-on: Elron_dev/elbear_arduino_bsp#1
This commit is contained in:
klassents committed 2024-09-11 10:50:22 +03:00
1 parent f020720e1f
commit 8f0a5b0a94
17 files changed
+433 -313

No files matched your search

+8 -7
View File
@@ -100,7 +100,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
HAL_EPIC_MaskLevelSet(HAL_EPIC_TIMER16_1_MASK);
pinMode(pin, OUTPUT);
timer_pin_port->CLEAR = timer_pin_mask;
HAL_GPIO_WritePin((GPIO_TypeDef *)timer_pin_port, timer_pin_mask, GPIO_PIN_LOW);
HAL_Timer16_Counter_Start_IT(&htimer16_1, frequencyParams.period_ticks);
timerIsOn = true;
@@ -124,8 +124,9 @@ void noTone(uint8_t pin)
{
if (timerIsOn)
{
timer_pin_port->CLEAR = timer_pin_mask; // pin to 0
htimer16_1.Instance->CR &= ~TIMER16_CR_ENABLE_M; // disable timer
// pin to 0
HAL_GPIO_WritePin((GPIO_TypeDef *)timer_pin_port, timer_pin_mask, GPIO_PIN_LOW);
HAL_Timer16_Disable(&htimer16_1); // disable timer
HAL_EPIC_MaskLevelClear(HAL_EPIC_TIMER16_1_MASK);
pinMode(pin, INPUT); // deinit pin
timer_pin = -1; // reset to default
@@ -136,12 +137,12 @@ void noTone(uint8_t pin)
// irq handler
extern "C" void tone_interrupt_handler(void)
{
if ((htimer16_1.Instance->ISR & htimer16_1.Instance->IER) & TIMER16_ISR_ARR_MATCH_M)
if(HAL_Timer16_GetInterruptStatus_ARRM(&htimer16_1))
{
// timer period has passed, change the pin state
if (timer_toggle_count != 0)
{
timer_pin_port->OUTPUT_ ^= timer_pin_mask;
HAL_GPIO_TogglePin((GPIO_TypeDef*)timer_pin_port, timer_pin_mask);
if (timer_toggle_count > 0)
timer_toggle_count--;
@@ -149,10 +150,10 @@ extern "C" void tone_interrupt_handler(void)
else
{
// turn off if the specified duration has passed
timer_pin_port->CLEAR = timer_pin_mask;
HAL_GPIO_WritePin((GPIO_TypeDef *)timer_pin_port, timer_pin_mask, GPIO_PIN_LOW);
noTone(timer_pin);
}
}
// reset timer interrupt flags
htimer16_1.Instance->ICR = 0xFFFFFFFF;
HAL_Timer16_ClearInterruptMask(&htimer16_1, 0xFFFFFFFF);
}
@@ -375,14 +375,96 @@ typedef enum __HAL_GPIO_InterruptMode
HAL_StatusTypeDef HAL_GPIO_Init(GPIO_TypeDef *GPIO_x, GPIO_InitTypeDef *GPIO_Init);
HAL_StatusTypeDef HAL_GPIO_PinConfig(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin, HAL_GPIO_ModeTypeDef mode, HAL_GPIO_PullTypeDef pull, HAL_GPIO_DSTypeDef driveStrength);
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin);
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin, GPIO_PinState pinState);
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin);
HAL_StatusTypeDef HAL_GPIO_InitInterruptLine(HAL_GPIO_Line_Config mux, HAL_GPIO_InterruptMode mode);
HAL_StatusTypeDef HAL_GPIO_DeInitInterruptLine(HAL_GPIO_Line irqLine);
uint32_t HAL_GPIO_LineInterruptState(HAL_GPIO_Line irqLine);
GPIO_PinState HAL_GPIO_LinePinState(HAL_GPIO_Line irqLine);
void HAL_GPIO_ClearInterrupts();
/**
* @brief Считать текущее состояние выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, с которых считывание значение.
* @return @ref GPIO_PIN_HIGH если с одного или больше выводов, указанных в pin, считалась 1. Иначе @ref GPIO_PIN_LOW.
*/
static inline __attribute__((always_inline)) GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin)
{
if ((GPIO_x->SET & pin) != (uint32_t)GPIO_PIN_LOW)
return GPIO_PIN_HIGH;
else
return GPIO_PIN_LOW;
}
/**
* @brief Задать логический уровень выходного сигнала для указанных выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, к которым применяются указанные настройки.
* @param pinState значение состояние вывода, в которое будут установлены указанные выводы.
* Этот параметр должен быть одним из значений:
* - @ref GPIO_PIN_LOW низкий выходной уровень
* - @ref GPIO_PIN_HIGH высокий выходной уровень
*/
static inline __attribute__((always_inline)) void HAL_GPIO_WritePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin, GPIO_PinState pinState)
{
if (pinState == GPIO_PIN_LOW)
GPIO_x->CLEAR = pin;
else
GPIO_x->SET = pin;
}
/**
* @brief Переключить логический уровень выходного сигнала для указанных выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, к которым применяются указанные настройки.
*/
static inline __attribute__((always_inline)) void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin)
{
GPIO_x->OUTPUT_ ^= pin;
}
/**
* @brief Возвращает направление вывода при работе в режиме вход/выход
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска вывода порта GPIO_x, направление которого необходимо узнать.
* @return Возвращает направление вывода - input или output.
*/
static inline __attribute__((always_inline)) HAL_GPIO_ModeTypeDef HAL_GPIO_GetPinDirection(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin)
{
return (GPIO_x->DIRECTION_IN & pin) == 0 ? HAL_GPIO_MODE_GPIO_OUTPUT : HAL_GPIO_MODE_GPIO_INPUT;
}
/**
* @brief Получить состояние линии прерывания.
* @param irqLine номер линии прерывания.
* @return Возвращает 1 если сработало прерывание данной линии, иначе 0.
*/
static inline __attribute__((always_inline)) uint32_t HAL_GPIO_LineInterruptState(HAL_GPIO_Line irqLine)
{
int irq_line_num = irqLine >> GPIO_IRQ_LINE_S;
return (GPIO_IRQ->INTERRUPT & (1 << (irq_line_num))) != 0;
}
/**
* @brief Функция чтения логического уровня вывода, подключенного к линии прерывания.
* @param irqLine номер линии прерывания.
* @return Логический уровень вывода.
*/
static inline __attribute__((always_inline)) GPIO_PinState HAL_GPIO_LinePinState(HAL_GPIO_Line irqLine)
{
int irq_line_num = irqLine >> GPIO_IRQ_LINE_S;
return (GPIO_PinState)((GPIO_IRQ->STATE & (1 << (irq_line_num))) >> irq_line_num);
}
/**
* @brief Функция сброса регистра состояния прерываний.
* @note Когда срабатывает прерывание на одной из линии, в регистре INTERRUPT
* выставляется 1 в разряде, соответствующем линии прерывания.
* После обработки прерывания необходимо сбросить данный регистр
* в обработчике прерывания trap_handler().
* Если после обработки прерывания регистр не был сброшен,
* обработчик будет вызван снова, программа будет бесконечно вызывать обработчик.
*/
static inline __attribute__((always_inline)) void HAL_GPIO_ClearInterrupts()
{
GPIO_IRQ->CLEAR = 0b11111111;
}
#ifdef __cplusplus
}
@@ -380,9 +380,6 @@ typedef struct
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c);
void HAL_I2C_Disable(I2C_HandleTypeDef *hi2c);
void HAL_I2C_Reset(I2C_HandleTypeDef *hi2c);
void HAL_I2C_Enable(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AnalogFilterInit(I2C_HandleTypeDef *hi2c, HAL_I2C_AnalogFilterTypeDef AnalogFilter);
void HAL_I2C_DigitalFilterInit(I2C_HandleTypeDef *hi2c, HAL_I2C_DigitalFilterTypeDef DigitalFilter);
void HAL_I2C_SetClockSpeed(I2C_HandleTypeDef *hi2c);
@@ -394,6 +391,7 @@ void HAL_I2C_SBCMode(I2C_HandleTypeDef *hi2c, HAL_I2C_SBCModeTypeDef SBCMode);
void HAL_I2C_SlaveInit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MasterInit(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_Deinit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_AutoEnd(I2C_HandleTypeDef *hi2c, HAL_I2C_AutoEndModeTypeDef AutoEnd);
HAL_StatusTypeDef HAL_I2C_Master_WaitTXIS(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Master_WaitRXNE(I2C_HandleTypeDef *hi2c, uint32_t Timeout);
@@ -427,6 +425,60 @@ HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pDa
HAL_StatusTypeDef HAL_I2C_Slave_Receive_NOSTRETCH_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t DataSize);
HAL_StatusTypeDef HAL_I2C_Slave_ReceiveSBC_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t DataSize);
static inline __attribute__((always_inline)) void HAL_I2C_Disable(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->CR1 &= ~I2C_CR1_PE_M;
}
static inline __attribute__((always_inline)) void HAL_I2C_Reset(I2C_HandleTypeDef *hi2c)
{
hi2c->ErrorCode = I2C_ERROR_NONE;
hi2c->Instance->CR1 &= ~I2C_CR1_PE_M;
hi2c->Instance->CR1 |= I2C_CR1_PE_M;
}
static inline __attribute__((always_inline)) void HAL_I2C_Enable(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->CR1 |= I2C_CR1_PE_M;
}
static inline __attribute__((always_inline)) void HAL_I2C_Reset_Interrupt_Flag(I2C_HandleTypeDef *hi2c, uint32_t mask)
{
hi2c->Instance->ICR |= mask;
}
static inline __attribute__((always_inline)) void HAL_I2C_Reset_TXDR_Content(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->ISR |= I2C_ISR_TXE_M;
}
static inline __attribute__((always_inline)) uint32_t HAL_I2C_Get_Interrupts_Status(I2C_HandleTypeDef *hi2c)
{
return hi2c->Instance->ISR;
}
static inline __attribute__((always_inline)) uint32_t HAL_I2C_Get_CR1_Content(I2C_HandleTypeDef *hi2c)
{
return hi2c->Instance->CR1;
}
static inline __attribute__((always_inline)) void HAL_I2C_Write_TXDR(I2C_HandleTypeDef *hi2c, uint8_t value)
{
hi2c->Instance->TXDR = value;
}
static inline __attribute__((always_inline)) uint8_t HAL_I2C_Get_RXDR(I2C_HandleTypeDef *hi2c)
{
return hi2c->Instance->RXDR;
}
static inline __attribute__((always_inline)) void HAL_I2C_Clear_Reload(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->CR2 &= ~I2C_CR2_RELOAD_M;
}
static inline __attribute__((always_inline)) void HAL_I2C_ADDR_IRQ(I2C_HandleTypeDef *hi2c)
{
if (hi2c->Instance->CR1 & I2C_CR1_SBC_M)
@@ -253,7 +253,8 @@ void HAL_SPI_CS_Disable(SPI_HandleTypeDef *hspi);
HAL_StatusTypeDef HAL_SPI_Exchange(SPI_HandleTypeDef *hspi, uint8_t TransmitBytes[], uint8_t ReceiveBytes[], uint32_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_SPI_ExchangeThreshold(SPI_HandleTypeDef *hspi, uint8_t TransmitBytes[], uint8_t ReceiveBytes[], uint32_t DataSize, uint32_t Timeout);
HAL_StatusTypeDef HAL_SPI_Exchange_IT(SPI_HandleTypeDef *hspi, uint8_t TransmitBytes[], uint8_t ReceiveBytes[], uint32_t Size);
void HAL_SPI_Set_Clock_Divider(SPI_HandleTypeDef *hspi, uint8_t clockDiv);
void HAL_SPI_Set_Clock_Mode(SPI_HandleTypeDef *hspi, uint8_t CLKPhase, uint8_t CLKPolarity);
/**
* @brief Разрешить прерывания в соответствии с маской.
@@ -230,8 +230,6 @@ typedef struct __Timer16_HandleTypeDef
void HAL_TIMER16_MspInit(Timer16_HandleTypeDef* htimer16);
void HAL_Timer16_Disable(Timer16_HandleTypeDef *htimer16);
void HAL_Timer16_Enable(Timer16_HandleTypeDef *htimer16);
void HAL_Timer16_SetActiveEdge(Timer16_HandleTypeDef *htimer16, uint8_t ActiveEdge);
void HAL_Timer16_SetSourceClock(Timer16_HandleTypeDef *htimer16, uint8_t SourceClock);
void HAL_Timer16_SetCountMode(Timer16_HandleTypeDef *htimer16, uint8_t CountMode);
@@ -278,6 +276,26 @@ void HAL_Timer16_SetInterruptARRM(Timer16_HandleTypeDef *htimer16);
void HAL_Timer16_SetInterruptCMPM(Timer16_HandleTypeDef *htimer16);
void HAL_Timer16_InterruptInit(Timer16_HandleTypeDef *htimer16);
/**
* @brief Выключить таймер.
* Может использоваться для отключения таймера или при записи в регистр CFGR.
*
* @param htimer16 Указатель на структуру с настройками Timer16.
*/
static inline void __attribute__((always_inline)) HAL_Timer16_Disable(Timer16_HandleTypeDef *htimer16)
{
htimer16->Instance->CR &= ~TIMER16_CR_ENABLE_M;
}
/**
* @brief Включить таймер
* @param htimer16 Указатель на структуру с настройками Timer16.
*/
static inline void __attribute__((always_inline)) HAL_Timer16_Enable(Timer16_HandleTypeDef *htimer16)
{
htimer16->Instance->CR |= TIMER16_CR_ENABLE_M;
}
/**
* @brief Получить статус прерываний Timer16.
* Функция возвращает статус прерываний в соответствии с маской разрешенный прерываний.
@@ -291,6 +309,16 @@ static inline __attribute__((always_inline)) uint32_t HAL_Timer16_GetInterruptSt
return interrupt_status;
}
/**
* @brief Получить статус прерывания по соответствию автозагрузке ARRM
* @param htimer16 Указатель на структуру с настройками Timer16
* @return Статус прерывания ARRM - true, если прерывание сработало
*/
static inline __attribute__((always_inline)) bool HAL_Timer16_GetInterruptStatus_ARRM(Timer16_HandleTypeDef *htimer16)
{
return (bool)((htimer16->Instance->ISR & htimer16->Instance->IER) & TIMER16_ISR_ARR_MATCH_M);
}
/**
* @brief Очистить флаг прерывания.
* @param htimer16 Указатель на структуру с настройками Timer16.
@@ -226,6 +226,7 @@ static inline __attribute__((always_inline)) HAL_StatusTypeDef HAL_Timer32_WaitF
void HAL_TIMER32_MspInit(TIMER32_HandleTypeDef* htimer32);
void HAL_TIMER32_Channel_MspInit(TIMER32_CHANNEL_HandleTypeDef* timerChannel);
HAL_StatusTypeDef HAL_Timer32_Init(TIMER32_HandleTypeDef *timer);
HAL_StatusTypeDef HAL_Timer32_Deinit(TIMER32_HandleTypeDef *timer);
void HAL_Timer32_State_Set(TIMER32_HandleTypeDef *timer, HAL_TIMER32_StateTypeDef state);
void HAL_Timer32_Top_Set(TIMER32_HandleTypeDef *timer, uint32_t top);
void HAL_Timer32_Prescaler_Set(TIMER32_HandleTypeDef *timer, uint32_t prescaler);
@@ -93,58 +93,6 @@ HAL_StatusTypeDef HAL_GPIO_PinConfig(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin,
return HAL_GPIO_Init(GPIO_x, &GPIO_InitStruct);
}
/**
* @brief Считать текущее состояние выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, с которых считывание значение.
* @return @ref GPIO_PIN_HIGH если с одного или больше выводов, указанных в pin, считалась 1. Иначе @ref GPIO_PIN_LOW.
*/
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin)
{
GPIO_PinState bitStatus;
if ((GPIO_x->SET & pin) != (uint32_t)GPIO_PIN_LOW)
{
bitStatus = GPIO_PIN_HIGH;
}
else
{
bitStatus = GPIO_PIN_LOW;
}
return bitStatus;
}
/**
* @brief Задать логический уровень выходного сигнала для указанных выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, к которым применяются указанные настройки.
* @param pinState значение состояние вывода, в которое будут установлены указанные выводы.
* Этот параметр должен быть одним из значений:
* - @ref GPIO_PIN_LOW низкий выходной уровень
* - @ref GPIO_PIN_HIGH высокий выходной уровень
*/
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin, GPIO_PinState pinState)
{
if (pinState == GPIO_PIN_LOW)
{
GPIO_x->CLEAR = pin;
}
else
{
GPIO_x->SET = pin;
}
}
/**
* @brief Переключить логический уровень выходного сигнала для указанных выводов порта GPIO_x.
* @param GPIO_x порт GPIO_x, где x может быть (0, 1, 2).
* @param pin маска выводов порта GPIO_x, к которым применяются указанные настройки.
*/
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIO_x, HAL_PinsTypeDef pin)
{
GPIO_x->OUTPUT_ ^= pin;
}
/**
* @brief Функция инициализации линии прерывания.
* \param mux настройка мультиплексора линии прерывания.
@@ -222,39 +170,3 @@ HAL_StatusTypeDef HAL_GPIO_DeInitInterruptLine(HAL_GPIO_Line irqLine)
return HAL_OK;
}
/**
* @brief Получить состояние линии прерывания.
* @param irqLine номер линии прерывания.
* @return Возвращает 1 если сработало прерывание данной линии, иначе 0.
*/
uint32_t HAL_GPIO_LineInterruptState(HAL_GPIO_Line irqLine)
{
int irq_line_num = irqLine >> GPIO_IRQ_LINE_S;
return (GPIO_IRQ->INTERRUPT & (1 << (irq_line_num))) != 0;
}
/**
* @brief Функция чтения логического уровня вывода, подключенного к линии прерывания.
* @param irqLine номер линии прерывания.
* @return Логический уровень вывода.
*/
GPIO_PinState HAL_GPIO_LinePinState(HAL_GPIO_Line irqLine)
{
int irq_line_num = irqLine >> GPIO_IRQ_LINE_S;
return (GPIO_PinState)((GPIO_IRQ->STATE & (1 << (irq_line_num))) >> irq_line_num);
}
/**
* @brief Функция сброса регистра состояния прерываний.
* @note Когда срабатывает прерывание на одной из линии, в регистре INTERRUPT
* выставляется 1 в разряде, соответствующем линии прерывания.
* После обработки прерывания необходимо сбросить данный регистр
* в обработчике прерывания trap_handler().
* Если после обработки прерывания регистр не был сброшен,
* обработчик будет вызван снова, программа будет бесконечно вызывать обработчик.
*/
void HAL_GPIO_ClearInterrupts()
{
GPIO_IRQ->CLEAR = 0b11111111;
}
@@ -26,24 +26,6 @@ __attribute__((weak)) void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
}
void HAL_I2C_Disable(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->CR1 &= ~I2C_CR1_PE_M;
}
void HAL_I2C_Reset(I2C_HandleTypeDef *hi2c)
{
hi2c->ErrorCode = I2C_ERROR_NONE;
hi2c->Instance->CR1 &= ~I2C_CR1_PE_M;
hi2c->Instance->CR1 |= I2C_CR1_PE_M;
}
void HAL_I2C_Enable(I2C_HandleTypeDef *hi2c)
{
hi2c->Instance->CR1 |= I2C_CR1_PE_M;
}
void HAL_I2C_AnalogFilterInit(I2C_HandleTypeDef *hi2c, HAL_I2C_AnalogFilterTypeDef AnalogFilter)
{
hi2c->Init.AnalogFilter = AnalogFilter;
@@ -244,6 +226,24 @@ HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
return HAL_OK;
}
HAL_StatusTypeDef HAL_I2C_Deinit(I2C_HandleTypeDef *hi2c)
{
HAL_I2C_Disable(hi2c);
if (hi2c->Instance == I2C_0)
{
__HAL_PCC_I2C_0_CLK_DISABLE();
HAL_GPIO_PinConfig(GPIO_0, GPIO_PIN_9 | GPIO_PIN_10, HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
else if(hi2c->Instance == I2C_1)
{
__HAL_PCC_I2C_1_CLK_DISABLE();
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_12 | GPIO_PIN_13, HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
return HAL_OK;
}
void HAL_I2C_AutoEnd(I2C_HandleTypeDef *hi2c, HAL_I2C_AutoEndModeTypeDef AutoEnd)
{
hi2c->Instance->CR2 &= ~I2C_CR2_AUTOEND_M;
@@ -282,6 +282,49 @@ HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
return error_code;
}
/**
* @brief Установить новый делитель частоты
*
* @param hspi указатель на структуру SPI_HandleTypeDef, которая содержит
* информацию о конфигурации для модуля SPI.
* @param clockDiv делитель частоты в пределах от SPI_BAUDRATE_DIV4 до SPI_BAUDRATE_DIV256
*/
void HAL_SPI_Set_Clock_Divider(SPI_HandleTypeDef *hspi, uint8_t clockDiv)
{
uint32_t config = hspi->Instance->CONFIG;
HAL_SPI_Disable(hspi);
hspi->Init.BaudRateDiv = clockDiv;
config &= ~(0b111 << SPI_CONFIG_BAUD_RATE_DIV_S); // очистить
config |= (hspi->Init.BaudRateDiv << SPI_CONFIG_BAUD_RATE_DIV_S); // установить новое
hspi->Instance->CONFIG = config; // сохранить конфигурацию
HAL_SPI_Enable(hspi);
}
/**
* @brief Установить новый режим работы
*
* @param hspi указатель на структуру SPI_HandleTypeDef, которая содержит
* информацию о конфигурации для модуля SPI.
* @param CLKPhase фаза тактирующего сигнала:
* 1 - тактовая частота SPI неактивна вне слова,
* 0 - тактовая частота SPI активна вне слова
* @param CLKPolarity полярность тактирующего сигнала
* 1 - тактовый сигнал удерживается на высоком уровне,
* 0 - тактовый сигнал удерживается на низком уровне
*/
void HAL_SPI_Set_Clock_Mode(SPI_HandleTypeDef *hspi, uint8_t CLKPhase, uint8_t CLKPolarity)
{
uint32_t config = hspi->Instance->CONFIG;
HAL_SPI_Disable(hspi);
hspi->Init.CLKPhase = CLKPhase;
hspi->Init.CLKPolarity = CLKPolarity;
config &= ~((1 << SPI_CONFIG_CLK_PH_S) | (1 << SPI_CONFIG_CLK_POL_S)); // очистить
config |= ((hspi->Init.CLKPhase << SPI_CONFIG_CLK_PH_S) |
(hspi->Init.CLKPolarity << SPI_CONFIG_CLK_POL_S)); // установить новые значения
hspi->Instance->CONFIG = config; // сохранить конфигурацию
HAL_SPI_Enable(hspi);
}
/**
* @brief Очистить буфер TX_FIFO.
*
@@ -99,26 +99,6 @@ __attribute__((weak)) void HAL_TIMER16_MspInit(Timer16_HandleTypeDef* htimer16)
}
}
/**
* @brief Выключить таймер.
* Может использоваться для отключения таймера или при записи в регистр CFGR.
*
* @param htimer16 Указатель на структуру с настройками Timer16.
*/
void HAL_Timer16_Disable(Timer16_HandleTypeDef *htimer16)
{
htimer16->Instance->CR &= ~TIMER16_CR_ENABLE_M;
}
/**
* @brief Включить таймер
* @param htimer16 Указатель на структуру с настройками Timer16.
*/
void HAL_Timer16_Enable(Timer16_HandleTypeDef *htimer16)
{
htimer16->Instance->CR |= TIMER16_CR_ENABLE_M;
}
/**
* @brief Установить активный фронт для подсчёта или задать подрежим энкодера.
* Используется при тактировании Timer16 от внешнего источника тактового сигнала на выводе Input1.
@@ -78,6 +78,41 @@ HAL_StatusTypeDef HAL_Timer32_Init(TIMER32_HandleTypeDef *timer)
return HAL_OK;
}
HAL_StatusTypeDef HAL_Timer32_Deinit(TIMER32_HandleTypeDef *timer)
{
if ((timer->Instance != TIMER32_0) && (timer->Instance != TIMER32_1) && (timer->Instance != TIMER32_2))
{
return HAL_ERROR;
}
if (timer->Instance == TIMER32_0)
{
__HAL_PCC_TIMER32_0_CLK_DISABLE();
}
if (timer->Instance == TIMER32_1)
{
__HAL_PCC_TIMER32_1_CLK_DISABLE();
if (timer->Clock.Source == TIMER32_SOURCE_TX_PAD)
HAL_GPIO_PinConfig(GPIO_0, GPIO_PIN_4, HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
if (timer->Instance == TIMER32_2)
{
__HAL_PCC_TIMER32_2_CLK_DISABLE();
if (timer->Clock.Source == TIMER32_SOURCE_TX_PAD)
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_4, HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
HAL_Timer32_InterruptMask_Clear(timer, 0xFFFFFFFF);
HAL_Timer32_Prescaler_Set(timer, 0);
HAL_Timer32_InterruptFlags_ClearMask(timer, 0xFFFFFFFF);
HAL_Timer32_InterruptFlags_Clear(timer);
return HAL_OK;
}
void HAL_Timer32_State_Set(TIMER32_HandleTypeDef *timer, HAL_TIMER32_StateTypeDef state)
{
timer->State = state;
@@ -199,7 +234,7 @@ HAL_StatusTypeDef HAL_Timer32_Channel_Init(TIMER32_CHANNEL_HandleTypeDef *timerC
return HAL_ERROR;
}
HAL_TIMER32_Channel_MspInit(timerChannel);
// HAL_TIMER32_Channel_MspInit(timerChannel); // здесь инициализируются сразу все каналы выбранного таймера, а нам такого не надо
timerChannel->Instance = (TIMER32_CHANNEL_TypeDef *)&(timerChannel->TimerInstance->CHANNELS[timerChannel->ChannelIndex]);
@@ -220,6 +255,8 @@ HAL_StatusTypeDef HAL_Timer32_Channel_DeInit(TIMER32_CHANNEL_HandleTypeDef *time
return HAL_ERROR;
}
timerChannel->Instance = (TIMER32_CHANNEL_TypeDef *)&(timerChannel->TimerInstance->CHANNELS[timerChannel->ChannelIndex]);
HAL_Timer32_Channel_Disable(timerChannel);
HAL_Timer32_Channel_CaptureEdge_Set(timerChannel, 0);
HAL_Timer32_Channel_ICR_Clear(timerChannel);
+18 -30
View File
@@ -68,25 +68,8 @@ static TIMER32_HandleTypeDef htimer32;
static TIMER32_CHANNEL_HandleTypeDef htimer32_channel;
static uint32_t WriteValMax = WRITE_VAL_MAX_DEFAULT;
static uint32_t pwmTopVal = PWM_TOP_VAL_DEFAULT;
static bool pwmIsInited = false;
static uint8_t pwmIsInited = 0;
HAL_StatusTypeDef Timer32_Channel_Init(TIMER32_CHANNEL_HandleTypeDef *timerChannel)
{
if (timerChannel->TimerInstance == TIMER32_0)
return HAL_ERROR;
// gpio init removed from standard function
timerChannel->Instance = (TIMER32_CHANNEL_TypeDef *)&(timerChannel->TimerInstance->CHANNELS[timerChannel->ChannelIndex]);
HAL_Timer32_Channel_PWM_Invert_Set(timerChannel, timerChannel->PWM_Invert);
HAL_Timer32_Channel_Mode_Set(timerChannel, timerChannel->Mode);
HAL_Timer32_Channel_CaptureEdge_Set(timerChannel, timerChannel->CaptureEdge);
HAL_Timer32_Channel_OCR_Set(timerChannel, timerChannel->OCR);
HAL_Timer32_Channel_ICR_Clear(timerChannel);
HAL_Timer32_Channel_Noise_Set(timerChannel, timerChannel->Noise);
return HAL_OK;
}
/*
It is recommended to enable the timer in the following order:
@@ -120,15 +103,15 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal)
htimer32_channel.PWM_Invert = TIMER32_CHANNEL_NON_INVERTED_PWM;
htimer32_channel.Mode = TIMER32_CHANNEL_MODE_PWM;
htimer32_channel.CaptureEdge = TIMER32_CHANNEL_CAPTUREEDGE_RISING;
// cast to uint64_t to avoid overflow when multiplying
htimer32_channel.OCR = (uint32_t) (((uint64_t)pwmTopVal * writeVal) / WriteValMax);
htimer32_channel.Noise = TIMER32_CHANNEL_FILTER_OFF;
Timer32_Channel_Init(&htimer32_channel);
HAL_Timer32_Channel_Init(&htimer32_channel);
// start timer with initialized channel
HAL_Timer32_Channel_Enable(&htimer32_channel);
HAL_Timer32_Value_Clear(&htimer32);
HAL_Timer32_Start(&htimer32);
pwmIsInited = true; // if at least one channel is working, say that the module is initialized
pwmIsInited++; // increase inited channels qty
}
else if(PinNumber == 10) // pin d10 has pwm, but you cannot use it while spi is running
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
@@ -165,21 +148,26 @@ It is recommended to turn off the timer in the following order:
*/
void analogWriteStop(uint32_t PinNumber)
{
if (pwmIsInited)
if ((pwmIsInited > 0) && (digitalPinPwmIsOn(PinNumber)))
{
// load the timer address and channel number corresponding to the specified pin
htimer32.Instance = pwmPinToTimer(PinNumber);
htimer32_channel.TimerInstance = htimer32.Instance;
htimer32_channel.ChannelIndex = pwmPinToTimerChannel(PinNumber);
// in the initChannel function they do it inside, but in deinit they don't. We do it outside
htimer32_channel.Instance = (TIMER32_CHANNEL_TypeDef *)&(htimer32_channel.TimerInstance->CHANNELS[htimer32_channel.ChannelIndex]);
// и все чистим/отключаем
HAL_Timer32_InterruptMask_Clear(&htimer32, 0xFFFFFFFF);
HAL_Timer32_Prescaler_Set(&htimer32, 0);
HAL_Timer32_InterruptFlags_ClearMask(&htimer32, 0xFFFFFFFF);
// deinit channel
HAL_Timer32_Channel_DeInit(&htimer32_channel);
HAL_Timer32_Stop(&htimer32);
pwmIsInited = false;
pwmIsInited--; // decrease inited channels qty
// stop timer if no inited channels left
if (pwmIsInited == 0)
{
HAL_Timer32_Stop(&htimer32);
HAL_Timer32_Deinit(&htimer32);
}
// config pin as input when timer channel off
HAL_GPIO_PinConfig(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber),
HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
}