Merge branch 'qmk-pre-merge-2021-09-12' into qmk-merge-2021-09-12
This commit is contained in:
commit
cf548ab9e6
10266 files changed
+209325
-91259
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32F401xC memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 (rx) : org = 0x08000000 + 64k, len = 256k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */
|
||||
flash1 (rx) : org = 0x00000000, len = 0
|
||||
flash2 (rx) : org = 0x00000000, len = 0
|
||||
flash3 (rx) : org = 0x00000000, len = 0
|
||||
flash4 (rx) : org = 0x00000000, len = 0
|
||||
flash5 (rx) : org = 0x00000000, len = 0
|
||||
flash6 (rx) : org = 0x00000000, len = 0
|
||||
flash7 (rx) : org = 0x00000000, len = 0
|
||||
ram0 (wx) : org = 0x20000000, len = 64k
|
||||
ram1 (wx) : org = 0x00000000, len = 0
|
||||
ram2 (wx) : org = 0x00000000, len = 0
|
||||
ram3 (wx) : org = 0x00000000, len = 0
|
||||
ram4 (wx) : org = 0x00000000, len = 0
|
||||
ram5 (wx) : org = 0x00000000, len = 0
|
||||
ram6 (wx) : org = 0x00000000, len = 0
|
||||
ram7 (wx) : org = 0x00000000, len = 0
|
||||
}
|
||||
|
||||
/* For each data/text section two region are defined, a virtual region
|
||||
and a load region (_LMA suffix).*/
|
||||
|
||||
/* Flash region to be used for exception vectors.*/
|
||||
REGION_ALIAS("VECTORS_FLASH", flash0);
|
||||
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for constructors and destructors.*/
|
||||
REGION_ALIAS("XTORS_FLASH", flash0);
|
||||
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for code text.*/
|
||||
REGION_ALIAS("TEXT_FLASH", flash0);
|
||||
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for read only data.*/
|
||||
REGION_ALIAS("RODATA_FLASH", flash0);
|
||||
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for various.*/
|
||||
REGION_ALIAS("VARIOUS_FLASH", flash0);
|
||||
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for RAM(n) initialization data.*/
|
||||
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for Main stack. This stack accommodates the processing
|
||||
of all exceptions and interrupts.*/
|
||||
REGION_ALIAS("MAIN_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the process stack. This is the stack used by
|
||||
the main() function.*/
|
||||
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for data segment.*/
|
||||
REGION_ALIAS("DATA_RAM", ram0);
|
||||
REGION_ALIAS("DATA_RAM_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for BSS segment.*/
|
||||
REGION_ALIAS("BSS_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the default heap.*/
|
||||
REGION_ALIAS("HEAP_RAM", ram0);
|
||||
|
||||
/* Generic rules inclusion.*/
|
||||
INCLUDE rules.ld
|
||||
|
||||
/* TinyUF2 bootloader reset support */
|
||||
_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32F401xE memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 (rx) : org = 0x08000000 + 64k, len = 512k - 64k /* tinyuf2 bootloader requires app to be located at 64k offset for this MCU */
|
||||
flash1 (rx) : org = 0x00000000, len = 0
|
||||
flash2 (rx) : org = 0x00000000, len = 0
|
||||
flash3 (rx) : org = 0x00000000, len = 0
|
||||
flash4 (rx) : org = 0x00000000, len = 0
|
||||
flash5 (rx) : org = 0x00000000, len = 0
|
||||
flash6 (rx) : org = 0x00000000, len = 0
|
||||
flash7 (rx) : org = 0x00000000, len = 0
|
||||
ram0 (wx) : org = 0x20000000, len = 96k
|
||||
ram1 (wx) : org = 0x00000000, len = 0
|
||||
ram2 (wx) : org = 0x00000000, len = 0
|
||||
ram3 (wx) : org = 0x00000000, len = 0
|
||||
ram4 (wx) : org = 0x00000000, len = 0
|
||||
ram5 (wx) : org = 0x00000000, len = 0
|
||||
ram6 (wx) : org = 0x00000000, len = 0
|
||||
ram7 (wx) : org = 0x00000000, len = 0
|
||||
}
|
||||
|
||||
/* For each data/text section two region are defined, a virtual region
|
||||
and a load region (_LMA suffix).*/
|
||||
|
||||
/* Flash region to be used for exception vectors.*/
|
||||
REGION_ALIAS("VECTORS_FLASH", flash0);
|
||||
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for constructors and destructors.*/
|
||||
REGION_ALIAS("XTORS_FLASH", flash0);
|
||||
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for code text.*/
|
||||
REGION_ALIAS("TEXT_FLASH", flash0);
|
||||
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for read only data.*/
|
||||
REGION_ALIAS("RODATA_FLASH", flash0);
|
||||
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for various.*/
|
||||
REGION_ALIAS("VARIOUS_FLASH", flash0);
|
||||
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for RAM(n) initialization data.*/
|
||||
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for Main stack. This stack accommodates the processing
|
||||
of all exceptions and interrupts.*/
|
||||
REGION_ALIAS("MAIN_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the process stack. This is the stack used by
|
||||
the main() function.*/
|
||||
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for data segment.*/
|
||||
REGION_ALIAS("DATA_RAM", ram0);
|
||||
REGION_ALIAS("DATA_RAM_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for BSS segment.*/
|
||||
REGION_ALIAS("BSS_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the default heap.*/
|
||||
REGION_ALIAS("HEAP_RAM", ram0);
|
||||
|
||||
/* Generic rules inclusion.*/
|
||||
INCLUDE rules.ld
|
||||
|
||||
/* TinyUF2 bootloader reset support */
|
||||
_board_dfu_dbl_tap = ORIGIN(ram0) + 64k - 4; /* this is based off the linker file for tinyuf2 */
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,9 @@
|
||||
# List of all the board related files.
|
||||
BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY/board.c
|
||||
|
||||
# Required include directories
|
||||
BOARDINC = $(CHIBIOS)/os/hal/boards/ST_STM32F4_DISCOVERY
|
||||
|
||||
# Shared variables
|
||||
ALLCSRC += $(BOARDSRC)
|
||||
ALLINC += $(BOARDINC)
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define STM32_HSECLK 8000000
|
||||
// The following is required to disable the pull-down on PA9, when PA9 is used for the keyboard matrix:
|
||||
#define BOARD_OTG_NOVBUSSENS
|
||||
|
||||
#include_next "board.h"
|
||||
|
||||
#undef STM32_HSE_BYPASS
|
||||
File renamed without changes.
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MCUCONF_H
|
||||
#define MCUCONF_H
|
||||
|
||||
/*
|
||||
* STM32F4xx drivers configuration.
|
||||
* The following settings override the default settings present in
|
||||
* the various device driver implementation headers.
|
||||
* Note that the settings for each driver only have effect if the whole
|
||||
* driver is enabled in halconf.h.
|
||||
*
|
||||
* IRQ priorities:
|
||||
* 15...0 Lowest...Highest.
|
||||
*
|
||||
* DMA priorities:
|
||||
* 0...3 Lowest...Highest.
|
||||
*/
|
||||
|
||||
#define STM32F4xx_MCUCONF
|
||||
#define STM32F405_MCUCONF
|
||||
#define STM32F415_MCUCONF
|
||||
#define STM32F407_MCUCONF
|
||||
#define STM32F417_MCUCONF
|
||||
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
#define STM32_NO_INIT FALSE
|
||||
#define STM32_PVD_ENABLE FALSE
|
||||
#define STM32_PLS STM32_PLS_LEV0
|
||||
#define STM32_BKPRAM_ENABLE FALSE
|
||||
#define STM32_HSI_ENABLED TRUE
|
||||
#define STM32_LSI_ENABLED TRUE
|
||||
#define STM32_HSE_ENABLED TRUE
|
||||
#define STM32_LSE_ENABLED FALSE
|
||||
#define STM32_CLOCK48_REQUIRED TRUE
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_PLLM_VALUE 8
|
||||
#define STM32_PLLN_VALUE 336
|
||||
#define STM32_PLLP_VALUE 2
|
||||
#define STM32_PLLQ_VALUE 7
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV4
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||
#define STM32_RTCSEL STM32_RTCSEL_LSI
|
||||
#define STM32_RTCPRE_VALUE 8
|
||||
#define STM32_MCO1SEL STM32_MCO1SEL_HSI
|
||||
#define STM32_MCO1PRE STM32_MCO1PRE_DIV1
|
||||
#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK
|
||||
#define STM32_MCO2PRE STM32_MCO2PRE_DIV5
|
||||
#define STM32_I2SSRC STM32_I2SSRC_CKIN
|
||||
#define STM32_PLLI2SN_VALUE 192
|
||||
#define STM32_PLLI2SR_VALUE 5
|
||||
|
||||
/*
|
||||
* IRQ system settings.
|
||||
*/
|
||||
#define STM32_IRQ_EXTI0_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI2_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI3_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI4_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI5_9_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI10_15_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI16_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI17_PRIORITY 15
|
||||
#define STM32_IRQ_EXTI18_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI19_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI20_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI21_PRIORITY 15
|
||||
#define STM32_IRQ_EXTI22_PRIORITY 15
|
||||
|
||||
/*
|
||||
* ADC driver system settings.
|
||||
*/
|
||||
#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4
|
||||
#define STM32_ADC_USE_ADC1 FALSE
|
||||
#define STM32_ADC_USE_ADC2 FALSE
|
||||
#define STM32_ADC_USE_ADC3 FALSE
|
||||
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
|
||||
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
|
||||
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
|
||||
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC2_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC3_DMA_PRIORITY 2
|
||||
#define STM32_ADC_IRQ_PRIORITY 6
|
||||
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6
|
||||
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6
|
||||
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6
|
||||
|
||||
/*
|
||||
* CAN driver system settings.
|
||||
*/
|
||||
#define STM32_CAN_USE_CAN1 FALSE
|
||||
#define STM32_CAN_USE_CAN2 FALSE
|
||||
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
|
||||
#define STM32_CAN_CAN2_IRQ_PRIORITY 11
|
||||
|
||||
/*
|
||||
* DAC driver system settings.
|
||||
*/
|
||||
#define STM32_DAC_DUAL_MODE FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH1 FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH2 FALSE
|
||||
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
|
||||
#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
|
||||
/*
|
||||
* GPT driver system settings.
|
||||
*/
|
||||
#define STM32_GPT_USE_TIM1 FALSE
|
||||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM3 FALSE
|
||||
#define STM32_GPT_USE_TIM4 FALSE
|
||||
#define STM32_GPT_USE_TIM5 FALSE
|
||||
#define STM32_GPT_USE_TIM6 FALSE
|
||||
#define STM32_GPT_USE_TIM7 FALSE
|
||||
#define STM32_GPT_USE_TIM8 FALSE
|
||||
#define STM32_GPT_USE_TIM9 FALSE
|
||||
#define STM32_GPT_USE_TIM11 FALSE
|
||||
#define STM32_GPT_USE_TIM12 FALSE
|
||||
#define STM32_GPT_USE_TIM14 FALSE
|
||||
#define STM32_GPT_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM9_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM11_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM12_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM14_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* I2C driver system settings.
|
||||
*/
|
||||
#define STM32_I2C_USE_I2C1 FALSE
|
||||
#define STM32_I2C_USE_I2C2 FALSE
|
||||
#define STM32_I2C_USE_I2C3 FALSE
|
||||
#define STM32_I2C_BUSY_TIMEOUT 50
|
||||
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
|
||||
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
|
||||
#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
|
||||
#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
#define STM32_I2C_I2C1_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C2_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C3_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C1_DMA_PRIORITY 3
|
||||
#define STM32_I2C_I2C2_DMA_PRIORITY 3
|
||||
#define STM32_I2C_I2C3_DMA_PRIORITY 3
|
||||
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* I2S driver system settings.
|
||||
*/
|
||||
#define STM32_I2S_USE_SPI2 FALSE
|
||||
#define STM32_I2S_USE_SPI3 FALSE
|
||||
#define STM32_I2S_SPI2_IRQ_PRIORITY 10
|
||||
#define STM32_I2S_SPI3_IRQ_PRIORITY 10
|
||||
#define STM32_I2S_SPI2_DMA_PRIORITY 1
|
||||
#define STM32_I2S_SPI3_DMA_PRIORITY 1
|
||||
#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
|
||||
#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
|
||||
#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ICU driver system settings.
|
||||
*/
|
||||
#define STM32_ICU_USE_TIM1 FALSE
|
||||
#define STM32_ICU_USE_TIM2 FALSE
|
||||
#define STM32_ICU_USE_TIM3 FALSE
|
||||
#define STM32_ICU_USE_TIM4 FALSE
|
||||
#define STM32_ICU_USE_TIM5 FALSE
|
||||
#define STM32_ICU_USE_TIM8 FALSE
|
||||
#define STM32_ICU_USE_TIM9 FALSE
|
||||
#define STM32_ICU_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM8_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM9_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* MAC driver system settings.
|
||||
*/
|
||||
#define STM32_MAC_TRANSMIT_BUFFERS 2
|
||||
#define STM32_MAC_RECEIVE_BUFFERS 4
|
||||
#define STM32_MAC_BUFFERS_SIZE 1522
|
||||
#define STM32_MAC_PHY_TIMEOUT 100
|
||||
#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE
|
||||
#define STM32_MAC_ETH1_IRQ_PRIORITY 13
|
||||
#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0
|
||||
|
||||
/*
|
||||
* PWM driver system settings.
|
||||
*/
|
||||
#define STM32_PWM_USE_ADVANCED FALSE
|
||||
#define STM32_PWM_USE_TIM1 FALSE
|
||||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM3 FALSE
|
||||
#define STM32_PWM_USE_TIM4 FALSE
|
||||
#define STM32_PWM_USE_TIM5 FALSE
|
||||
#define STM32_PWM_USE_TIM8 FALSE
|
||||
#define STM32_PWM_USE_TIM9 FALSE
|
||||
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM5_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM9_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
#define STM32_RTC_PRESA_VALUE 32
|
||||
#define STM32_RTC_PRESS_VALUE 1024
|
||||
#define STM32_RTC_CR_INIT 0
|
||||
#define STM32_RTC_TAMPCR_INIT 0
|
||||
|
||||
/*
|
||||
* SDC driver system settings.
|
||||
*/
|
||||
#define STM32_SDC_SDIO_DMA_PRIORITY 3
|
||||
#define STM32_SDC_SDIO_IRQ_PRIORITY 9
|
||||
#define STM32_SDC_WRITE_TIMEOUT_MS 1000
|
||||
#define STM32_SDC_READ_TIMEOUT_MS 1000
|
||||
#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10
|
||||
#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE
|
||||
#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
|
||||
|
||||
/*
|
||||
* SERIAL driver system settings.
|
||||
*/
|
||||
#define STM32_SERIAL_USE_USART1 FALSE
|
||||
#define STM32_SERIAL_USE_USART2 FALSE
|
||||
#define STM32_SERIAL_USE_USART3 FALSE
|
||||
#define STM32_SERIAL_USE_UART4 FALSE
|
||||
#define STM32_SERIAL_USE_UART5 FALSE
|
||||
#define STM32_SERIAL_USE_USART6 FALSE
|
||||
#define STM32_SERIAL_USART1_PRIORITY 12
|
||||
#define STM32_SERIAL_USART2_PRIORITY 12
|
||||
#define STM32_SERIAL_USART3_PRIORITY 12
|
||||
#define STM32_SERIAL_UART4_PRIORITY 12
|
||||
#define STM32_SERIAL_UART5_PRIORITY 12
|
||||
#define STM32_SERIAL_USART6_PRIORITY 12
|
||||
|
||||
/*
|
||||
* SPI driver system settings.
|
||||
*/
|
||||
#define STM32_SPI_USE_SPI1 FALSE
|
||||
#define STM32_SPI_USE_SPI2 FALSE
|
||||
#define STM32_SPI_USE_SPI3 FALSE
|
||||
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0)
|
||||
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
|
||||
#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
|
||||
#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
|
||||
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI2_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI3_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ST driver system settings.
|
||||
*/
|
||||
#define STM32_ST_IRQ_PRIORITY 8
|
||||
#define STM32_ST_USE_TIMER 2
|
||||
|
||||
/*
|
||||
* UART driver system settings.
|
||||
*/
|
||||
#define STM32_UART_USE_USART1 FALSE
|
||||
#define STM32_UART_USE_USART2 FALSE
|
||||
#define STM32_UART_USE_USART3 FALSE
|
||||
#define STM32_UART_USE_UART4 FALSE
|
||||
#define STM32_UART_USE_UART5 FALSE
|
||||
#define STM32_UART_USE_USART6 FALSE
|
||||
#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
|
||||
#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
|
||||
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
|
||||
#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
|
||||
#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
|
||||
#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0)
|
||||
#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
|
||||
#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_UART_USART1_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART2_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART3_IRQ_PRIORITY 12
|
||||
#define STM32_UART_UART4_IRQ_PRIORITY 12
|
||||
#define STM32_UART_UART5_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART6_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART1_DMA_PRIORITY 0
|
||||
#define STM32_UART_USART2_DMA_PRIORITY 0
|
||||
#define STM32_UART_USART3_DMA_PRIORITY 0
|
||||
#define STM32_UART_UART4_DMA_PRIORITY 0
|
||||
#define STM32_UART_UART5_DMA_PRIORITY 0
|
||||
#define STM32_UART_USART6_DMA_PRIORITY 0
|
||||
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* USB driver system settings.
|
||||
*/
|
||||
#define STM32_USB_USE_OTG1 TRUE
|
||||
#define STM32_USB_USE_OTG2 FALSE
|
||||
#define STM32_USB_OTG1_IRQ_PRIORITY 14
|
||||
#define STM32_USB_OTG2_IRQ_PRIORITY 14
|
||||
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
|
||||
#define STM32_USB_OTG2_RX_FIFO_SIZE 1024
|
||||
#define STM32_USB_HOST_WAKEUP_DURATION 2
|
||||
|
||||
#define STM32_USB_OTG_THREAD_PRIO NORMALPRIO+1
|
||||
#define STM32_USB_OTG_THREAD_STACK_SIZE 128
|
||||
|
||||
/*
|
||||
* WDG driver system settings.
|
||||
*/
|
||||
#define STM32_WDG_USE_IWDG FALSE
|
||||
|
||||
#endif /* MCUCONF_H */
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,23 @@
|
||||
/* Copyright 2021 Andrei Purdea
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -19,6 +19,6 @@
|
||||
|
||||
#undef STM32L432xx
|
||||
|
||||
// Pretend that we're an L443xx as the ChibiOS definitions for L432/L433 mistakenly don't enable GPIOH, I2C2, or SPI2.
|
||||
// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2.
|
||||
// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443.
|
||||
#define STM32L443xx
|
||||
File renamed without changes.
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32L4xx drivers configuration.
|
||||
* The following settings override the default settings present in
|
||||
* the various device driver implementation headers.
|
||||
* Note that the settings for each driver only have effect if the whole
|
||||
* driver is enabled in halconf.h.
|
||||
*
|
||||
* IRQ priorities:
|
||||
* 15...0 Lowest...Highest.
|
||||
*
|
||||
* DMA priorities:
|
||||
* 0...3 Lowest...Highest.
|
||||
*/
|
||||
|
||||
#ifndef MCUCONF_H
|
||||
#define MCUCONF_H
|
||||
|
||||
#define STM32L4xx_MCUCONF
|
||||
#define STM32L412_MCUCONF
|
||||
#define STM32L422_MCUCONF
|
||||
#define STM32L432_MCUCONF
|
||||
#define STM32L433_MCUCONF
|
||||
#define STM32L442_MCUCONF
|
||||
#define STM32L443_MCUCONF
|
||||
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
#define STM32_NO_INIT FALSE
|
||||
#define STM32_VOS STM32_VOS_RANGE1
|
||||
#define STM32_PVD_ENABLE FALSE
|
||||
#define STM32_PLS STM32_PLS_LEV0
|
||||
#define STM32_HSI16_ENABLED TRUE
|
||||
#define STM32_HSI48_ENABLED TRUE
|
||||
#define STM32_LSI_ENABLED FALSE
|
||||
#define STM32_HSE_ENABLED FALSE
|
||||
#define STM32_LSE_ENABLED FALSE
|
||||
#define STM32_MSIPLL_ENABLED FALSE
|
||||
#define STM32_ADC_CLOCK_ENABLED TRUE
|
||||
#define STM32_USB_CLOCK_ENABLED TRUE
|
||||
#define STM32_SAI1_CLOCK_ENABLED TRUE
|
||||
#define STM32_SAI2_CLOCK_ENABLED TRUE
|
||||
#define STM32_MSIRANGE STM32_MSIRANGE_4M
|
||||
#define STM32_MSISRANGE STM32_MSISRANGE_4M
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSI16
|
||||
#define STM32_PLLM_VALUE 4
|
||||
#define STM32_PLLN_VALUE 80
|
||||
#define STM32_PLLP_VALUE 7
|
||||
#define STM32_PLLQ_VALUE 4
|
||||
#define STM32_PLLR_VALUE 4
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV1
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV1
|
||||
#define STM32_STOPWUCK STM32_STOPWUCK_MSI
|
||||
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
|
||||
#define STM32_MCOPRE STM32_MCOPRE_DIV1
|
||||
#define STM32_LSCOSEL STM32_LSCOSEL_NOCLOCK
|
||||
#define STM32_PLLSAI1N_VALUE 72
|
||||
#define STM32_PLLSAI1P_VALUE 7
|
||||
#define STM32_PLLSAI1Q_VALUE 6
|
||||
#define STM32_PLLSAI1R_VALUE 6
|
||||
#define STM32_PLLSAI2N_VALUE 72
|
||||
#define STM32_PLLSAI2P_VALUE 7
|
||||
#define STM32_PLLSAI2R_VALUE 6
|
||||
|
||||
/*
|
||||
* Peripherals clock sources.
|
||||
*/
|
||||
#define STM32_USART1SEL STM32_USART1SEL_SYSCLK
|
||||
#define STM32_USART2SEL STM32_USART2SEL_SYSCLK
|
||||
#define STM32_USART3SEL STM32_USART3SEL_SYSCLK
|
||||
#define STM32_UART4SEL STM32_UART4SEL_SYSCLK
|
||||
#define STM32_UART5SEL STM32_UART5SEL_SYSCLK
|
||||
#define STM32_LPUART1SEL STM32_LPUART1SEL_SYSCLK
|
||||
#define STM32_I2C1SEL STM32_I2C1SEL_SYSCLK
|
||||
#define STM32_I2C2SEL STM32_I2C2SEL_SYSCLK
|
||||
#define STM32_I2C3SEL STM32_I2C3SEL_SYSCLK
|
||||
#define STM32_LPTIM1SEL STM32_LPTIM1SEL_PCLK1
|
||||
#define STM32_LPTIM2SEL STM32_LPTIM2SEL_PCLK1
|
||||
#define STM32_SAI1SEL STM32_SAI1SEL_OFF
|
||||
#define STM32_SAI2SEL STM32_SAI2SEL_OFF
|
||||
#define STM32_CLK48SEL STM32_CLK48SEL_HSI48
|
||||
#define STM32_ADCSEL STM32_ADCSEL_SYSCLK
|
||||
#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1
|
||||
#define STM32_RTCSEL STM32_RTCSEL_LSI
|
||||
|
||||
/*
|
||||
* IRQ system settings.
|
||||
*/
|
||||
#define STM32_IRQ_EXTI0_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI2_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI3_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI4_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI5_9_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI10_15_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1635_38_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI18_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI19_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI20_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI21_22_PRIORITY 15
|
||||
|
||||
#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_CC_PRIORITY 7
|
||||
#define STM32_IRQ_TIM2_PRIORITY 7
|
||||
#define STM32_IRQ_TIM6_PRIORITY 7
|
||||
#define STM32_IRQ_TIM7_PRIORITY 7
|
||||
|
||||
#define STM32_IRQ_USART1_PRIORITY 12
|
||||
#define STM32_IRQ_USART2_PRIORITY 12
|
||||
#define STM32_IRQ_USART3_PRIORITY 12
|
||||
#define STM32_IRQ_LPUART1_PRIORITY 12
|
||||
|
||||
/*
|
||||
* ADC driver system settings.
|
||||
*/
|
||||
#define STM32_ADC_COMPACT_SAMPLES FALSE
|
||||
#define STM32_ADC_USE_ADC1 FALSE
|
||||
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
|
||||
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC12_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC123_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
|
||||
#define STM32_ADC_ADC123_PRESC ADC_CCR_PRESC_DIV2
|
||||
|
||||
/*
|
||||
* CAN driver system settings.
|
||||
*/
|
||||
#define STM32_CAN_USE_CAN1 FALSE
|
||||
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
|
||||
|
||||
/*
|
||||
* DAC driver system settings.
|
||||
*/
|
||||
#define STM32_DAC_DUAL_MODE FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH1 FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH2 FALSE
|
||||
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
|
||||
#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
|
||||
|
||||
/*
|
||||
* GPT driver system settings.
|
||||
*/
|
||||
#define STM32_GPT_USE_TIM1 FALSE
|
||||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM6 FALSE
|
||||
#define STM32_GPT_USE_TIM7 FALSE
|
||||
#define STM32_GPT_USE_TIM15 FALSE
|
||||
#define STM32_GPT_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* I2C driver system settings.
|
||||
*/
|
||||
#define STM32_I2C_USE_I2C1 FALSE
|
||||
#define STM32_I2C_USE_I2C3 FALSE
|
||||
#define STM32_I2C_BUSY_TIMEOUT 50
|
||||
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3)
|
||||
#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2)
|
||||
#define STM32_I2C_I2C1_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C3_IRQ_PRIORITY 5
|
||||
#define STM32_I2C_I2C1_DMA_PRIORITY 3
|
||||
#define STM32_I2C_I2C3_DMA_PRIORITY 3
|
||||
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ICU driver system settings.
|
||||
*/
|
||||
#define STM32_ICU_USE_TIM1 FALSE
|
||||
#define STM32_ICU_USE_TIM2 FALSE
|
||||
#define STM32_ICU_USE_TIM15 FALSE
|
||||
#define STM32_ICU_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* PWM driver system settings.
|
||||
*/
|
||||
#define STM32_PWM_USE_ADVANCED FALSE
|
||||
#define STM32_PWM_USE_TIM1 FALSE
|
||||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM15 FALSE
|
||||
#define STM32_PWM_USE_TIM16 FALSE
|
||||
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
#define STM32_RTC_PRESA_VALUE 32
|
||||
#define STM32_RTC_PRESS_VALUE 1024
|
||||
#define STM32_RTC_CR_INIT 0
|
||||
#define STM32_RTC_TAMPCR_INIT 0
|
||||
|
||||
/*
|
||||
* SERIAL driver system settings.
|
||||
*/
|
||||
#define STM32_SERIAL_USE_USART1 FALSE
|
||||
#define STM32_SERIAL_USE_USART2 FALSE
|
||||
#define STM32_SERIAL_USE_LPUART1 FALSE
|
||||
#define STM32_SERIAL_USART1_PRIORITY 12
|
||||
#define STM32_SERIAL_USART2_PRIORITY 12
|
||||
#define STM32_SERIAL_LPUART1_PRIORITY 12
|
||||
|
||||
/*
|
||||
* SPI driver system settings.
|
||||
*/
|
||||
#define STM32_SPI_USE_SPI1 FALSE
|
||||
#define STM32_SPI_USE_SPI3 FALSE
|
||||
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3)
|
||||
#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 4)
|
||||
#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
|
||||
#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
|
||||
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI3_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ST driver system settings.
|
||||
*/
|
||||
#define STM32_ST_IRQ_PRIORITY 8
|
||||
#define STM32_ST_USE_TIMER 2
|
||||
|
||||
/*
|
||||
* TRNG driver system settings.
|
||||
*/
|
||||
#define STM32_TRNG_USE_RNG1 FALSE
|
||||
|
||||
/*
|
||||
* UART driver system settings.
|
||||
*/
|
||||
#define STM32_UART_USE_USART1 FALSE
|
||||
#define STM32_UART_USE_USART2 FALSE
|
||||
#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 6)
|
||||
#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
|
||||
#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
|
||||
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* USB driver system settings.
|
||||
*/
|
||||
#define STM32_USB_USE_USB1 TRUE
|
||||
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
|
||||
#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
|
||||
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
|
||||
|
||||
/*
|
||||
* WDG driver system settings.
|
||||
*/
|
||||
#define STM32_WDG_USE_IWDG FALSE
|
||||
|
||||
/*
|
||||
* WSPI driver system settings.
|
||||
*/
|
||||
#define STM32_WSPI_USE_QUADSPI1 FALSE
|
||||
#define STM32_WSPI_QUADSPI1_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
|
||||
#define STM32_WSPI_QUADSPI1_PRESCALER_VALUE 1
|
||||
|
||||
#endif /* MCUCONF_H */
|
||||
@@ -0,0 +1,9 @@
|
||||
# List of all the board related files.
|
||||
BOARDSRC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC/board.c
|
||||
|
||||
# Required include directories
|
||||
BOARDINC = $(CHIBIOS)/os/hal/boards/ST_NUCLEO32_L432KC
|
||||
|
||||
# Shared variables
|
||||
ALLCSRC += $(BOARDSRC)
|
||||
ALLINC += $(BOARDINC)
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright 2018-2021 Harrison Chan (@Xelus)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include_next "board.h"
|
||||
|
||||
#undef STM32L432xx
|
||||
|
||||
// Pretend that we're an L443xx as the ChibiOS definitions for L4x2/L4x3 mistakenly don't enable GPIOH, I2C2, or SPI2.
|
||||
// Until ChibiOS upstream is fixed, this should be kept at L443, as nothing in QMK currently utilises the crypto peripheral on the L443.
|
||||
#define STM32L443xx
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Copyright 2018-2021 Harrison Chan (@Xelus)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Address for jumping to bootloader on STM32 chips. */
|
||||
/* It is chip dependent, the correct number can be looked up by checking against ST's application note AN2606.
|
||||
*/
|
||||
#define STM32_BOOTLOADER_ADDRESS 0x1FFF0000
|
||||
|
||||
#define PAL_STM32_OSPEED_HIGHEST PAL_STM32_OSPEED_HIGH
|
||||
|
||||
#ifndef EARLY_INIT_PERFORM_BOOTLOADER_JUMP
|
||||
# define EARLY_INIT_PERFORM_BOOTLOADER_JUMP TRUE
|
||||
#endif
|
||||
File renamed without changes.
+5
@@ -144,3 +144,8 @@ void __early_init(void) {
|
||||
* @todo Add your board-specific code, if any.
|
||||
*/
|
||||
void boardInit(void) {}
|
||||
|
||||
|
||||
void restart_usb_driver(USBDriver *usbp) {
|
||||
// Do nothing. Restarting the USB driver on these boards breaks it.
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/boards/PJRC_TEENSY_4_1/board.mk
|
||||
@@ -0,0 +1 @@
|
||||
TEENSY_LOADER_CLI_MCU = imxrt1062
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -412,7 +412,7 @@
|
||||
* buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_BUFFERS_SIZE 16
|
||||
#define SERIAL_BUFFERS_SIZE 128
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32F103x8 memory setup for use with the STM32Duino bootloader.
|
||||
*/
|
||||
f103_flash_size = 64k;
|
||||
|
||||
INCLUDE stm32duino_bootloader_common.ld
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32F103xB memory setup for use with the STM32Duino bootloader.
|
||||
*/
|
||||
f103_flash_size = 128k;
|
||||
|
||||
INCLUDE stm32duino_bootloader_common.ld
|
||||
+2
-2
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* ST32F103xB memory setup for use with the maplemini bootloader.
|
||||
* STM32Duino bootloader common memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = 0x08002000, len = 64k - 0x2000
|
||||
flash0 : org = 0x08002000, len = f103_flash_size - 0x2000
|
||||
flash1 : org = 0x00000000, len = 0
|
||||
flash2 : org = 0x00000000, len = 0
|
||||
flash3 : org = 0x00000000, len = 0
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -412,7 +412,7 @@
|
||||
* buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_BUFFERS_SIZE 16
|
||||
#define SERIAL_BUFFERS_SIZE 128
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
File renamed without changes.
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32L412xB memory setup.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
flash0 : org = 0x08000000, len = 128k
|
||||
flash1 : org = 0x00000000, len = 0
|
||||
flash2 : org = 0x00000000, len = 0
|
||||
flash3 : org = 0x00000000, len = 0
|
||||
flash4 : org = 0x00000000, len = 0
|
||||
flash5 : org = 0x00000000, len = 0
|
||||
flash6 : org = 0x00000000, len = 0
|
||||
flash7 : org = 0x00000000, len = 0
|
||||
ram0 : org = 0x20000000, len = 32k
|
||||
ram1 : org = 0x00000000, len = 0
|
||||
ram2 : org = 0x00000000, len = 0
|
||||
ram3 : org = 0x00000000, len = 0
|
||||
ram4 : org = 0x00000000, len = 0
|
||||
ram5 : org = 0x00000000, len = 0
|
||||
ram6 : org = 0x00000000, len = 0
|
||||
ram7 : org = 0x00000000, len = 0
|
||||
}
|
||||
|
||||
/* For each data/text section two region are defined, a virtual region
|
||||
and a load region (_LMA suffix).*/
|
||||
|
||||
/* Flash region to be used for exception vectors.*/
|
||||
REGION_ALIAS("VECTORS_FLASH", flash0);
|
||||
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for constructors and destructors.*/
|
||||
REGION_ALIAS("XTORS_FLASH", flash0);
|
||||
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for code text.*/
|
||||
REGION_ALIAS("TEXT_FLASH", flash0);
|
||||
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for read only data.*/
|
||||
REGION_ALIAS("RODATA_FLASH", flash0);
|
||||
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for various.*/
|
||||
REGION_ALIAS("VARIOUS_FLASH", flash0);
|
||||
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
|
||||
|
||||
/* Flash region to be used for RAM(n) initialization data.*/
|
||||
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for Main stack. This stack accommodates the processing
|
||||
of all exceptions and interrupts.*/
|
||||
REGION_ALIAS("MAIN_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the process stack. This is the stack used by
|
||||
the main() function.*/
|
||||
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for data segment.*/
|
||||
REGION_ALIAS("DATA_RAM", ram0);
|
||||
REGION_ALIAS("DATA_RAM_LMA", flash0);
|
||||
|
||||
/* RAM region to be used for BSS segment.*/
|
||||
REGION_ALIAS("BSS_RAM", ram0);
|
||||
|
||||
/* RAM region to be used for the default heap.*/
|
||||
REGION_ALIAS("HEAP_RAM", ram0);
|
||||
|
||||
/* Generic rules inclusion.*/
|
||||
INCLUDE rules.ld
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,321 @@
|
||||
/* Copyright 2019 Drew Mills
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "analog.h"
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#if !HAL_USE_ADC
|
||||
# error "You need to set HAL_USE_ADC to TRUE in your halconf.h to use the ADC."
|
||||
#endif
|
||||
|
||||
#if !STM32_ADC_USE_ADC1 && !STM32_ADC_USE_ADC2 && !STM32_ADC_USE_ADC3 && !STM32_ADC_USE_ADC4
|
||||
# error "You need to set one of the 'STM32_ADC_USE_ADCx' settings to TRUE in your mcuconf.h to use the ADC."
|
||||
#endif
|
||||
|
||||
#if STM32_ADC_DUAL_MODE
|
||||
# error "STM32 ADC Dual Mode is not supported at this time."
|
||||
#endif
|
||||
|
||||
#if STM32_ADCV3_OVERSAMPLING
|
||||
# error "STM32 ADCV3 Oversampling is not supported at this time."
|
||||
#endif
|
||||
|
||||
// Otherwise assume V3
|
||||
#if defined(STM32F0XX) || defined(STM32L0XX)
|
||||
# define USE_ADCV1
|
||||
#elif defined(STM32F1XX) || defined(STM32F2XX) || defined(STM32F4XX)
|
||||
# define USE_ADCV2
|
||||
#endif
|
||||
|
||||
// BODGE to make v2 look like v1,3 and 4
|
||||
#ifdef USE_ADCV2
|
||||
# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_3)
|
||||
# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_3
|
||||
# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_15
|
||||
# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_28
|
||||
# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_56
|
||||
# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_84
|
||||
# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_112
|
||||
# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_144
|
||||
# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_480
|
||||
# endif
|
||||
|
||||
# if !defined(ADC_SMPR_SMP_1P5) && defined(ADC_SAMPLE_1P5)
|
||||
# define ADC_SMPR_SMP_1P5 ADC_SAMPLE_1P5
|
||||
# define ADC_SMPR_SMP_7P5 ADC_SAMPLE_7P5
|
||||
# define ADC_SMPR_SMP_13P5 ADC_SAMPLE_13P5
|
||||
# define ADC_SMPR_SMP_28P5 ADC_SAMPLE_28P5
|
||||
# define ADC_SMPR_SMP_41P5 ADC_SAMPLE_41P5
|
||||
# define ADC_SMPR_SMP_55P5 ADC_SAMPLE_55P5
|
||||
# define ADC_SMPR_SMP_71P5 ADC_SAMPLE_71P5
|
||||
# define ADC_SMPR_SMP_239P5 ADC_SAMPLE_239P5
|
||||
# endif
|
||||
|
||||
// we still sample at 12bit, but scale down to the requested bit range
|
||||
# define ADC_CFGR1_RES_12BIT 12
|
||||
# define ADC_CFGR1_RES_10BIT 10
|
||||
# define ADC_CFGR1_RES_8BIT 8
|
||||
# define ADC_CFGR1_RES_6BIT 6
|
||||
#endif
|
||||
|
||||
/* User configurable ADC options */
|
||||
#ifndef ADC_COUNT
|
||||
# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F4XX)
|
||||
# define ADC_COUNT 1
|
||||
# elif defined(STM32F3XX)
|
||||
# define ADC_COUNT 4
|
||||
# else
|
||||
# error "ADC_COUNT has not been set for this ARM microcontroller."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ADC_NUM_CHANNELS
|
||||
# define ADC_NUM_CHANNELS 1
|
||||
#elif ADC_NUM_CHANNELS != 1
|
||||
# error "The ARM ADC implementation currently only supports reading one channel at a time."
|
||||
#endif
|
||||
|
||||
#ifndef ADC_BUFFER_DEPTH
|
||||
# define ADC_BUFFER_DEPTH 1
|
||||
#endif
|
||||
|
||||
// For more sampling rate options, look at hal_adc_lld.h in ChibiOS
|
||||
#ifndef ADC_SAMPLING_RATE
|
||||
# define ADC_SAMPLING_RATE ADC_SMPR_SMP_1P5
|
||||
#endif
|
||||
|
||||
// Options are 12, 10, 8, and 6 bit.
|
||||
#ifndef ADC_RESOLUTION
|
||||
# ifdef ADC_CFGR_RES_10BITS // ADCv3, ADCv4
|
||||
# define ADC_RESOLUTION ADC_CFGR_RES_10BITS
|
||||
# else // ADCv1, ADCv5, or the bodge for ADCv2 above
|
||||
# define ADC_RESOLUTION ADC_CFGR1_RES_10BIT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static ADCConfig adcCfg = {};
|
||||
static adcsample_t sampleBuffer[ADC_NUM_CHANNELS * ADC_BUFFER_DEPTH];
|
||||
|
||||
// Initialize to max number of ADCs, set to empty object to initialize all to false.
|
||||
static bool adcInitialized[ADC_COUNT] = {};
|
||||
|
||||
// TODO: add back TR handling???
|
||||
static ADCConversionGroup adcConversionGroup = {
|
||||
.circular = FALSE,
|
||||
.num_channels = (uint16_t)(ADC_NUM_CHANNELS),
|
||||
#if defined(USE_ADCV1)
|
||||
.cfgr1 = ADC_CFGR1_CONT | ADC_RESOLUTION,
|
||||
.smpr = ADC_SAMPLING_RATE,
|
||||
#elif defined(USE_ADCV2)
|
||||
# if !defined(STM32F1XX)
|
||||
.cr2 = ADC_CR2_SWSTART, // F103 seem very unhappy with, F401 seems very unhappy without...
|
||||
# endif
|
||||
.smpr2 = ADC_SMPR2_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN9(ADC_SAMPLING_RATE),
|
||||
.smpr1 = ADC_SMPR1_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN15(ADC_SAMPLING_RATE),
|
||||
#else
|
||||
.cfgr = ADC_CFGR_CONT | ADC_RESOLUTION,
|
||||
.smpr = {ADC_SMPR1_SMP_AN0(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN1(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN2(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN3(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN4(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN5(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN6(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN7(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN8(ADC_SAMPLING_RATE) | ADC_SMPR1_SMP_AN9(ADC_SAMPLING_RATE), ADC_SMPR2_SMP_AN10(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN11(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN12(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN13(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN14(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN15(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN16(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN17(ADC_SAMPLING_RATE) | ADC_SMPR2_SMP_AN18(ADC_SAMPLING_RATE)},
|
||||
#endif
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
__attribute__((weak)) adc_mux pinToMux(pin_t pin) {
|
||||
switch (pin) {
|
||||
#if defined(STM32F0XX)
|
||||
case A0: return TO_MUX( ADC_CHSELR_CHSEL0, 0 );
|
||||
case A1: return TO_MUX( ADC_CHSELR_CHSEL1, 0 );
|
||||
case A2: return TO_MUX( ADC_CHSELR_CHSEL2, 0 );
|
||||
case A3: return TO_MUX( ADC_CHSELR_CHSEL3, 0 );
|
||||
case A4: return TO_MUX( ADC_CHSELR_CHSEL4, 0 );
|
||||
case A5: return TO_MUX( ADC_CHSELR_CHSEL5, 0 );
|
||||
case A6: return TO_MUX( ADC_CHSELR_CHSEL6, 0 );
|
||||
case A7: return TO_MUX( ADC_CHSELR_CHSEL7, 0 );
|
||||
case B0: return TO_MUX( ADC_CHSELR_CHSEL8, 0 );
|
||||
case B1: return TO_MUX( ADC_CHSELR_CHSEL9, 0 );
|
||||
case C0: return TO_MUX( ADC_CHSELR_CHSEL10, 0 );
|
||||
case C1: return TO_MUX( ADC_CHSELR_CHSEL11, 0 );
|
||||
case C2: return TO_MUX( ADC_CHSELR_CHSEL12, 0 );
|
||||
case C3: return TO_MUX( ADC_CHSELR_CHSEL13, 0 );
|
||||
case C4: return TO_MUX( ADC_CHSELR_CHSEL14, 0 );
|
||||
case C5: return TO_MUX( ADC_CHSELR_CHSEL15, 0 );
|
||||
#elif defined(STM32F3XX)
|
||||
case A0: return TO_MUX( ADC_CHANNEL_IN1, 0 );
|
||||
case A1: return TO_MUX( ADC_CHANNEL_IN2, 0 );
|
||||
case A2: return TO_MUX( ADC_CHANNEL_IN3, 0 );
|
||||
case A3: return TO_MUX( ADC_CHANNEL_IN4, 0 );
|
||||
case A4: return TO_MUX( ADC_CHANNEL_IN1, 1 );
|
||||
case A5: return TO_MUX( ADC_CHANNEL_IN2, 1 );
|
||||
case A6: return TO_MUX( ADC_CHANNEL_IN3, 1 );
|
||||
case A7: return TO_MUX( ADC_CHANNEL_IN4, 1 );
|
||||
case B0: return TO_MUX( ADC_CHANNEL_IN12, 2 );
|
||||
case B1: return TO_MUX( ADC_CHANNEL_IN1, 2 );
|
||||
case B2: return TO_MUX( ADC_CHANNEL_IN12, 1 );
|
||||
case B12: return TO_MUX( ADC_CHANNEL_IN3, 3 );
|
||||
case B13: return TO_MUX( ADC_CHANNEL_IN5, 2 );
|
||||
case B14: return TO_MUX( ADC_CHANNEL_IN4, 3 );
|
||||
case B15: return TO_MUX( ADC_CHANNEL_IN5, 3 );
|
||||
case C0: return TO_MUX( ADC_CHANNEL_IN6, 0 ); // Can also be ADC2
|
||||
case C1: return TO_MUX( ADC_CHANNEL_IN7, 0 ); // Can also be ADC2
|
||||
case C2: return TO_MUX( ADC_CHANNEL_IN8, 0 ); // Can also be ADC2
|
||||
case C3: return TO_MUX( ADC_CHANNEL_IN9, 0 ); // Can also be ADC2
|
||||
case C4: return TO_MUX( ADC_CHANNEL_IN5, 1 );
|
||||
case C5: return TO_MUX( ADC_CHANNEL_IN11, 1 );
|
||||
case D8: return TO_MUX( ADC_CHANNEL_IN12, 3 );
|
||||
case D9: return TO_MUX( ADC_CHANNEL_IN13, 3 );
|
||||
case D10: return TO_MUX( ADC_CHANNEL_IN7, 2 ); // Can also be ADC4
|
||||
case D11: return TO_MUX( ADC_CHANNEL_IN8, 2 ); // Can also be ADC4
|
||||
case D12: return TO_MUX( ADC_CHANNEL_IN9, 2 ); // Can also be ADC4
|
||||
case D13: return TO_MUX( ADC_CHANNEL_IN10, 2 ); // Can also be ADC4
|
||||
case D14: return TO_MUX( ADC_CHANNEL_IN11, 2 ); // Can also be ADC4
|
||||
case E7: return TO_MUX( ADC_CHANNEL_IN13, 2 );
|
||||
case E8: return TO_MUX( ADC_CHANNEL_IN6, 2 ); // Can also be ADC4
|
||||
case E9: return TO_MUX( ADC_CHANNEL_IN2, 2 );
|
||||
case E10: return TO_MUX( ADC_CHANNEL_IN14, 2 );
|
||||
case E11: return TO_MUX( ADC_CHANNEL_IN15, 2 );
|
||||
case E12: return TO_MUX( ADC_CHANNEL_IN16, 2 );
|
||||
case E13: return TO_MUX( ADC_CHANNEL_IN3, 2 );
|
||||
case E14: return TO_MUX( ADC_CHANNEL_IN1, 3 );
|
||||
case E15: return TO_MUX( ADC_CHANNEL_IN2, 3 );
|
||||
case F2: return TO_MUX( ADC_CHANNEL_IN10, 0 ); // Can also be ADC2
|
||||
case F4: return TO_MUX( ADC_CHANNEL_IN5, 0 );
|
||||
#elif defined(STM32F4XX)
|
||||
case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
|
||||
case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
|
||||
case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
|
||||
case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 );
|
||||
case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 );
|
||||
case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 );
|
||||
case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 );
|
||||
case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 );
|
||||
case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 );
|
||||
case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 );
|
||||
case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 );
|
||||
case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 );
|
||||
case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 );
|
||||
case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 );
|
||||
case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 );
|
||||
case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 );
|
||||
# if STM32_ADC_USE_ADC3
|
||||
case F3: return TO_MUX( ADC_CHANNEL_IN9, 2 );
|
||||
case F4: return TO_MUX( ADC_CHANNEL_IN14, 2 );
|
||||
case F5: return TO_MUX( ADC_CHANNEL_IN15, 2 );
|
||||
case F6: return TO_MUX( ADC_CHANNEL_IN4, 2 );
|
||||
case F7: return TO_MUX( ADC_CHANNEL_IN5, 2 );
|
||||
case F8: return TO_MUX( ADC_CHANNEL_IN6, 2 );
|
||||
case F9: return TO_MUX( ADC_CHANNEL_IN7, 2 );
|
||||
case F10: return TO_MUX( ADC_CHANNEL_IN8, 2 );
|
||||
# endif
|
||||
#elif defined(STM32F1XX)
|
||||
case A0: return TO_MUX( ADC_CHANNEL_IN0, 0 );
|
||||
case A1: return TO_MUX( ADC_CHANNEL_IN1, 0 );
|
||||
case A2: return TO_MUX( ADC_CHANNEL_IN2, 0 );
|
||||
case A3: return TO_MUX( ADC_CHANNEL_IN3, 0 );
|
||||
case A4: return TO_MUX( ADC_CHANNEL_IN4, 0 );
|
||||
case A5: return TO_MUX( ADC_CHANNEL_IN5, 0 );
|
||||
case A6: return TO_MUX( ADC_CHANNEL_IN6, 0 );
|
||||
case A7: return TO_MUX( ADC_CHANNEL_IN7, 0 );
|
||||
case B0: return TO_MUX( ADC_CHANNEL_IN8, 0 );
|
||||
case B1: return TO_MUX( ADC_CHANNEL_IN9, 0 );
|
||||
case C0: return TO_MUX( ADC_CHANNEL_IN10, 0 );
|
||||
case C1: return TO_MUX( ADC_CHANNEL_IN11, 0 );
|
||||
case C2: return TO_MUX( ADC_CHANNEL_IN12, 0 );
|
||||
case C3: return TO_MUX( ADC_CHANNEL_IN13, 0 );
|
||||
case C4: return TO_MUX( ADC_CHANNEL_IN14, 0 );
|
||||
case C5: return TO_MUX( ADC_CHANNEL_IN15, 0 );
|
||||
// STM32F103x[C-G] in 144-pin packages also have analog inputs on F6...F10, but they are on ADC3, and the
|
||||
// ChibiOS ADC driver for STM32F1xx currently supports only ADC1, therefore these pins are not usable.
|
||||
#endif
|
||||
}
|
||||
|
||||
// return an adc that would never be used so intToADCDriver will bail out
|
||||
return TO_MUX(0, 0xFF);
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
static inline ADCDriver* intToADCDriver(uint8_t adcInt) {
|
||||
switch (adcInt) {
|
||||
#if STM32_ADC_USE_ADC1
|
||||
case 0:
|
||||
return &ADCD1;
|
||||
#endif
|
||||
#if STM32_ADC_USE_ADC2
|
||||
case 1:
|
||||
return &ADCD2;
|
||||
#endif
|
||||
#if STM32_ADC_USE_ADC3
|
||||
case 2:
|
||||
return &ADCD3;
|
||||
#endif
|
||||
#if STM32_ADC_USE_ADC4
|
||||
case 3:
|
||||
return &ADCD4;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void manageAdcInitializationDriver(uint8_t adc, ADCDriver* adcDriver) {
|
||||
if (!adcInitialized[adc]) {
|
||||
adcStart(adcDriver, &adcCfg);
|
||||
adcInitialized[adc] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t analogReadPin(pin_t pin) {
|
||||
palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
|
||||
|
||||
return adc_read(pinToMux(pin));
|
||||
}
|
||||
|
||||
int16_t analogReadPinAdc(pin_t pin, uint8_t adc) {
|
||||
palSetLineMode(pin, PAL_MODE_INPUT_ANALOG);
|
||||
|
||||
adc_mux target = pinToMux(pin);
|
||||
target.adc = adc;
|
||||
return adc_read(target);
|
||||
}
|
||||
|
||||
int16_t adc_read(adc_mux mux) {
|
||||
#if defined(USE_ADCV1)
|
||||
// TODO: fix previous assumption of only 1 input...
|
||||
adcConversionGroup.chselr = 1 << mux.input; /*no macro to convert N to ADC_CHSELR_CHSEL1*/
|
||||
#elif defined(USE_ADCV2)
|
||||
adcConversionGroup.sqr3 = ADC_SQR3_SQ1_N(mux.input);
|
||||
#else
|
||||
adcConversionGroup.sqr[0] = ADC_SQR1_SQ1_N(mux.input);
|
||||
#endif
|
||||
|
||||
ADCDriver* targetDriver = intToADCDriver(mux.adc);
|
||||
if (!targetDriver) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
manageAdcInitializationDriver(mux.adc, targetDriver);
|
||||
if (adcConvert(targetDriver, &adcConversionGroup, &sampleBuffer[0], ADC_BUFFER_DEPTH) != MSG_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_ADCV2
|
||||
// fake 12-bit -> N-bit scale
|
||||
return (*sampleBuffer) >> (12 - ADC_RESOLUTION);
|
||||
#else
|
||||
// already handled as part of adcConvert
|
||||
return *sampleBuffer;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Copyright 2019 Drew Mills
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint16_t input;
|
||||
uint8_t adc;
|
||||
} adc_mux;
|
||||
#define TO_MUX(i, a) \
|
||||
(adc_mux) { i, a }
|
||||
|
||||
int16_t analogReadPin(pin_t pin);
|
||||
int16_t analogReadPinAdc(pin_t pin, uint8_t adc);
|
||||
adc_mux pinToMux(pin_t pin);
|
||||
|
||||
int16_t adc_read(adc_mux mux);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <hal.h>
|
||||
#include "eeprom_driver.h"
|
||||
#include "eeprom_stm32_L0_L1.h"
|
||||
|
||||
#define EEPROM_BASE_ADDR 0x08080000
|
||||
#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset))
|
||||
#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_ADDR(offset))
|
||||
#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset))))
|
||||
|
||||
#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset))
|
||||
|
||||
#define FLASH_PEKEY1 0x89ABCDEF
|
||||
#define FLASH_PEKEY2 0x02030405
|
||||
|
||||
static inline void STM32_L0_L1_EEPROM_WaitNotBusy(void) {
|
||||
while (FLASH->SR & FLASH_SR_BSY) {
|
||||
__WFI();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void STM32_L0_L1_EEPROM_Unlock(void) {
|
||||
STM32_L0_L1_EEPROM_WaitNotBusy();
|
||||
if (FLASH->PECR & FLASH_PECR_PELOCK) {
|
||||
FLASH->PEKEYR = FLASH_PEKEY1;
|
||||
FLASH->PEKEYR = FLASH_PEKEY2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void STM32_L0_L1_EEPROM_Lock(void) {
|
||||
STM32_L0_L1_EEPROM_WaitNotBusy();
|
||||
FLASH->PECR |= FLASH_PECR_PELOCK;
|
||||
}
|
||||
|
||||
void eeprom_driver_init(void) {}
|
||||
|
||||
void eeprom_driver_erase(void) {
|
||||
STM32_L0_L1_EEPROM_Unlock();
|
||||
|
||||
for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) {
|
||||
FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA;
|
||||
|
||||
*(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0;
|
||||
|
||||
STM32_L0_L1_EEPROM_WaitNotBusy();
|
||||
FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA);
|
||||
}
|
||||
|
||||
STM32_L0_L1_EEPROM_Lock();
|
||||
}
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, size_t len) {
|
||||
for (size_t offset = 0; offset < len; ++offset) {
|
||||
// Drop out if we've hit the limit of the EEPROM
|
||||
if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
|
||||
break;
|
||||
}
|
||||
|
||||
STM32_L0_L1_EEPROM_WaitNotBusy();
|
||||
BUFFER_BYTE(buf, offset) = EEPROM_BYTE(addr, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, size_t len) {
|
||||
STM32_L0_L1_EEPROM_Unlock();
|
||||
|
||||
for (size_t offset = 0; offset < len; ++offset) {
|
||||
// Drop out if we've hit the limit of the EEPROM
|
||||
if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
|
||||
break;
|
||||
}
|
||||
|
||||
STM32_L0_L1_EEPROM_WaitNotBusy();
|
||||
EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset);
|
||||
}
|
||||
|
||||
STM32_L0_L1_EEPROM_Lock();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
The size used by the STM32 L0/L1 EEPROM driver.
|
||||
*/
|
||||
#ifndef STM32_ONBOARD_EEPROM_SIZE
|
||||
# ifdef VIA_ENABLE
|
||||
# define STM32_ONBOARD_EEPROM_SIZE 1024
|
||||
# else
|
||||
# include "eeconfig.h"
|
||||
# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if STM32_ONBOARD_EEPROM_SIZE > 128
|
||||
# pragma message("Please note: resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.")
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
/* Copyright 2018 Jack Humbert
|
||||
* Copyright 2018 Yiancar
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This library is only valid for STM32 processors.
|
||||
* This library follows the convention of the AVR i2c_master library.
|
||||
* As a result addresses are expected to be already shifted (addr << 1).
|
||||
* I2CD1 is the default driver which corresponds to pins B6 and B7. This
|
||||
* can be changed.
|
||||
* Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
|
||||
* STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used
|
||||
* but using any other I2C pins should be trivial.
|
||||
*/
|
||||
#include "quantum.h"
|
||||
#include "i2c_master.h"
|
||||
#include <string.h>
|
||||
#include <hal.h>
|
||||
|
||||
static uint8_t i2c_address;
|
||||
|
||||
static const I2CConfig i2cconfig = {
|
||||
#if defined(USE_I2CV1_CONTRIB)
|
||||
I2C1_CLOCK_SPEED,
|
||||
#elif defined(USE_I2CV1)
|
||||
I2C1_OPMODE,
|
||||
I2C1_CLOCK_SPEED,
|
||||
I2C1_DUTY_CYCLE,
|
||||
#else
|
||||
// This configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0
|
||||
#endif
|
||||
};
|
||||
|
||||
static i2c_status_t chibios_to_qmk(const msg_t* status) {
|
||||
switch (*status) {
|
||||
case I2C_NO_ERROR:
|
||||
return I2C_STATUS_SUCCESS;
|
||||
case I2C_TIMEOUT:
|
||||
return I2C_STATUS_TIMEOUT;
|
||||
// I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT
|
||||
default:
|
||||
return I2C_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void i2c_init(void) {
|
||||
static bool is_initialised = false;
|
||||
if (!is_initialised) {
|
||||
is_initialised = true;
|
||||
|
||||
// Try releasing special pins for a short time
|
||||
palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT);
|
||||
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT);
|
||||
|
||||
chThdSleepMilliseconds(10);
|
||||
#if defined(USE_GPIOV1)
|
||||
palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE);
|
||||
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE);
|
||||
#else
|
||||
palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
i2c_status_t i2c_start(uint8_t address) {
|
||||
i2c_address = address;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
return I2C_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = address;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout));
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = address;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
msg_t status = i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, TIME_MS2I(timeout));
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = devaddr;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
|
||||
uint8_t complete_packet[length + 1];
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
complete_packet[i + 1] = data[i];
|
||||
}
|
||||
complete_packet[0] = regaddr;
|
||||
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout));
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) {
|
||||
i2c_address = devaddr;
|
||||
i2cStart(&I2C_DRIVER, &i2cconfig);
|
||||
msg_t status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout));
|
||||
return chibios_to_qmk(&status);
|
||||
}
|
||||
|
||||
void i2c_stop(void) { i2cStop(&I2C_DRIVER); }
|
||||
@@ -0,0 +1,113 @@
|
||||
/* Copyright 2018 Jack Humbert
|
||||
* Copyright 2018 Yiancar
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This library follows the convention of the AVR i2c_master library.
|
||||
* As a result addresses are expected to be already shifted (addr << 1).
|
||||
* I2CD1 is the default driver which corresponds to pins B6 and B7. This
|
||||
* can be changed.
|
||||
* Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
|
||||
* STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#ifdef I2C1_BANK
|
||||
# define I2C1_SCL_BANK I2C1_BANK
|
||||
# define I2C1_SDA_BANK I2C1_BANK
|
||||
#endif
|
||||
|
||||
#ifndef I2C1_SCL_BANK
|
||||
# define I2C1_SCL_BANK GPIOB
|
||||
#endif
|
||||
|
||||
#ifndef I2C1_SDA_BANK
|
||||
# define I2C1_SDA_BANK GPIOB
|
||||
#endif
|
||||
|
||||
#ifndef I2C1_SCL
|
||||
# define I2C1_SCL 6
|
||||
#endif
|
||||
#ifndef I2C1_SDA
|
||||
# define I2C1_SDA 7
|
||||
#endif
|
||||
|
||||
#ifdef USE_I2CV1
|
||||
# ifndef I2C1_OPMODE
|
||||
# define I2C1_OPMODE OPMODE_I2C
|
||||
# endif
|
||||
# ifndef I2C1_CLOCK_SPEED
|
||||
# define I2C1_CLOCK_SPEED 100000 /* 400000 */
|
||||
# endif
|
||||
# ifndef I2C1_DUTY_CYCLE
|
||||
# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */
|
||||
# endif
|
||||
#else
|
||||
// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||
# ifndef I2C1_TIMINGR_PRESC
|
||||
# define I2C1_TIMINGR_PRESC 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLDEL
|
||||
# define I2C1_TIMINGR_SCLDEL 7U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SDADEL
|
||||
# define I2C1_TIMINGR_SDADEL 0U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLH
|
||||
# define I2C1_TIMINGR_SCLH 38U
|
||||
# endif
|
||||
# ifndef I2C1_TIMINGR_SCLL
|
||||
# define I2C1_TIMINGR_SCLL 129U
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef I2C_DRIVER
|
||||
# define I2C_DRIVER I2CD1
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPIOV1
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
|
||||
# endif
|
||||
#else
|
||||
// The default PAL alternate modes are used to signal that the pins are used for I2C
|
||||
# ifndef I2C1_SCL_PAL_MODE
|
||||
# define I2C1_SCL_PAL_MODE 4
|
||||
# endif
|
||||
# ifndef I2C1_SDA_PAL_MODE
|
||||
# define I2C1_SDA_PAL_MODE 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef int16_t i2c_status_t;
|
||||
|
||||
#define I2C_STATUS_SUCCESS (0)
|
||||
#define I2C_STATUS_ERROR (-1)
|
||||
#define I2C_STATUS_TIMEOUT (-2)
|
||||
|
||||
void i2c_init(void);
|
||||
i2c_status_t i2c_start(uint8_t address);
|
||||
i2c_status_t i2c_transmit(uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
|
||||
void i2c_stop(void);
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* WARNING: be careful changing this code, it is very timing dependent
|
||||
*/
|
||||
|
||||
#include "quantum.h"
|
||||
#include "serial.h"
|
||||
#include "wait.h"
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
// TODO: resolve/remove build warnings
|
||||
#if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) && defined(PROTOCOL_CHIBIOS) && defined(WS2812_DRIVER_BITBANG)
|
||||
# warning "RGBLED_SPLIT not supported with bitbang WS2812 driver"
|
||||
#endif
|
||||
|
||||
// default wait implementation cannot be called within interrupt
|
||||
// this method seems to be more accurate than GPT timers
|
||||
#if PORT_SUPPORTS_RT == FALSE
|
||||
# error "chSysPolledDelayX method not supported on this platform"
|
||||
#else
|
||||
# undef wait_us
|
||||
# define wait_us(x) chSysPolledDelayX(US2RTC(STM32_SYSCLK, x))
|
||||
#endif
|
||||
|
||||
#ifndef SELECT_SOFT_SERIAL_SPEED
|
||||
# define SELECT_SOFT_SERIAL_SPEED 1
|
||||
// TODO: correct speeds...
|
||||
// 0: about 189kbps (Experimental only)
|
||||
// 1: about 137kbps (default)
|
||||
// 2: about 75kbps
|
||||
// 3: about 39kbps
|
||||
// 4: about 26kbps
|
||||
// 5: about 20kbps
|
||||
#endif
|
||||
|
||||
// Serial pulse period in microseconds. At the moment, going lower than 12 causes communication failure
|
||||
#if SELECT_SOFT_SERIAL_SPEED == 0
|
||||
# define SERIAL_DELAY 12
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 1
|
||||
# define SERIAL_DELAY 16
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 2
|
||||
# define SERIAL_DELAY 24
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 3
|
||||
# define SERIAL_DELAY 32
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 4
|
||||
# define SERIAL_DELAY 48
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 5
|
||||
# define SERIAL_DELAY 64
|
||||
#else
|
||||
# error invalid SELECT_SOFT_SERIAL_SPEED value
|
||||
#endif
|
||||
|
||||
inline static void serial_delay(void) { wait_us(SERIAL_DELAY); }
|
||||
inline static void serial_delay_half(void) { wait_us(SERIAL_DELAY / 2); }
|
||||
inline static void serial_delay_blip(void) { wait_us(1); }
|
||||
inline static void serial_output(void) { setPinOutput(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_input(void) { setPinInputHigh(SOFT_SERIAL_PIN); }
|
||||
inline static bool serial_read_pin(void) { return !!readPin(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
|
||||
inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
|
||||
|
||||
void interrupt_handler(void *arg);
|
||||
|
||||
// Use thread + palWaitLineTimeout instead of palSetLineCallback
|
||||
// - Methods like setPinOutput and palEnableLineEvent/palDisableLineEvent
|
||||
// cause the interrupt to lock up, which would limit to only receiving data...
|
||||
static THD_WORKING_AREA(waThread1, 128);
|
||||
static THD_FUNCTION(Thread1, arg) {
|
||||
(void)arg;
|
||||
chRegSetThreadName("blinker");
|
||||
while (true) {
|
||||
palWaitLineTimeout(SOFT_SERIAL_PIN, TIME_INFINITE);
|
||||
interrupt_handler(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void soft_serial_initiator_init(void) {
|
||||
serial_output();
|
||||
serial_high();
|
||||
}
|
||||
|
||||
void soft_serial_target_init(void) {
|
||||
serial_input();
|
||||
|
||||
palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE);
|
||||
chThdCreateStatic(waThread1, sizeof(waThread1), HIGHPRIO, Thread1, NULL);
|
||||
}
|
||||
|
||||
// Used by the master to synchronize timing with the slave.
|
||||
static void __attribute__((noinline)) sync_recv(void) {
|
||||
serial_input();
|
||||
// This shouldn't hang if the slave disconnects because the
|
||||
// serial line will float to high if the slave does disconnect.
|
||||
while (!serial_read_pin()) {
|
||||
}
|
||||
|
||||
serial_delay();
|
||||
}
|
||||
|
||||
// Used by the slave to send a synchronization signal to the master.
|
||||
static void __attribute__((noinline)) sync_send(void) {
|
||||
serial_output();
|
||||
|
||||
serial_low();
|
||||
serial_delay();
|
||||
|
||||
serial_high();
|
||||
}
|
||||
|
||||
// Reads a byte from the serial line
|
||||
static uint8_t __attribute__((noinline)) serial_read_byte(void) {
|
||||
uint8_t byte = 0;
|
||||
serial_input();
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
byte = (byte << 1) | serial_read_pin();
|
||||
serial_delay();
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
// Sends a byte with MSB ordering
|
||||
static void __attribute__((noinline)) serial_write_byte(uint8_t data) {
|
||||
uint8_t b = 8;
|
||||
serial_output();
|
||||
while (b--) {
|
||||
if (data & (1 << b)) {
|
||||
serial_high();
|
||||
} else {
|
||||
serial_low();
|
||||
}
|
||||
serial_delay();
|
||||
}
|
||||
}
|
||||
|
||||
// interrupt handle to be used by the slave device
|
||||
void interrupt_handler(void *arg) {
|
||||
chSysLockFromISR();
|
||||
|
||||
sync_send();
|
||||
|
||||
// read mid pulses
|
||||
serial_delay_blip();
|
||||
|
||||
uint8_t checksum_computed = 0;
|
||||
int sstd_index = 0;
|
||||
|
||||
sstd_index = serial_read_byte();
|
||||
sync_send();
|
||||
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
|
||||
split_trans_initiator2target_buffer(trans)[i] = serial_read_byte();
|
||||
sync_send();
|
||||
checksum_computed += split_trans_initiator2target_buffer(trans)[i];
|
||||
}
|
||||
checksum_computed ^= 7;
|
||||
uint8_t checksum_received = serial_read_byte();
|
||||
sync_send();
|
||||
|
||||
// wait for the sync to finish sending
|
||||
serial_delay();
|
||||
|
||||
// Allow any slave processing to occur
|
||||
if (trans->slave_callback) {
|
||||
trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
|
||||
}
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
|
||||
serial_write_byte(split_trans_target2initiator_buffer(trans)[i]);
|
||||
sync_send();
|
||||
serial_delay_half();
|
||||
checksum += split_trans_target2initiator_buffer(trans)[i];
|
||||
}
|
||||
serial_write_byte(checksum ^ 7);
|
||||
sync_send();
|
||||
|
||||
// wait for the sync to finish sending
|
||||
serial_delay();
|
||||
|
||||
*trans->status = (checksum_computed == checksum_received) ? TRANSACTION_ACCEPTED : TRANSACTION_DATA_ERROR;
|
||||
|
||||
// end transaction
|
||||
serial_input();
|
||||
|
||||
// TODO: remove extra delay between transactions
|
||||
serial_delay();
|
||||
|
||||
chSysUnlockFromISR();
|
||||
}
|
||||
|
||||
/////////
|
||||
// start transaction by initiator
|
||||
//
|
||||
// int soft_serial_transaction(int sstd_index)
|
||||
//
|
||||
// Returns:
|
||||
// TRANSACTION_END
|
||||
// TRANSACTION_NO_RESPONSE
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
|
||||
|
||||
// TODO: remove extra delay between transactions
|
||||
serial_delay();
|
||||
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
chSysLock();
|
||||
|
||||
// signal to the slave that we want to start a transaction
|
||||
serial_output();
|
||||
serial_low();
|
||||
serial_delay_blip();
|
||||
|
||||
// wait for the slaves response
|
||||
serial_input();
|
||||
serial_high();
|
||||
serial_delay();
|
||||
|
||||
// check if the slave is present
|
||||
if (serial_read_pin()) {
|
||||
// slave failed to pull the line low, assume not present
|
||||
dprintf("serial::NO_RESPONSE\n");
|
||||
chSysUnlock();
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
|
||||
// if the slave is present syncronize with it
|
||||
|
||||
uint8_t checksum = 0;
|
||||
// send data to the slave
|
||||
serial_write_byte(sstd_index); // first chunk is transaction id
|
||||
sync_recv();
|
||||
|
||||
for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
|
||||
serial_write_byte(split_trans_initiator2target_buffer(trans)[i]);
|
||||
sync_recv();
|
||||
checksum += split_trans_initiator2target_buffer(trans)[i];
|
||||
}
|
||||
serial_write_byte(checksum ^ 7);
|
||||
sync_recv();
|
||||
|
||||
serial_delay();
|
||||
serial_delay(); // read mid pulses
|
||||
|
||||
// receive data from the slave
|
||||
uint8_t checksum_computed = 0;
|
||||
for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
|
||||
split_trans_target2initiator_buffer(trans)[i] = serial_read_byte();
|
||||
sync_recv();
|
||||
checksum_computed += split_trans_target2initiator_buffer(trans)[i];
|
||||
}
|
||||
checksum_computed ^= 7;
|
||||
uint8_t checksum_received = serial_read_byte();
|
||||
|
||||
sync_recv();
|
||||
serial_delay();
|
||||
|
||||
if ((checksum_computed) != (checksum_received)) {
|
||||
dprintf("serial::FAIL[%u,%u,%u]\n", checksum_computed, checksum_received, sstd_index);
|
||||
serial_output();
|
||||
serial_high();
|
||||
|
||||
chSysUnlock();
|
||||
return TRANSACTION_DATA_ERROR;
|
||||
}
|
||||
|
||||
// always, release the line when not in use
|
||||
serial_high();
|
||||
serial_output();
|
||||
|
||||
chSysUnlock();
|
||||
return TRANSACTION_END;
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "serial_usart.h"
|
||||
|
||||
#if defined(SERIAL_USART_CONFIG)
|
||||
static SerialConfig serial_config = SERIAL_USART_CONFIG;
|
||||
#else
|
||||
static SerialConfig serial_config = {
|
||||
.speed = (SERIAL_USART_SPEED), /* speed - mandatory */
|
||||
.cr1 = (SERIAL_USART_CR1),
|
||||
.cr2 = (SERIAL_USART_CR2),
|
||||
# if !defined(SERIAL_USART_FULL_DUPLEX)
|
||||
.cr3 = ((SERIAL_USART_CR3) | USART_CR3_HDSEL) /* activate half-duplex mode */
|
||||
# else
|
||||
.cr3 = (SERIAL_USART_CR3)
|
||||
# endif
|
||||
};
|
||||
#endif
|
||||
|
||||
static SerialDriver* serial_driver = &SERIAL_USART_DRIVER;
|
||||
|
||||
static inline bool react_to_transactions(void);
|
||||
static inline bool __attribute__((nonnull)) receive(uint8_t* destination, const size_t size);
|
||||
static inline bool __attribute__((nonnull)) send(const uint8_t* source, const size_t size);
|
||||
static inline int initiate_transaction(uint8_t sstd_index);
|
||||
static inline void usart_clear(void);
|
||||
|
||||
/**
|
||||
* @brief Clear the receive input queue.
|
||||
*/
|
||||
static inline void usart_clear(void) {
|
||||
osalSysLock();
|
||||
bool volatile queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue);
|
||||
osalSysUnlock();
|
||||
|
||||
while (queue_not_empty) {
|
||||
osalSysLock();
|
||||
/* Hard reset the input queue. */
|
||||
iqResetI(&serial_driver->iqueue);
|
||||
osalSysUnlock();
|
||||
/* Allow pending interrupts to preempt.
|
||||
* Do not merge the lock/unlock blocks into one
|
||||
* or the code will not work properly.
|
||||
* The empty read adds a tiny amount of delay. */
|
||||
(void)queue_not_empty;
|
||||
osalSysLock();
|
||||
queue_not_empty = !iqIsEmptyI(&serial_driver->iqueue);
|
||||
osalSysUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocking send of buffer with timeout.
|
||||
*
|
||||
* @return true Send success.
|
||||
* @return false Send failed.
|
||||
*/
|
||||
static inline bool send(const uint8_t* source, const size_t size) {
|
||||
bool success = (size_t)sdWriteTimeout(serial_driver, source, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
|
||||
|
||||
#if !defined(SERIAL_USART_FULL_DUPLEX)
|
||||
if (success) {
|
||||
/* Half duplex fills the input queue with the data we wrote - just throw it away.
|
||||
Under the right circumstances (e.g. bad cables paired with high baud rates)
|
||||
less bytes can be present in the input queue, therefore a timeout is needed. */
|
||||
uint8_t dump[size];
|
||||
return receive(dump, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blocking receive of size * bytes with timeout.
|
||||
*
|
||||
* @return true Receive success.
|
||||
* @return false Receive failed.
|
||||
*/
|
||||
static inline bool receive(uint8_t* destination, const size_t size) {
|
||||
bool success = (size_t)sdReadTimeout(serial_driver, destination, size, TIME_MS2I(SERIAL_USART_TIMEOUT)) == size;
|
||||
return success;
|
||||
}
|
||||
|
||||
#if !defined(SERIAL_USART_FULL_DUPLEX)
|
||||
|
||||
/**
|
||||
* @brief Initiate pins for USART peripheral. Half-duplex configuration.
|
||||
*/
|
||||
__attribute__((weak)) void usart_init(void) {
|
||||
# if defined(MCU_STM32)
|
||||
# if defined(USE_GPIOV1)
|
||||
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
|
||||
# else
|
||||
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
# endif
|
||||
|
||||
# if defined(USART_REMAP)
|
||||
USART_REMAP;
|
||||
# endif
|
||||
# else
|
||||
# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files."
|
||||
# endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief Initiate pins for USART peripheral. Full-duplex configuration.
|
||||
*/
|
||||
__attribute__((weak)) void usart_init(void) {
|
||||
# if defined(MCU_STM32)
|
||||
# if defined(USE_GPIOV1)
|
||||
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
||||
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_INPUT);
|
||||
# else
|
||||
palSetLineMode(SERIAL_USART_TX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_TX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
palSetLineMode(SERIAL_USART_RX_PIN, PAL_MODE_ALTERNATE(SERIAL_USART_RX_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
# endif
|
||||
|
||||
# if defined(USART_REMAP)
|
||||
USART_REMAP;
|
||||
# endif
|
||||
# else
|
||||
# pragma message "usart_init: MCU Familiy not supported by default, please supply your own init code by implementing usart_init() in your keyboard files."
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Overridable master specific initializations.
|
||||
*/
|
||||
__attribute__((weak, nonnull)) void usart_master_init(SerialDriver** driver) {
|
||||
(void)driver;
|
||||
usart_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overridable slave specific initializations.
|
||||
*/
|
||||
__attribute__((weak, nonnull)) void usart_slave_init(SerialDriver** driver) {
|
||||
(void)driver;
|
||||
usart_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This thread runs on the slave and responds to transactions initiated
|
||||
* by the master.
|
||||
*/
|
||||
static THD_WORKING_AREA(waSlaveThread, 1024);
|
||||
static THD_FUNCTION(SlaveThread, arg) {
|
||||
(void)arg;
|
||||
chRegSetThreadName("usart_tx_rx");
|
||||
|
||||
while (true) {
|
||||
if (!react_to_transactions()) {
|
||||
/* Clear the receive queue, to start with a clean slate.
|
||||
* Parts of failed transactions or spurious bytes could still be in it. */
|
||||
usart_clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slave specific initializations.
|
||||
*/
|
||||
void soft_serial_target_init(void) {
|
||||
usart_slave_init(&serial_driver);
|
||||
|
||||
sdStart(serial_driver, &serial_config);
|
||||
|
||||
/* Start transport thread. */
|
||||
chThdCreateStatic(waSlaveThread, sizeof(waSlaveThread), HIGHPRIO, SlaveThread, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief React to transactions started by the master.
|
||||
*/
|
||||
static inline bool react_to_transactions(void) {
|
||||
/* Wait until there is a transaction for us. */
|
||||
uint8_t sstd_index = (uint8_t)sdGet(serial_driver);
|
||||
|
||||
/* Sanity check that we are actually responding to a valid transaction. */
|
||||
if (sstd_index >= NUM_TOTAL_TRANSACTIONS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
|
||||
|
||||
/* Send back the handshake which is XORed as a simple checksum,
|
||||
to signal that the slave is ready to receive possible transaction buffers */
|
||||
sstd_index ^= HANDSHAKE_MAGIC;
|
||||
if (!send(&sstd_index, sizeof(sstd_index))) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Receive transaction buffer from the master. If this transaction requires it.*/
|
||||
if (trans->initiator2target_buffer_size) {
|
||||
if (!receive(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allow any slave processing to occur. */
|
||||
if (trans->slave_callback) {
|
||||
trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size, split_trans_target2initiator_buffer(trans));
|
||||
}
|
||||
|
||||
/* Send transaction buffer to the master. If this transaction requires it. */
|
||||
if (trans->target2initiator_buffer_size) {
|
||||
if (!send(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Master specific initializations.
|
||||
*/
|
||||
void soft_serial_initiator_init(void) {
|
||||
usart_master_init(&serial_driver);
|
||||
|
||||
#if defined(MCU_STM32) && defined(SERIAL_USART_PIN_SWAP)
|
||||
serial_config.cr2 |= USART_CR2_SWAP; // master has swapped TX/RX pins
|
||||
#endif
|
||||
|
||||
sdStart(serial_driver, &serial_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start transaction from the master half to the slave half.
|
||||
*
|
||||
* @param index Transaction Table index of the transaction to start.
|
||||
* @return int TRANSACTION_NO_RESPONSE in case of Timeout.
|
||||
* TRANSACTION_TYPE_ERROR in case of invalid transaction index.
|
||||
* TRANSACTION_END in case of success.
|
||||
*/
|
||||
int soft_serial_transaction(int index) {
|
||||
/* Clear the receive queue, to start with a clean slate.
|
||||
* Parts of failed transactions or spurious bytes could still be in it. */
|
||||
usart_clear();
|
||||
return initiate_transaction((uint8_t)index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiate transaction to slave half.
|
||||
*/
|
||||
static inline int initiate_transaction(uint8_t sstd_index) {
|
||||
/* Sanity check that we are actually starting a valid transaction. */
|
||||
if (sstd_index >= NUM_TOTAL_TRANSACTIONS) {
|
||||
dprintln("USART: Illegal transaction Id.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
}
|
||||
|
||||
split_transaction_desc_t* trans = &split_transaction_table[sstd_index];
|
||||
|
||||
/* Transaction is not registered. Abort. */
|
||||
if (!trans->status) {
|
||||
dprintln("USART: Transaction not registered.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
}
|
||||
|
||||
/* Send transaction table index to the slave, which doubles as basic handshake token. */
|
||||
if (!send(&sstd_index, sizeof(sstd_index))) {
|
||||
dprintln("USART: Send Handshake failed.");
|
||||
return TRANSACTION_TYPE_ERROR;
|
||||
}
|
||||
|
||||
uint8_t sstd_index_shake = 0xFF;
|
||||
|
||||
/* Which we always read back first so that we can error out correctly.
|
||||
* - due to the half duplex limitations on return codes, we always have to read *something*.
|
||||
* - without the read, write only transactions *always* succeed, even during the boot process where the slave is not ready.
|
||||
*/
|
||||
if (!receive(&sstd_index_shake, sizeof(sstd_index_shake)) || (sstd_index_shake != (sstd_index ^ HANDSHAKE_MAGIC))) {
|
||||
dprintln("USART: Handshake failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
|
||||
/* Send transaction buffer to the slave. If this transaction requires it. */
|
||||
if (trans->initiator2target_buffer_size) {
|
||||
if (!send(split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
dprintln("USART: Send failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive transaction buffer from the slave. If this transaction requires it. */
|
||||
if (trans->target2initiator_buffer_size) {
|
||||
if (!receive(split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
dprintln("USART: Receive failed.");
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRANSACTION_END;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/* Copyright 2021 QMK
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
#include "serial.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#if !defined(SERIAL_USART_DRIVER)
|
||||
# define SERIAL_USART_DRIVER SD1
|
||||
#endif
|
||||
|
||||
#if !defined(USE_GPIOV1)
|
||||
/* The default PAL alternate modes are used to signal that the pins are used for USART. */
|
||||
# if !defined(SERIAL_USART_TX_PAL_MODE)
|
||||
# define SERIAL_USART_TX_PAL_MODE 7
|
||||
# endif
|
||||
# if !defined(SERIAL_USART_RX_PAL_MODE)
|
||||
# define SERIAL_USART_RX_PAL_MODE 7
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(SOFT_SERIAL_PIN)
|
||||
# define SERIAL_USART_TX_PIN SOFT_SERIAL_PIN
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_TX_PIN)
|
||||
# define SERIAL_USART_TX_PIN A9
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_RX_PIN)
|
||||
# define SERIAL_USART_RX_PIN A10
|
||||
#endif
|
||||
|
||||
#if !defined(USART_CR1_M0)
|
||||
# define USART_CR1_M0 USART_CR1_M // some platforms (f1xx) dont have this so
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR1)
|
||||
# define SERIAL_USART_CR1 (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0) // parity enable, odd parity, 9 bit length
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR2)
|
||||
# define SERIAL_USART_CR2 (USART_CR2_STOP_1) // 2 stop bits
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_CR3)
|
||||
# define SERIAL_USART_CR3 0
|
||||
#endif
|
||||
|
||||
#if defined(USART1_REMAP)
|
||||
# define USART_REMAP \
|
||||
do { \
|
||||
(AFIO->MAPR |= AFIO_MAPR_USART1_REMAP); \
|
||||
} while (0)
|
||||
#elif defined(USART2_REMAP)
|
||||
# define USART_REMAP \
|
||||
do { \
|
||||
(AFIO->MAPR |= AFIO_MAPR_USART2_REMAP); \
|
||||
} while (0)
|
||||
#elif defined(USART3_PARTIALREMAP)
|
||||
# define USART_REMAP \
|
||||
do { \
|
||||
(AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_PARTIALREMAP); \
|
||||
} while (0)
|
||||
#elif defined(USART3_FULLREMAP)
|
||||
# define USART_REMAP \
|
||||
do { \
|
||||
(AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if !defined(SELECT_SOFT_SERIAL_SPEED)
|
||||
# define SELECT_SOFT_SERIAL_SPEED 1
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_USART_SPEED)
|
||||
// Allow advanced users to directly set SERIAL_USART_SPEED
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 0
|
||||
# define SERIAL_USART_SPEED 460800
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 1
|
||||
# define SERIAL_USART_SPEED 230400
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 2
|
||||
# define SERIAL_USART_SPEED 115200
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 3
|
||||
# define SERIAL_USART_SPEED 57600
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 4
|
||||
# define SERIAL_USART_SPEED 38400
|
||||
#elif SELECT_SOFT_SERIAL_SPEED == 5
|
||||
# define SERIAL_USART_SPEED 19200
|
||||
#else
|
||||
# error invalid SELECT_SOFT_SERIAL_SPEED value
|
||||
#endif
|
||||
|
||||
#if !defined(SERIAL_USART_TIMEOUT)
|
||||
# define SERIAL_USART_TIMEOUT 20
|
||||
#endif
|
||||
|
||||
#define HANDSHAKE_MAGIC 7
|
||||
@@ -0,0 +1,202 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "spi_master.h"
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
static pin_t currentSlavePin = NO_PIN;
|
||||
|
||||
#if defined(K20x) || defined(KL2x)
|
||||
static SPIConfig spiConfig = {NULL, 0, 0, 0};
|
||||
#else
|
||||
static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0};
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) void spi_init(void) {
|
||||
static bool is_initialised = false;
|
||||
if (!is_initialised) {
|
||||
is_initialised = true;
|
||||
|
||||
// Try releasing special pins for a short time
|
||||
setPinInput(SPI_SCK_PIN);
|
||||
setPinInput(SPI_MOSI_PIN);
|
||||
setPinInput(SPI_MISO_PIN);
|
||||
|
||||
chThdSleepMilliseconds(10);
|
||||
#if defined(USE_GPIOV1)
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), SPI_SCK_PAL_MODE);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), SPI_MOSI_PAL_MODE);
|
||||
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), SPI_MISO_PAL_MODE);
|
||||
#else
|
||||
palSetPadMode(PAL_PORT(SPI_SCK_PIN), PAL_PAD(SPI_SCK_PIN), PAL_MODE_ALTERNATE(SPI_SCK_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
palSetPadMode(PAL_PORT(SPI_MOSI_PIN), PAL_PAD(SPI_MOSI_PIN), PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
palSetPadMode(PAL_PORT(SPI_MISO_PIN), PAL_PAD(SPI_MISO_PIN), PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE) | PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) {
|
||||
if (currentSlavePin != NO_PIN || slavePin == NO_PIN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t roundedDivisor = 2;
|
||||
while (roundedDivisor < divisor) {
|
||||
roundedDivisor <<= 1;
|
||||
}
|
||||
|
||||
if (roundedDivisor < 2 || roundedDivisor > 256) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(K20x) || defined(KL2x)
|
||||
spiConfig.tar0 = SPIx_CTARn_FMSZ(7) | SPIx_CTARn_ASC(1);
|
||||
|
||||
if (lsbFirst) {
|
||||
spiConfig.tar0 |= SPIx_CTARn_LSBFE;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPHA;
|
||||
break;
|
||||
case 2:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPOL;
|
||||
break;
|
||||
case 3:
|
||||
spiConfig.tar0 |= SPIx_CTARn_CPHA | SPIx_CTARn_CPOL;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (roundedDivisor) {
|
||||
case 2:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(0);
|
||||
break;
|
||||
case 4:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(1);
|
||||
break;
|
||||
case 8:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(3);
|
||||
break;
|
||||
case 16:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(4);
|
||||
break;
|
||||
case 32:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(5);
|
||||
break;
|
||||
case 64:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(6);
|
||||
break;
|
||||
case 128:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(7);
|
||||
break;
|
||||
case 256:
|
||||
spiConfig.tar0 |= SPIx_CTARn_BR(8);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
spiConfig.cr1 = 0;
|
||||
|
||||
if (lsbFirst) {
|
||||
spiConfig.cr1 |= SPI_CR1_LSBFIRST;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
spiConfig.cr1 |= SPI_CR1_CPHA;
|
||||
break;
|
||||
case 2:
|
||||
spiConfig.cr1 |= SPI_CR1_CPOL;
|
||||
break;
|
||||
case 3:
|
||||
spiConfig.cr1 |= SPI_CR1_CPHA | SPI_CR1_CPOL;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (roundedDivisor) {
|
||||
case 2:
|
||||
break;
|
||||
case 4:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_0;
|
||||
break;
|
||||
case 8:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_1;
|
||||
break;
|
||||
case 16:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0;
|
||||
break;
|
||||
case 32:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_2;
|
||||
break;
|
||||
case 64:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_0;
|
||||
break;
|
||||
case 128:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1;
|
||||
break;
|
||||
case 256:
|
||||
spiConfig.cr1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
currentSlavePin = slavePin;
|
||||
spiConfig.ssport = PAL_PORT(slavePin);
|
||||
spiConfig.sspad = PAL_PAD(slavePin);
|
||||
|
||||
setPinOutput(slavePin);
|
||||
spiStart(&SPI_DRIVER, &spiConfig);
|
||||
spiSelect(&SPI_DRIVER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
spi_status_t spi_write(uint8_t data) {
|
||||
uint8_t rxData;
|
||||
spiExchange(&SPI_DRIVER, 1, &data, &rxData);
|
||||
|
||||
return rxData;
|
||||
}
|
||||
|
||||
spi_status_t spi_read(void) {
|
||||
uint8_t data = 0;
|
||||
spiReceive(&SPI_DRIVER, 1, &data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
spi_status_t spi_transmit(const uint8_t *data, uint16_t length) {
|
||||
spiSend(&SPI_DRIVER, length, data);
|
||||
return SPI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
spi_status_t spi_receive(uint8_t *data, uint16_t length) {
|
||||
spiReceive(&SPI_DRIVER, length, data);
|
||||
return SPI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void spi_stop(void) {
|
||||
if (currentSlavePin != NO_PIN) {
|
||||
spiUnselect(&SPI_DRIVER);
|
||||
spiStop(&SPI_DRIVER);
|
||||
currentSlavePin = NO_PIN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Copyright 2020 Nick Brassel (tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "chibios_config.h"
|
||||
|
||||
#ifndef SPI_DRIVER
|
||||
# define SPI_DRIVER SPID2
|
||||
#endif
|
||||
|
||||
#ifndef SPI_SCK_PIN
|
||||
# define SPI_SCK_PIN B13
|
||||
#endif
|
||||
|
||||
#ifndef SPI_SCK_PAL_MODE
|
||||
# if defined(USE_GPIOV1)
|
||||
# define SPI_SCK_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
|
||||
# else
|
||||
# define SPI_SCK_PAL_MODE 5
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SPI_MOSI_PIN
|
||||
# define SPI_MOSI_PIN B15
|
||||
#endif
|
||||
|
||||
#ifndef SPI_MOSI_PAL_MODE
|
||||
# if defined(USE_GPIOV1)
|
||||
# define SPI_MOSI_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
|
||||
# else
|
||||
# define SPI_MOSI_PAL_MODE 5
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SPI_MISO_PIN
|
||||
# define SPI_MISO_PIN B14
|
||||
#endif
|
||||
|
||||
#ifndef SPI_MISO_PAL_MODE
|
||||
# if defined(USE_GPIOV1)
|
||||
# define SPI_MISO_PAL_MODE PAL_MODE_STM32_ALTERNATE_PUSHPULL
|
||||
# else
|
||||
# define SPI_MISO_PAL_MODE 5
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef int16_t spi_status_t;
|
||||
|
||||
#define SPI_STATUS_SUCCESS (0)
|
||||
#define SPI_STATUS_ERROR (-1)
|
||||
#define SPI_STATUS_TIMEOUT (-2)
|
||||
|
||||
#define SPI_TIMEOUT_IMMEDIATE (0)
|
||||
#define SPI_TIMEOUT_INFINITE (0xFFFF)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void spi_init(void);
|
||||
|
||||
bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor);
|
||||
|
||||
spi_status_t spi_write(uint8_t data);
|
||||
|
||||
spi_status_t spi_read(void);
|
||||
|
||||
spi_status_t spi_transmit(const uint8_t *data, uint16_t length);
|
||||
|
||||
spi_status_t spi_receive(uint8_t *data, uint16_t length);
|
||||
|
||||
void spi_stop(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright 2021
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
static SerialConfig serialConfig = {SERIAL_DEFAULT_BITRATE, SD1_CR1, SD1_CR2, SD1_CR3};
|
||||
|
||||
void uart_init(uint32_t baud) {
|
||||
static bool is_initialised = false;
|
||||
|
||||
if (!is_initialised) {
|
||||
is_initialised = true;
|
||||
|
||||
serialConfig.speed = baud;
|
||||
|
||||
#if defined(USE_GPIOV1)
|
||||
palSetLineMode(SD1_TX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
|
||||
palSetLineMode(SD1_RX_PIN, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
|
||||
#else
|
||||
palSetLineMode(SD1_TX_PIN, PAL_MODE_ALTERNATE(SD1_TX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
palSetLineMode(SD1_RX_PIN, PAL_MODE_ALTERNATE(SD1_RX_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
#endif
|
||||
sdStart(&SERIAL_DRIVER, &serialConfig);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_putchar(uint8_t c) { sdPut(&SERIAL_DRIVER, c); }
|
||||
|
||||
uint8_t uart_getchar(void) {
|
||||
msg_t res = sdGet(&SERIAL_DRIVER);
|
||||
|
||||
return (uint8_t)res;
|
||||
}
|
||||
|
||||
bool uart_available(void) { return !sdGetWouldBlock(&SERIAL_DRIVER); }
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Copyright 2021
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
#ifndef SERIAL_DRIVER
|
||||
# define SERIAL_DRIVER SD1
|
||||
#endif
|
||||
|
||||
#ifndef SD1_TX_PIN
|
||||
# define SD1_TX_PIN A9
|
||||
#endif
|
||||
|
||||
#ifndef SD1_TX_PAL_MODE
|
||||
# define SD1_TX_PAL_MODE 7
|
||||
#endif
|
||||
|
||||
#ifndef SD1_RX_PIN
|
||||
# define SD1_RX_PIN A10
|
||||
#endif
|
||||
|
||||
#ifndef SD1_RX_PAL_MODE
|
||||
# define SD1_RX_PAL_MODE 7
|
||||
#endif
|
||||
|
||||
#ifndef SD1_CTS_PIN
|
||||
# define SD1_CTS_PIN A11
|
||||
#endif
|
||||
|
||||
#ifndef SD1_CTS_PAL_MODE
|
||||
# define SD1_CTS_PAL_MODE 7
|
||||
#endif
|
||||
|
||||
#ifndef SD1_RTS_PIN
|
||||
# define SD1_RTS_PIN A12
|
||||
#endif
|
||||
|
||||
#ifndef SD1_RTS_PAL_MODE
|
||||
# define SD1_RTS_PAL_MODE 7
|
||||
#endif
|
||||
|
||||
#ifndef SD1_CR1
|
||||
# define SD1_CR1 0
|
||||
#endif
|
||||
|
||||
#ifndef SD1_CR2
|
||||
# define SD1_CR2 0
|
||||
#endif
|
||||
|
||||
#ifndef SD1_CR3
|
||||
# define SD1_CR3 0
|
||||
#endif
|
||||
|
||||
void uart_init(uint32_t baud);
|
||||
|
||||
void uart_putchar(uint8_t c);
|
||||
|
||||
uint8_t uart_getchar(void);
|
||||
|
||||
bool uart_available(void);
|
||||
@@ -0,0 +1,76 @@
|
||||
/* Copyright 2021 Nick Brassel (@tzarc)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <quantum.h>
|
||||
|
||||
#ifndef USBPD_UCPD1_CFG1
|
||||
# define USBPD_UCPD1_CFG1 (UCPD_CFG1_PSC_UCPDCLK_0 | UCPD_CFG1_TRANSWIN_3 | UCPD_CFG1_IFRGAP_4 | UCPD_CFG1_HBITCLKDIV_4)
|
||||
#endif // USBPD_UCPD1_CFG1
|
||||
|
||||
// Initialises the USBPD subsystem
|
||||
__attribute__((weak)) void usbpd_init(void) {
|
||||
// Disable dead-battery signals
|
||||
PWR->CR3 |= PWR_CR3_UCPD_DBDIS;
|
||||
// Enable the clock for the UCPD1 peripheral
|
||||
RCC->APB1ENR2 |= RCC_APB1ENR2_UCPD1EN;
|
||||
|
||||
// Copy the existing value
|
||||
uint32_t CFG1 = UCPD1->CFG1;
|
||||
// Force-disable UCPD1 before configuring
|
||||
CFG1 &= ~UCPD_CFG1_UCPDEN;
|
||||
// Configure UCPD1
|
||||
CFG1 = USBPD_UCPD1_CFG1;
|
||||
// Apply the changes
|
||||
UCPD1->CFG1 = CFG1;
|
||||
// Enable UCPD1
|
||||
UCPD1->CFG1 |= UCPD_CFG1_UCPDEN;
|
||||
|
||||
// Copy the existing value
|
||||
uint32_t CR = UCPD1->CR;
|
||||
// Clear out ANASUBMODE (irrelevant as a sink device)
|
||||
CR &= ~UCPD_CR_ANASUBMODE_Msk;
|
||||
// Advertise our capabilities as a sink, with both CC lines enabled
|
||||
CR |= UCPD_CR_ANAMODE | UCPD_CR_CCENABLE_Msk;
|
||||
// Apply the changes
|
||||
UCPD1->CR = CR;
|
||||
}
|
||||
|
||||
// Gets the current state of the USBPD allowance
|
||||
__attribute__((weak)) usbpd_allowance_t usbpd_get_allowance(void) {
|
||||
uint32_t CR = UCPD1->CR;
|
||||
|
||||
int ucpd_enabled = (UCPD1->CFG1 & UCPD_CFG1_UCPDEN_Msk) >> UCPD_CFG1_UCPDEN_Pos;
|
||||
int anamode = (CR & UCPD_CR_ANAMODE_Msk) >> UCPD_CR_ANAMODE_Pos;
|
||||
int cc_enabled = (CR & UCPD_CR_CCENABLE_Msk) >> UCPD_CR_CCENABLE_Pos;
|
||||
|
||||
if (ucpd_enabled && anamode && cc_enabled) {
|
||||
uint32_t SR = UCPD1->SR;
|
||||
int vstate_cc1 = (SR & UCPD_SR_TYPEC_VSTATE_CC1_Msk) >> UCPD_SR_TYPEC_VSTATE_CC1_Pos;
|
||||
int vstate_cc2 = (SR & UCPD_SR_TYPEC_VSTATE_CC2_Msk) >> UCPD_SR_TYPEC_VSTATE_CC2_Pos;
|
||||
int vstate_max = vstate_cc1 > vstate_cc2 ? vstate_cc1 : vstate_cc2;
|
||||
switch (vstate_max) {
|
||||
case 0:
|
||||
case 1:
|
||||
return USBPD_500MA; // Note that this is 500mA (i.e. max USB 2.0), not 900mA, as we're not using USB 3.1 as a sink device.
|
||||
case 2:
|
||||
return USBPD_1500MA;
|
||||
case 3:
|
||||
return USBPD_3000MA;
|
||||
}
|
||||
}
|
||||
|
||||
return USBPD_500MA;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "quantum.h"
|
||||
#include "ws2812.h"
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
/* Adapted from https://github.com/bigjosh/SimpleNeoPixelDemo/ */
|
||||
|
||||
#ifndef NOP_FUDGE
|
||||
# if defined(STM32F0XX) || defined(STM32F1XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32L0XX)
|
||||
# define NOP_FUDGE 0.4
|
||||
# else
|
||||
# error("NOP_FUDGE configuration required")
|
||||
# define NOP_FUDGE 1 // this just pleases the compile so the above error is easier to spot
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Push Pull or Open Drain Configuration
|
||||
// Default Push Pull
|
||||
#ifndef WS2812_EXTERNAL_PULLUP
|
||||
# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_PUSHPULL
|
||||
#else
|
||||
# define WS2812_OUTPUT_MODE PAL_MODE_OUTPUT_OPENDRAIN
|
||||
#endif
|
||||
|
||||
#define NUMBER_NOPS 6
|
||||
#define CYCLES_PER_SEC (STM32_SYSCLK / NUMBER_NOPS * NOP_FUDGE)
|
||||
#define NS_PER_SEC (1000000000L) // Note that this has to be SIGNED since we want to be able to check for negative values of derivatives
|
||||
#define NS_PER_CYCLE (NS_PER_SEC / CYCLES_PER_SEC)
|
||||
#define NS_TO_CYCLES(n) ((n) / NS_PER_CYCLE)
|
||||
|
||||
#define wait_ns(x) \
|
||||
do { \
|
||||
for (int i = 0; i < NS_TO_CYCLES(x); i++) { \
|
||||
__asm__ volatile("nop\n\t" \
|
||||
"nop\n\t" \
|
||||
"nop\n\t" \
|
||||
"nop\n\t" \
|
||||
"nop\n\t" \
|
||||
"nop\n\t"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// These are the timing constraints taken mostly from the WS2812 datasheets
|
||||
// These are chosen to be conservative and avoid problems rather than for maximum throughput
|
||||
|
||||
#define T1H 900 // Width of a 1 bit in ns
|
||||
#define T1L (1250 - T1H) // Width of a 1 bit in ns
|
||||
|
||||
#define T0H 350 // Width of a 0 bit in ns
|
||||
#define T0L (1250 - T0H) // Width of a 0 bit in ns
|
||||
|
||||
// The reset gap can be 6000 ns, but depending on the LED strip it may have to be increased
|
||||
// to values like 600000 ns. If it is too small, the pixels will show nothing most of the time.
|
||||
#define RES (1000 * WS2812_TRST_US) // Width of the low gap between bits to cause a frame to latch
|
||||
|
||||
void sendByte(uint8_t byte) {
|
||||
// WS2812 protocol wants most significant bits first
|
||||
for (unsigned char bit = 0; bit < 8; bit++) {
|
||||
bool is_one = byte & (1 << (7 - bit));
|
||||
// using something like wait_ns(is_one ? T1L : T0L) here throws off timings
|
||||
if (is_one) {
|
||||
// 1
|
||||
writePinHigh(RGB_DI_PIN);
|
||||
wait_ns(T1H);
|
||||
writePinLow(RGB_DI_PIN);
|
||||
wait_ns(T1L);
|
||||
} else {
|
||||
// 0
|
||||
writePinHigh(RGB_DI_PIN);
|
||||
wait_ns(T0H);
|
||||
writePinLow(RGB_DI_PIN);
|
||||
wait_ns(T0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws2812_init(void) { palSetLineMode(RGB_DI_PIN, WS2812_OUTPUT_MODE); }
|
||||
|
||||
// Setleds for standard RGB
|
||||
void ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) {
|
||||
static bool s_init = false;
|
||||
if (!s_init) {
|
||||
ws2812_init();
|
||||
s_init = true;
|
||||
}
|
||||
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
chSysLock();
|
||||
|
||||
for (uint8_t i = 0; i < leds; i++) {
|
||||
// WS2812 protocol dictates grb order
|
||||
#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
|
||||
sendByte(ledarray[i].g);
|
||||
sendByte(ledarray[i].r);
|
||||
sendByte(ledarray[i].b);
|
||||
#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_RGB)
|
||||
sendByte(ledarray[i].r);
|
||||
sendByte(ledarray[i].g);
|
||||
sendByte(ledarray[i].b);
|
||||
#elif (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_BGR)
|
||||
sendByte(ledarray[i].b);
|
||||
sendByte(ledarray[i].g);
|
||||
sendByte(ledarray[i].r);
|
||||
#endif
|
||||
|
||||
#ifdef RGBW
|
||||
sendByte(ledarray[i].w);
|
||||
#endif
|
||||
}
|
||||
|
||||
wait_ns(RES);
|
||||
|
||||
chSysUnlock();
|
||||
}
|
||||
Loaded 100 of 10266 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user