forked from Elron_dev/elbear_arduino_bsp
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:
parent
f020720e1f
commit
8f0a5b0a94
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
installed.json
|
||||
.vscode/
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
pwmIsInited--; // decrease inited channels qty
|
||||
|
||||
// stop timer if no inited channels left
|
||||
if (pwmIsInited == 0)
|
||||
{
|
||||
HAL_Timer32_Stop(&htimer32);
|
||||
pwmIsInited = false;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -50,53 +50,18 @@ void SPISettings::spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, ui
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
// pins shift in gpio register
|
||||
#define PIN_1_3_GPIO_S 3
|
||||
#define PIN_1_4_GPIO_S 4
|
||||
|
||||
|
||||
SPIClass SPI;
|
||||
bool SPIClass::spiInUse = false;
|
||||
uint8_t SPIClass::interruptMode = 0;
|
||||
uint8_t SPIClass::interruptMask = 0;
|
||||
|
||||
#define PAD_GET_PIN_CONFIG(port, pin) (((PAD_CONFIG->port) & (0b11<<(2*pin))) >> (2*pin))
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
// there is a seller on pin 1.6 which replace D10 from spi NSS pin 1.3 to pin 1.4,
|
||||
// because spi needs pin 1.3 for correct work
|
||||
|
||||
// replace config from 1.3 to 1.4
|
||||
uint8_t config = ((PAD_CONFIG->PORT_1_CFG) & (0b11<<(2*PIN_1_3_GPIO_S))) >> (2*PIN_1_3_GPIO_S);
|
||||
if (config == 0) // common gpio
|
||||
{
|
||||
// pin direction
|
||||
uint8_t direction = ((GPIO_1->DIRECTION_IN) & (1<<PIN_1_3_GPIO_S)) >> PIN_1_3_GPIO_S;
|
||||
if (direction == 1) // input
|
||||
GPIO_1->DIRECTION_IN |= (1<<PIN_1_4_GPIO_S);
|
||||
else // output
|
||||
GPIO_1->DIRECTION_OUT |= (1<<PIN_1_4_GPIO_S);
|
||||
|
||||
// pull up/down
|
||||
uint8_t pupd_1_3 = ((PAD_CONFIG ->PORT_1_PUPD) & (0b11<<(2*PIN_1_3_GPIO_S))) >> (2*PIN_1_3_GPIO_S);
|
||||
PAD_CONFIG ->PORT_1_PUPD &= (~(0b11<<(2*PIN_1_4_GPIO_S))); // clear
|
||||
PAD_CONFIG ->PORT_1_PUPD |= ((pupd_1_3&0b11)<<(2*PIN_1_4_GPIO_S)); // set new
|
||||
|
||||
//current state
|
||||
uint8_t state1_3 = ((GPIO_1->OUTPUT_) & (1<<PIN_1_3_GPIO_S)) >> PIN_1_3_GPIO_S;
|
||||
GPIO_1->OUTPUT_ &= (~(0b1<<PIN_1_4_GPIO_S)); // clear
|
||||
GPIO_1->OUTPUT_ |= ((state1_3&0b1)<<PIN_1_4_GPIO_S); // set new
|
||||
}
|
||||
else if(config == 2) // timer for pwm
|
||||
{
|
||||
// if D10 (spi NSS pin) was used as pwm, we need to stop timer,
|
||||
// because 1.4 don't support timer
|
||||
analogWriteStop(10);
|
||||
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
|
||||
}
|
||||
|
||||
// switch seller to pin 1.4
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_6, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_HIGH);
|
||||
blockSpiPin();
|
||||
spi_onBegin();
|
||||
|
||||
spiInUse = true;
|
||||
}
|
||||
@ -115,29 +80,7 @@ void SPIClass::end()
|
||||
HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
}
|
||||
|
||||
// return D10 with common gpio config to pin 1.3
|
||||
PAD_CONFIG->PORT_1_CFG &= (~(0b11<<(2*PIN_1_3_GPIO_S))); // set config to 0 - common gpio mode
|
||||
|
||||
// pin direction
|
||||
uint8_t direction = ((GPIO_1->DIRECTION_IN) & (1<<PIN_1_4_GPIO_S)) >> PIN_1_4_GPIO_S;
|
||||
if (direction == 1) // input
|
||||
GPIO_1->DIRECTION_IN |= (1<<PIN_1_3_GPIO_S);
|
||||
else // output
|
||||
GPIO_1->DIRECTION_OUT |= (1<<PIN_1_3_GPIO_S);
|
||||
|
||||
// pull up/down
|
||||
uint8_t pupd_1_4 = ((PAD_CONFIG ->PORT_1_PUPD) & (0b11<<(2*PIN_1_4_GPIO_S))) >> (2*PIN_1_4_GPIO_S);
|
||||
PAD_CONFIG ->PORT_1_PUPD &= (~(0b11<<(2*PIN_1_3_GPIO_S))); // clear
|
||||
PAD_CONFIG ->PORT_1_PUPD |= ((pupd_1_4&0b11)<<(2*PIN_1_3_GPIO_S)); // set new
|
||||
|
||||
// current state
|
||||
uint8_t state1_4 = ((GPIO_1->OUTPUT_) & (1<<PIN_1_4_GPIO_S)) >> PIN_1_4_GPIO_S;
|
||||
GPIO_1->OUTPUT_ &= (~(0b1<<PIN_1_3_GPIO_S)); // clear
|
||||
GPIO_1->OUTPUT_ |= ((state1_4&0b1)<<PIN_1_3_GPIO_S); // set new
|
||||
|
||||
// switch seller back to pin 1.3
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_LOW);
|
||||
unblockSpiPin();
|
||||
spi_onEnd();
|
||||
|
||||
spiInUse = false;
|
||||
isInited = false;
|
||||
@ -304,30 +247,22 @@ void SPIClass::setBitOrder(uint8_t bitOrder)
|
||||
|
||||
void SPIClass::setDataMode(uint8_t dataMode)
|
||||
{
|
||||
uint32_t config = hspi.Instance->CONFIG;
|
||||
HAL_SPI_Disable(&hspi);
|
||||
hspi.Init.CLKPhase = dataMode & 0b00000001;
|
||||
hspi.Init.CLKPolarity = (dataMode & 0b00000010)>>1;
|
||||
config &= ~((1 << SPI_CONFIG_CLK_PH_S) | (1 << SPI_CONFIG_CLK_POL_S)); // clear
|
||||
config |= ((hspi.Init.CLKPhase << SPI_CONFIG_CLK_PH_S) |
|
||||
(hspi.Init.CLKPolarity << SPI_CONFIG_CLK_POL_S)); // set new
|
||||
hspi.Instance->CONFIG = config;
|
||||
HAL_SPI_Enable(&hspi);
|
||||
// ClkPhase ClkPolarity
|
||||
HAL_SPI_Set_Clock_Mode(&hspi, (dataMode&0b00000001), (dataMode&0b00000010)>>1);
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint8_t clockDiv)
|
||||
{
|
||||
// if divider is in valid range
|
||||
if ((clockDiv >= SPI_CLOCK_DIV4) && (clockDiv <= SPI_CLOCK_DIV256))
|
||||
// if divider is valid
|
||||
if ((clockDiv == SPI_CLOCK_DIV4) || (clockDiv == SPI_CLOCK_DIV8) ||
|
||||
(clockDiv == SPI_CLOCK_DIV16) || (clockDiv == SPI_CLOCK_DIV32) ||
|
||||
(clockDiv == SPI_CLOCK_DIV64) || (clockDiv == SPI_CLOCK_DIV128) ||
|
||||
(clockDiv == SPI_CLOCK_DIV256))
|
||||
{
|
||||
uint32_t config = hspi.Instance->CONFIG;
|
||||
HAL_SPI_Disable(&hspi);
|
||||
hspi.Init.BaudRateDiv = clockDiv;
|
||||
config &= ~(0b111 << SPI_CONFIG_BAUD_RATE_DIV_S); // clear
|
||||
config |= (hspi.Init.BaudRateDiv << SPI_CONFIG_BAUD_RATE_DIV_S); // set new
|
||||
hspi.Instance->CONFIG = config;
|
||||
HAL_SPI_Enable(&hspi);
|
||||
HAL_SPI_Set_Clock_Divider(&hspi, clockDiv);
|
||||
}
|
||||
else
|
||||
ErrorMsgHandler("SPI.setClockDivider(): Invalid clock devider");
|
||||
}
|
||||
|
||||
static uint8_t reverse_bits(uint8_t byte)
|
||||
|
||||
@ -88,36 +88,22 @@ void twi_deinit(void)
|
||||
{
|
||||
uint32_t EPICmask;
|
||||
|
||||
HAL_I2C_Disable(&hi2c);
|
||||
// disable clock
|
||||
#if I2C_NUM == 0
|
||||
hi2c.Instance = I2C_0;
|
||||
EPICmask = HAL_EPIC_I2C_0_MASK;
|
||||
__HAL_PCC_I2C_0_CLK_DISABLE();
|
||||
#elif I2C_NUM == 1
|
||||
hi2c.Instance = I2C_1;
|
||||
EPICmask = HAL_EPIC_I2C_1_MASK;
|
||||
__HAL_PCC_I2C_1_CLK_DISABLE();
|
||||
#else
|
||||
#error "Unsupported I2C_NUM value in pins_arduino.h"
|
||||
#endif
|
||||
|
||||
HAL_I2C_Deinit(&hi2c);
|
||||
|
||||
// for slave mode disable interrupts from i2c
|
||||
if (hi2c.Init.Mode == HAL_I2C_MODE_SLAVE)
|
||||
HAL_EPIC_MaskLevelClear(EPICmask);
|
||||
|
||||
// reconfigure pins to z state
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
memset(&GPIO_InitStruct, 0, sizeof(GPIO_InitStruct));
|
||||
// SDA
|
||||
GPIO_InitStruct.Pin = (HAL_PinsTypeDef)digitalPinToBitMask(PIN_WIRE_SDA);
|
||||
GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
|
||||
GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
|
||||
HAL_GPIO_Init(digitalPinToPort(PIN_WIRE_SDA), &GPIO_InitStruct);
|
||||
// SCL
|
||||
GPIO_InitStruct.Pin = (HAL_PinsTypeDef)digitalPinToBitMask(PIN_WIRE_SCL);
|
||||
HAL_GPIO_Init(digitalPinToPort(PIN_WIRE_SCL), &GPIO_InitStruct);
|
||||
|
||||
twiIsOn = false;
|
||||
}
|
||||
|
||||
@ -252,7 +238,7 @@ uint8_t twi_masterWriteTo(uint8_t address, uint8_t* data, uint8_t length, uint8_
|
||||
|
||||
// parse errors
|
||||
// check separately, because in hal libraries not all functions look at this
|
||||
if (hi2c.Instance->ISR & I2C_ISR_NACKF_M)
|
||||
if (HAL_I2C_Get_Interrupts_Status(&hi2c) & I2C_ISR_NACKF_M)
|
||||
hi2c.ErrorCode = I2C_ERROR_NACK;
|
||||
if (hi2c.ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_TIMEOUT) ret = I2C_TIMEOUT; // timeout
|
||||
else if (hi2c.ErrorCode == (HAL_I2C_ErrorTypeDef)I2C_ERROR_NACK) ret = I2C_NACK_DATA; // didn't receive ACK
|
||||
@ -275,39 +261,35 @@ i2c_status_e twi_slaveWrite(uint8_t *txData, uint8_t bytesNum)
|
||||
if ((hi2c.ErrorCode != I2C_ERROR_NONE))
|
||||
HAL_I2C_Reset(&hi2c);
|
||||
|
||||
// отправка данных
|
||||
// send data
|
||||
HAL_StatusTypeDef error_code = HAL_OK;
|
||||
HAL_I2C_Clear_Reload(&hi2c);
|
||||
if (!(HAL_I2C_Get_CR1_Content(&hi2c) & I2C_CR1_NOSTRETCH_M)) // NOSTRETCH = 0
|
||||
HAL_I2C_Reset_TXDR_Content(&hi2c);
|
||||
HAL_I2C_Write_TXDR(&hi2c, txData[0]); // first recording is made in advance
|
||||
|
||||
hi2c.Instance->CR2 &= ~I2C_CR2_RELOAD_M;
|
||||
|
||||
if (!(hi2c.Instance->CR1 & I2C_CR1_NOSTRETCH_M)) // NOSTRETCH = 0
|
||||
hi2c.Instance->ISR |= I2C_ISR_TXE_M; // Reset TXDR contents
|
||||
|
||||
hi2c.Instance->TXDR = txData[0]; // The first recording is made in advance
|
||||
|
||||
// Запись байта
|
||||
// write byte
|
||||
for (uint32_t tx_count = 1; tx_count < bytesNum; tx_count++)
|
||||
{
|
||||
if ((error_code = HAL_I2C_Slave_WaitTXIS(&hi2c, TIMEOUT_TICKS)) != HAL_OK)
|
||||
{
|
||||
// неудачная запись
|
||||
hi2c.Instance->ISR |= I2C_ISR_TXE_M; // Reset TXDR contents
|
||||
hi2c.Instance->ICR |= I2C_ICR_STOPCF_M; // Clear the STOP detection flag on the bus
|
||||
// failed to write
|
||||
HAL_I2C_Reset_TXDR_Content(&hi2c);
|
||||
HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus
|
||||
HAL_I2C_Reset(&hi2c);
|
||||
return I2C_TIMEOUT;
|
||||
}
|
||||
hi2c.Instance->TXDR = txData[tx_count];
|
||||
HAL_I2C_Write_TXDR(&hi2c, txData[tx_count]);
|
||||
}
|
||||
|
||||
if ((error_code = HAL_I2C_WaitBusy(&hi2c, TIMEOUT_TICKS)) != HAL_OK)
|
||||
{
|
||||
// неудачное завершение транзакции
|
||||
// failed to complete transaction
|
||||
HAL_I2C_Reset(&hi2c);
|
||||
return I2C_TIMEOUT;
|
||||
}
|
||||
|
||||
hi2c.Instance->ISR |= I2C_ISR_TXE_M; // Reset TXDR contents
|
||||
hi2c.Instance->ICR |= I2C_ICR_STOPCF_M; // Clear the STOP detection flag on the bus
|
||||
HAL_I2C_Reset_TXDR_Content(&hi2c);
|
||||
HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus
|
||||
|
||||
return I2C_OK;
|
||||
}
|
||||
@ -343,25 +325,24 @@ void twi_attachSlaveTxEvent( void (*function)(void) )
|
||||
*/
|
||||
void twi_interruptHandler(void)
|
||||
{
|
||||
uint32_t int_mask = hi2c.Instance->CR1 & I2C_INTMASK; // interrupts allowed
|
||||
uint32_t interrupt_status = hi2c.Instance->ISR; // current flags
|
||||
uint32_t int_mask = HAL_I2C_Get_CR1_Content(&hi2c) & I2C_INTMASK; // interrupts allowed
|
||||
uint32_t interrupt_status = HAL_I2C_Get_Interrupts_Status(&hi2c); // current flags
|
||||
|
||||
// master calls by address, device in slave mode
|
||||
if ((interrupt_status & I2C_ISR_ADDR_M) && (int_mask & I2C_CR1_ADDRIE_M))
|
||||
{
|
||||
// reset ADDR flag
|
||||
hi2c.Instance->ICR |= I2C_ICR_ADDRCF_M;
|
||||
HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_ADDRCF_M);
|
||||
|
||||
// look at the transmission direction and respond to the request
|
||||
if (interrupt_status & I2C_ISR_DIR_M) // master reads, slave sends
|
||||
// отправляем данные
|
||||
twi_onSlaveTransmit();
|
||||
twi_onSlaveTransmit(); // slave send data
|
||||
else // master writes, slave reads
|
||||
{
|
||||
twi_rxBufferIndex = 0; // write from the beginning of the buffer
|
||||
hi2c.State = HAL_I2C_STATE_BUSY;
|
||||
hi2c.Instance->CR2 &= ~I2C_CR2_RELOAD_M;
|
||||
// wait for interrupts because of receiving a byte or a stop condition
|
||||
HAL_I2C_Clear_Reload(&hi2c);
|
||||
// wait for interrupts by receiving a byte or a stop condition
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,15 +350,15 @@ void twi_interruptHandler(void)
|
||||
if ((interrupt_status & I2C_ISR_RXNE_M) && (int_mask & I2C_CR1_RXIE_M))
|
||||
{
|
||||
// put new byte into buffer
|
||||
twi_rxBuffer[twi_rxBufferIndex++] = (uint8_t)hi2c.Instance->RXDR;
|
||||
twi_rxBuffer[twi_rxBufferIndex++] = HAL_I2C_Get_RXDR(&hi2c);
|
||||
}
|
||||
|
||||
// master sent a STOP to the bus
|
||||
if ((interrupt_status & I2C_ISR_STOPF_M) && (int_mask & I2C_CR1_STOPIE_M))
|
||||
{
|
||||
hi2c.State = HAL_I2C_STATE_END;
|
||||
hi2c.Instance->ISR |= I2C_ISR_TXE_M; // Reset TXDR contents
|
||||
hi2c.Instance->ICR |= I2C_ICR_STOPCF_M; // Clear the STOP detection flag on the bus
|
||||
HAL_I2C_Reset_TXDR_Content(&hi2c);
|
||||
HAL_I2C_Reset_Interrupt_Flag(&hi2c, I2C_ICR_STOPCF_M); // Clear the STOP detection flag on the bus
|
||||
// pass the received data to callback function
|
||||
twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex);
|
||||
}
|
||||
|
||||
@ -32,8 +32,6 @@ extern "C" {
|
||||
#include "mik32_hal_gpio.h"
|
||||
#include "mik32_hal_timer32.h"
|
||||
|
||||
extern bool spiNssPinIsBlocked;
|
||||
|
||||
// analog pins
|
||||
#define PIN_A0 (14)
|
||||
#define PIN_A1 (15)
|
||||
@ -78,6 +76,7 @@ uint32_t analogInputToChannelNumber(uint32_t PinNumber);
|
||||
|
||||
// PWM
|
||||
bool digitalPinHasPWM(uint8_t p);
|
||||
bool digitalPinPwmIsOn(uint8_t digitalPin); // use only if digitalPinHasPWM() == true
|
||||
// determines which timer the pin belongs to
|
||||
TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber);
|
||||
// determines which timer channel the pin belongs to
|
||||
@ -94,19 +93,13 @@ static const uint8_t MISO = PIN_SPI_MISO;
|
||||
static const uint8_t SCK = PIN_SPI_SCK;
|
||||
// config SEL_NSS1 to replace D10 to different controller pin,
|
||||
// because pin 1.3 which is D10 by default is needed to spi
|
||||
inline void blockSpiPin(void)
|
||||
{
|
||||
spiNssPinIsBlocked = true;
|
||||
}
|
||||
inline void unblockSpiPin(void)
|
||||
{
|
||||
spiNssPinIsBlocked = false;
|
||||
}
|
||||
void spi_onBegin(void);
|
||||
void spi_onEnd(void);
|
||||
|
||||
// I2C
|
||||
#define PIN_WIRE_SDA (18)
|
||||
#define PIN_WIRE_SCL (19)
|
||||
#define I2C_NUM (1) // i2c number 0 or 1
|
||||
#define I2C_NUM (1) // i2c number 1
|
||||
static const uint8_t SDA = PIN_WIRE_SDA;
|
||||
static const uint8_t SCL = PIN_WIRE_SCL;
|
||||
// available frequencies
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "pins_arduino.h"
|
||||
#include "mik32_hal_adc.h"
|
||||
#include "wiring_analog.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -106,6 +107,10 @@ volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x)
|
||||
return &GPIO_x->STATE;
|
||||
}
|
||||
|
||||
// return config of pin with pinShift(0...16) in portReg (config, pupd, ds for ports 0...2)
|
||||
#define PIN_PAD_CONFIG(portReg, pinShift) ((PAD_CONFIG->portReg >> (pinShift<<1)) & 0b11)
|
||||
|
||||
|
||||
// ---------------------- ADC ---------------------- //
|
||||
// determines the ADC channel number by the board pin number
|
||||
uint32_t analogInputToChannelNumber(uint32_t PinNumber)
|
||||
@ -141,6 +146,38 @@ 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;
|
||||
}
|
||||
// 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);
|
||||
|
||||
if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0)
|
||||
config = PIN_PAD_CONFIG(PORT_0_CFG, pinShift);
|
||||
else
|
||||
config = PIN_PAD_CONFIG(PORT_1_CFG, pinShift);
|
||||
|
||||
if (config == 2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool digitalPinHasPWM(uint8_t p)
|
||||
{
|
||||
bool ret = false;
|
||||
@ -226,3 +263,51 @@ int8_t digitalPinToInterrupt(uint32_t digPinNumber)
|
||||
}
|
||||
return NOT_AN_INTERRUPT;
|
||||
}
|
||||
|
||||
// ---------------------- SPI ---------------------- //
|
||||
// pins shift in registers
|
||||
#define PIN_3_SHIFT 3
|
||||
#define PIN_4_SHIFT 4
|
||||
#define PORT1_GET_PAD_PUPD(pinShift) ((PAD_CONFIG->PORT_1_PUPD >> (pinShift<<1)) & 0b11)
|
||||
#define PORT1_GET_GPIO_STATE(pinShift) ((GPIO_1->OUTPUT_ >> pinShift) & 0b1)
|
||||
|
||||
void spi_onBegin(void)
|
||||
{
|
||||
// On Elbear Ace-Uno rev1.1.0 there is a seller on pin 1.6 which replace D10 from spi NSS pin 1.3 to pin 1.4,
|
||||
// because spi needs pin 1.3 for correct work
|
||||
|
||||
// replace config from 1.3 to 1.4
|
||||
uint8_t config = PIN_PAD_CONFIG(PORT_1_CFG, PIN_3_SHIFT);
|
||||
if (config == 0) // common gpio
|
||||
{
|
||||
// get info from pin gpio1.3 and set config to gpio1.4
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_4, HAL_GPIO_GetPinDirection(GPIO_1, GPIO_PIN_3),
|
||||
(HAL_GPIO_PullTypeDef)PORT1_GET_PAD_PUPD(PIN_3_SHIFT), HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_4, (GPIO_PinState)PORT1_GET_GPIO_STATE(PIN_3_SHIFT));
|
||||
|
||||
// pin D10 was switched to different gpio and can be used further
|
||||
}
|
||||
else if(config == 2) // timer for pwm
|
||||
{
|
||||
// if D10 (spi NSS pin) was used as pwm, we need to stop timer, because 1.4 don't support it
|
||||
analogWriteStop(10);
|
||||
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
|
||||
}
|
||||
|
||||
// switch seller to pin 1.4
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_6, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_HIGH);
|
||||
spiNssPinIsBlocked = true; // block spi pin
|
||||
}
|
||||
|
||||
void spi_onEnd(void)
|
||||
{
|
||||
// get info from pin gpio1.4 and set config to gpio1.3
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_3, HAL_GPIO_GetPinDirection(GPIO_1, GPIO_PIN_4),
|
||||
(HAL_GPIO_PullTypeDef)PORT1_GET_PAD_PUPD(PIN_4_SHIFT), HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_3, (GPIO_PinState)PORT1_GET_GPIO_STATE(PIN_4_SHIFT));
|
||||
|
||||
// switch seller back to pin 1.3
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_LOW);
|
||||
spiNssPinIsBlocked = false; // unblock spi pin
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user