diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_gpio.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_gpio.h index e398583..bc3237d 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_gpio.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_gpio.h @@ -419,6 +419,17 @@ static inline __attribute__((always_inline)) void HAL_GPIO_TogglePin(GPIO_TypeDe 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 номер линии прерывания. diff --git a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_spi.h b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_spi.h index f95a8ec..4886377 100644 --- a/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_spi.h +++ b/cores/arduino/mik32/hal/peripherals/Include/mik32_hal_spi.h @@ -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 Разрешить прерывания в соответствии с маской. diff --git a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_spi.c b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_spi.c index 3c07a13..e70587e 100644 --- a/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_spi.c +++ b/cores/arduino/mik32/hal/peripherals/Source/mik32_hal_spi.c @@ -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. * diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 7a28066..3885866 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -1,5 +1,6 @@ #include "SPI.h" #include "mik32_hal_spi.h" +#include "utility/spiElbear.h" SPI_HandleTypeDef hspi; bool newConfig = false; @@ -50,54 +51,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; - if (direction == 1) // input - GPIO_1->DIRECTION_IN |= (1<DIRECTION_OUT |= (1<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; - GPIO_1->OUTPUT_ &= (~(0b1<OUTPUT_ |= ((state1_3&0b1)<PORT_1_CFG &= (~(0b11<<(2*PIN_1_3_GPIO_S))); // set config to 0 - common gpio mode + // // 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; - if (direction == 1) // input - GPIO_1->DIRECTION_IN |= (1<DIRECTION_OUT |= (1<DIRECTION_IN) & (1<> PIN_1_4_GPIO_S; + // if (direction == 1) // input + // GPIO_1->DIRECTION_IN |= (1<DIRECTION_OUT |= (1<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 + // // 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; - GPIO_1->OUTPUT_ &= (~(0b1<OUTPUT_ |= ((state1_4&0b1)<OUTPUT_) & (1<> PIN_1_4_GPIO_S; + // GPIO_1->OUTPUT_ &= (~(0b1<OUTPUT_ |= ((state1_4&0b1)<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) diff --git a/libraries/SPI/src/utility/spiElbear.cpp b/libraries/SPI/src/utility/spiElbear.cpp new file mode 100644 index 0000000..8ccb935 --- /dev/null +++ b/libraries/SPI/src/utility/spiElbear.cpp @@ -0,0 +1,49 @@ +#include "Arduino.h" +#include "spiElbear.h" +#include "mik32_hal_gpio.h" +#include "xprintf.h" + +// pins shift in registers +#define PIN_3_SHIFT 3 +#define PIN_4_SHIFT 4 +#define PORT1_GET_PAD_CONFIG(pinShift) ((PAD_CONFIG->PORT_1_CFG >> (pinShift<<1)) & 0b11) +#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 spiElbear_prepareBegin(void) +{ + // 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 = PORT1_GET_PAD_CONFIG(PIN_3_SHIFT); + if (config == 0) // common gpio + { + // pin direction + HAL_GPIO_ModeTypeDef pin3_direction = HAL_GPIO_GetPinDirection(GPIO_1, GPIO_PIN_3); + // pull up/down + HAL_GPIO_PullTypeDef pin3_pupd = (HAL_GPIO_PullTypeDef)PORT1_GET_PAD_PUPD(PIN_3_SHIFT); + //current state + uint8_t pin3_state = PORT1_GET_GPIO_STATE(PIN_3_SHIFT); + + // init and set state + HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_4, pin3_direction, pin3_pupd, HAL_GPIO_DS_2MA); + HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_4, pin3_state); + // todo ПРОВЕРИТЬ, что по факту устанавливается то, что я говорю в HAL_GPIO_PinConfig + + } + else if(config == 2) // timer for pwm + { + // вместо это возвращать что-то, что покажет, что это не gpio и снаружи выбросит предупреждение это + + // // 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(); +} \ No newline at end of file diff --git a/libraries/SPI/src/utility/spiElbear.h b/libraries/SPI/src/utility/spiElbear.h new file mode 100644 index 0000000..8367111 --- /dev/null +++ b/libraries/SPI/src/utility/spiElbear.h @@ -0,0 +1,2 @@ + +void spiElbear_prepareBegin(void); \ No newline at end of file