mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
merge samd51 and same5x
This commit is contained in:
parent
1cf68f98b3
commit
4b86b49260
2
.github/workflows/build_arm.yml
vendored
2
.github/workflows/build_arm.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
family:
|
||||
# Alphabetical order
|
||||
- 'mm32'
|
||||
- 'samd11 same5x'
|
||||
- 'same5x'
|
||||
- 'tm4c123 xmc4000'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
|
2
.github/workflows/build_cmake.yml
vendored
2
.github/workflows/build_cmake.yml
vendored
@ -48,7 +48,7 @@ jobs:
|
||||
- 'nrf'
|
||||
- 'ra'
|
||||
- 'rp2040'
|
||||
- 'samd21 saml2x samd51'
|
||||
- 'samd11 samd21 saml2x samd51'
|
||||
- 'stm32f0'
|
||||
- 'stm32f1'
|
||||
- 'stm32f2'
|
||||
|
@ -1,7 +1,7 @@
|
||||
include_guard()
|
||||
|
||||
set(MCU_VARIANT samd11)
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/${MCU_VARIANT})
|
||||
set(SAM_FAMILY samd11)
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY})
|
||||
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
|
||||
@ -27,11 +27,11 @@ function(add_board_target BOARD_TARGET)
|
||||
message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined")
|
||||
endif ()
|
||||
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${MCU_VARIANT}.c)
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c)
|
||||
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
|
||||
|
||||
add_library(${BOARD_TARGET} STATIC
|
||||
${SDK_DIR}/gcc/system_${MCU_VARIANT}.c
|
||||
${SDK_DIR}/gcc/system_${SAM_FAMILY}.c
|
||||
${SDK_DIR}/hal/src/hal_atomic.c
|
||||
${SDK_DIR}/hpl/gclk/hpl_gclk.c
|
||||
${SDK_DIR}/hpl/pm/hpl_pm.c
|
||||
|
13
hw/bsp/samd51/boards/d5035_01/board.cmake
Normal file
13
hw/bsp/samd51/boards/d5035_01/board.cmake
Normal file
@ -0,0 +1,13 @@
|
||||
set(SAM_FAMILY same51)
|
||||
|
||||
set(JLINK_DEVICE ATSAME51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/same51j19a_flash.ld)
|
||||
|
||||
function(update_board TARGET)
|
||||
target_compile_definitions(${TARGET} PUBLIC
|
||||
__SAME51J19A__
|
||||
SVC_Handler=SVCall_Handler
|
||||
CONF_CPU_FREQUENCY=80000000
|
||||
CONF_GCLK_USB_FREQUENCY=48000000
|
||||
)
|
||||
endfunction()
|
198
hw/bsp/samd51/boards/d5035_01/board.h
Normal file
198
hw/bsp/samd51/boards/d5035_01/board.h
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H_
|
||||
#define BOARD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// LED
|
||||
#define LED_PIN PIN_PA02
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// Button: no button
|
||||
|
||||
// UART: HWREV < 3: SERCOM5 on PB02, otherwise SERCOM0 on PA08
|
||||
// XTAL configure is also different for HWREV as well
|
||||
|
||||
#if 0
|
||||
static inline void init_clock(void) {
|
||||
/* AUTOWS is enabled by default in REG_NVMCTRL_CTRLA - no need to change the number of wait states when changing the core clock */
|
||||
#if HWREV == 1
|
||||
/* configure XOSC1 for a 16MHz crystal connected to XIN1/XOUT1 */
|
||||
OSCCTRL->XOSCCTRL[1].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY1);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#else // HWREV >= 1
|
||||
/* configure XOSC0 for a 16MHz crystal connected to XIN0/XOUT0 */
|
||||
OSCCTRL->XOSCCTRL[0].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while (0 == OSCCTRL->STATUS.bit.XOSCRDY0);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(
|
||||
OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg =
|
||||
OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while (0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(
|
||||
OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg =
|
||||
OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while (0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#endif // HWREV
|
||||
|
||||
/* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */
|
||||
GCLK->GENCTRL[0].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 | /* DPLL0 */
|
||||
GCLK_GENCTRL_IDC;
|
||||
while (1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 1 to use DPLL1 as source -> for use with some peripheral */
|
||||
GCLK->GENCTRL[1].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL1 |
|
||||
GCLK_GENCTRL_IDC;
|
||||
while (1 == GCLK->SYNCBUSY.bit.GENCTRL1); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 2 to use DPLL0 as source -> for use with SERCOM */
|
||||
GCLK->GENCTRL[2].reg =
|
||||
GCLK_GENCTRL_DIV(1) | /* 80MHz */
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 |
|
||||
GCLK_GENCTRL_IDC;
|
||||
while (1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */
|
||||
}
|
||||
|
||||
static inline void uart_init(void) {
|
||||
#if HWREV < 3
|
||||
/* configure SERCOM5 on PB02 */
|
||||
PORT->Group[1].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(3) | /* function D */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0004) | /* PB02 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBDMASK.bit.SERCOM5_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg =
|
||||
GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while (SERCOM5->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM5->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM5->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM5->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM5->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM5->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while (SERCOM5->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#else
|
||||
/* configure SERCOM0 on PA08 */
|
||||
PORT->Group[0].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(2) | /* function C */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0100) | /* PA08 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBAMASK.bit.SERCOM0_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM0->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM0->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM0->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM0->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H_ */
|
@ -1,4 +1,4 @@
|
||||
MCU = same51
|
||||
SAM_FAMILY = same51
|
||||
|
||||
HWREV ?= 1
|
||||
|
@ -44,6 +44,8 @@ MEMORY
|
||||
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
|
||||
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x1000;
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
@ -1,3 +1,5 @@
|
||||
set(SAM_FAMILY samd51)
|
||||
|
||||
set(JLINK_DEVICE ATSAMD51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
SAM_FAMILY = samd51
|
||||
|
||||
CFLAGS += -D__SAMD51J19A__
|
||||
|
||||
LD_FILE = $(BOARD_PATH)/$(BOARD).ld
|
||||
|
@ -1,3 +1,5 @@
|
||||
set(SAM_FAMILY samd51)
|
||||
|
||||
set(JLINK_DEVICE ATSAMD51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
SAM_FAMILY = samd51
|
||||
|
||||
CFLAGS += -D__SAMD51J19A__
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
|
@ -1,3 +1,5 @@
|
||||
set(SAM_FAMILY samd51)
|
||||
|
||||
set(JLINK_DEVICE ATSAMD51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
SAM_FAMILY = samd51
|
||||
|
||||
CFLAGS += -D__SAMD51J19A__
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
|
@ -1,3 +1,5 @@
|
||||
set(SAM_FAMILY samd51)
|
||||
|
||||
set(JLINK_DEVICE ATSAMD51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
SAM_FAMILY = samd51
|
||||
|
||||
CFLAGS += -D__SAMD51J19A__
|
||||
|
||||
LD_FILE = $(BOARD_PATH)/$(BOARD).ld
|
||||
|
@ -1,3 +1,5 @@
|
||||
set(SAM_FAMILY samd51)
|
||||
|
||||
set(JLINK_DEVICE ATSAMD51J19)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
SAM_FAMILY = samd51
|
||||
|
||||
CFLAGS += -D__SAMD51J19A__
|
||||
|
||||
LD_FILE = $(BOARD_PATH)/$(BOARD).ld
|
||||
|
10
hw/bsp/samd51/boards/same54_xplained/board.cmake
Normal file
10
hw/bsp/samd51/boards/same54_xplained/board.cmake
Normal file
@ -0,0 +1,10 @@
|
||||
set(SAM_FAMILY same54)
|
||||
|
||||
set(JLINK_DEVICE ATSAME54P20)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/same54p20a_flash.ld)
|
||||
|
||||
function(update_board TARGET)
|
||||
target_compile_definitions(${TARGET} PUBLIC
|
||||
__SAME54P20A__
|
||||
)
|
||||
endfunction()
|
50
hw/bsp/samd51/boards/same54_xplained/board.h
Normal file
50
hw/bsp/samd51/boards/same54_xplained/board.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H_
|
||||
#define BOARD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// LED
|
||||
#define LED_PIN PIN_PC18
|
||||
#define LED_STATE_ON 1
|
||||
|
||||
// Button: D5
|
||||
#define BUTTON_PIN PIN_PB31
|
||||
#define BUTTON_STATE_ACTIVE 0
|
||||
|
||||
// UART: SERCOM2
|
||||
//#define UART_TX_PIN 23
|
||||
//#define UART_RX_PIN 22
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H_ */
|
@ -1,9 +1,6 @@
|
||||
MCU = same54
|
||||
SAM_FAMILY = same54
|
||||
|
||||
CFLAGS += \
|
||||
-DCONF_CPU_FREQUENCY=48000000 \
|
||||
-D__SAME54P20A__ \
|
||||
-DBOARD_NAME="\"Microchip SAM E54 Xplained Pro\""
|
||||
CFLAGS += -D__SAME54P20A__
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
LD_FILE = $(BOARD_PATH)/same54p20a_flash.ld
|
@ -44,6 +44,8 @@ MEMORY
|
||||
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
|
||||
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x10000;
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
@ -160,4 +162,5 @@ SECTIONS
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
end = .;
|
||||
}
|
@ -43,6 +43,8 @@ MEMORY
|
||||
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
|
||||
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x10000;
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
@ -159,4 +161,5 @@ SECTIONS
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
end = .;
|
||||
}
|
@ -34,8 +34,8 @@
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
|
||||
#include "hal/include/hal_gpio.h"
|
||||
#include "hal/include/hal_init.h"
|
||||
#include "hal_gpio.h"
|
||||
#include "hal_init.h"
|
||||
#include "hpl/gclk/hpl_gclk_base.h"
|
||||
#include "hpl_mclk_config.h"
|
||||
|
||||
@ -106,9 +106,11 @@ void board_init(void) {
|
||||
gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(LED_PIN, 0);
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
// Button init
|
||||
gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP);
|
||||
#endif
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
|
||||
@ -154,7 +156,11 @@ void board_led_write(bool state) {
|
||||
|
||||
uint32_t board_button_read(void) {
|
||||
// button is active low
|
||||
#ifdef BUTTON_PIN
|
||||
return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
|
||||
@ -194,6 +200,53 @@ uint32_t board_millis(void) {
|
||||
return system_ticks;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Initialize SERCOM2 for 115200 bps 8N1 using a 48 MHz clock */
|
||||
static inline void uart_init(void) {
|
||||
gpio_set_pin_function(PIN_PB24, PINMUX_PB24D_SERCOM2_PAD1);
|
||||
gpio_set_pin_function(PIN_PB25, PINMUX_PB25D_SERCOM2_PAD0);
|
||||
|
||||
MCLK->APBBMASK.bit.SERCOM2_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.bit.SWRST = 1; /* reset and disable SERCOM -> enable configuration */
|
||||
while (BOARD_SERCOM->USART.SYNCBUSY.bit.SWRST);
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.reg =
|
||||
SERCOM_USART_CTRLA_SAMPR(0) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPA(0) | /* 16x over sampling */
|
||||
SERCOM_USART_CTRLA_FORM(0) | /* 0x0 USART frame, 0x1 USART frame with parity, ... */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0x0 USART with external clock, 0x1 USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
BOARD_SERCOM->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN | /* transmitter enabled */
|
||||
SERCOM_USART_CTRLB_RXEN; /* receiver enabled */
|
||||
// BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); /* 48000000/(16*115200) = 26.041666667 */
|
||||
BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_BAUD(63019); /* 65536*(1−16*115200/48000000) */
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while (BOARD_SERCOM->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
}
|
||||
|
||||
static inline void uart_send_buffer(uint8_t const* text, size_t len) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
BOARD_SERCOM->USART.DATA.reg = text[i];
|
||||
while ((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart_send_str(const char* text) {
|
||||
while (*text) {
|
||||
BOARD_SERCOM->USART.DATA.reg = *text++;
|
||||
while ((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -1,16 +1,15 @@
|
||||
include_guard()
|
||||
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/samd51)
|
||||
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
|
||||
|
||||
# include board specific
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
|
||||
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY})
|
||||
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
|
||||
|
||||
# toolchain set up
|
||||
set(CMAKE_SYSTEM_PROCESSOR cortex-m4 CACHE INTERNAL "System Processor")
|
||||
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
|
||||
|
||||
set(FAMILY_MCUS SAMD51 CACHE INTERNAL "")
|
||||
set(FAMILY_MCUS SAMD51 SAME54 CACHE INTERNAL "")
|
||||
set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -c \"set CHIPNAME samd51\" -f target/atsame5x.cfg")
|
||||
|
||||
#------------------------------------
|
||||
@ -27,22 +26,20 @@ function(add_board_target BOARD_TARGET)
|
||||
message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined")
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED STARTUP_FILE_GNU)
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd51.c)
|
||||
endif ()
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c)
|
||||
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
|
||||
|
||||
add_library(${BOARD_TARGET} STATIC
|
||||
${SDK_DIR}/gcc/system_samd51.c
|
||||
${SDK_DIR}/gcc/system_${SAM_FAMILY}.c
|
||||
${SDK_DIR}/hal/src/hal_atomic.c
|
||||
${SDK_DIR}/hpl/gclk/hpl_gclk.c
|
||||
${SDK_DIR}/hpl/mclk/hpl_mclk.c
|
||||
${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c
|
||||
${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c
|
||||
${SDK_DIR}/hal/src/hal_atomic.c
|
||||
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
|
||||
)
|
||||
target_include_directories(${BOARD_TARGET} PUBLIC
|
||||
${SDK_DIR}/
|
||||
${SDK_DIR}
|
||||
${SDK_DIR}/config
|
||||
${SDK_DIR}/include
|
||||
${SDK_DIR}/hal/include
|
||||
|
@ -1,9 +1,10 @@
|
||||
UF2_FAMILY_ID = 0x55114460
|
||||
DEPS_SUBMODULES += hw/mcu/microchip
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m4
|
||||
|
||||
SDK_DIR = hw/mcu/microchip/${SAM_FAMILY}
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-DCFG_TUSB_MCU=OPT_MCU_SAMD51
|
||||
@ -17,23 +18,23 @@ LDFLAGS_GCC += \
|
||||
|
||||
SRC_C += \
|
||||
src/portable/microchip/samd/dcd_samd.c \
|
||||
hw/mcu/microchip/samd51/gcc/gcc/startup_samd51.c \
|
||||
hw/mcu/microchip/samd51/gcc/system_samd51.c \
|
||||
hw/mcu/microchip/samd51/hpl/gclk/hpl_gclk.c \
|
||||
hw/mcu/microchip/samd51/hpl/mclk/hpl_mclk.c \
|
||||
hw/mcu/microchip/samd51/hpl/osc32kctrl/hpl_osc32kctrl.c \
|
||||
hw/mcu/microchip/samd51/hpl/oscctrl/hpl_oscctrl.c \
|
||||
hw/mcu/microchip/samd51/hal/src/hal_atomic.c
|
||||
${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c \
|
||||
${SDK_DIR}/gcc/system_${SAM_FAMILY}.c \
|
||||
${SDK_DIR}/hpl/gclk/hpl_gclk.c \
|
||||
${SDK_DIR}/hpl/mclk/hpl_mclk.c \
|
||||
${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c \
|
||||
${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c \
|
||||
${SDK_DIR}/hal/src/hal_atomic.c
|
||||
|
||||
INC += \
|
||||
$(TOP)/$(BOARD_PATH) \
|
||||
$(TOP)/hw/mcu/microchip/samd51/ \
|
||||
$(TOP)/hw/mcu/microchip/samd51/config \
|
||||
$(TOP)/hw/mcu/microchip/samd51/include \
|
||||
$(TOP)/hw/mcu/microchip/samd51/hal/include \
|
||||
$(TOP)/hw/mcu/microchip/samd51/hal/utils/include \
|
||||
$(TOP)/hw/mcu/microchip/samd51/hpl/port \
|
||||
$(TOP)/hw/mcu/microchip/samd51/hri \
|
||||
$(TOP)/${SDK_DIR} \
|
||||
$(TOP)/${SDK_DIR}/config \
|
||||
$(TOP)/${SDK_DIR}/include \
|
||||
$(TOP)/${SDK_DIR}/hal/include \
|
||||
$(TOP)/${SDK_DIR}/hal/utils/include \
|
||||
$(TOP)/${SDK_DIR}/hpl/port \
|
||||
$(TOP)/${SDK_DIR}/hri \
|
||||
$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
|
||||
|
||||
# flash using bossac at least version 1.8
|
||||
@ -44,3 +45,7 @@ BOSSAC = bossac
|
||||
flash-bossac: $(BUILD)/$(PROJECT).bin
|
||||
@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
|
||||
$(BOSSAC) --port=$(SERIAL) -U -i --offset=0x4000 -e -w $^ -R
|
||||
|
||||
# flash using edbg from https://github.com/ataradov/edbg
|
||||
flash-edbg: $(BUILD)/$(PROJECT).bin
|
||||
edbg --verbose -t $(MCU) -pv -f $<
|
||||
|
@ -1,353 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Jean Gressmann <jean@0x42.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sam.h>
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
#include <hal/include/hal_gpio.h>
|
||||
|
||||
#if CONF_CPU_FREQUENCY != 80000000
|
||||
# error "CONF_CPU_FREQUENCY" must 80000000
|
||||
#endif
|
||||
|
||||
#if CONF_GCLK_USB_FREQUENCY != 48000000
|
||||
# error "CONF_GCLK_USB_FREQUENCY" must 48000000
|
||||
#endif
|
||||
|
||||
#if !defined(HWREV)
|
||||
# error Define "HWREV"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Forward USB interrupt events to TinyUSB IRQ Handler
|
||||
//--------------------------------------------------------------------+
|
||||
void USB_0_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_1_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_2_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_3_Handler (void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define LED_PIN PIN_PA02
|
||||
|
||||
#if HWREV < 3
|
||||
# define BOARD_SERCOM SERCOM5
|
||||
#else
|
||||
# define BOARD_SERCOM SERCOM0
|
||||
#endif
|
||||
|
||||
static inline void init_clock(void)
|
||||
{
|
||||
/* AUTOWS is enabled by default in REG_NVMCTRL_CTRLA - no need to change the number of wait states when changing the core clock */
|
||||
#if HWREV == 1
|
||||
/* configure XOSC1 for a 16MHz crystal connected to XIN1/XOUT1 */
|
||||
OSCCTRL->XOSCCTRL[1].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY1);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC1_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#else // HWREV >= 1
|
||||
/* configure XOSC0 for a 16MHz crystal connected to XIN0/XOUT0 */
|
||||
OSCCTRL->XOSCCTRL[0].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1,953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) |
|
||||
OSCCTRL_XOSCCTRL_IPTAT(3) |
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY0);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(3) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 8, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(39); /* multiply by 40 -> 80 MHz */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(7) | OSCCTRL_DPLLCTRLB_REFCLK(OSCCTRL_DPLLCTRLB_REFCLK_XOSC0_Val); /* pre-scaler = 16, input = XOSC1 */
|
||||
OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR(47); /* multiply by 48 -> 48 MHz */
|
||||
OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL1 to be ready */
|
||||
#endif // HWREV
|
||||
|
||||
/* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */
|
||||
GCLK->GENCTRL[0].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 | /* DPLL0 */
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 1 to use DPLL1 as source -> for use with some peripheral */
|
||||
GCLK->GENCTRL[1].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL1 |
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL1); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* configure clock-generator 2 to use DPLL0 as source -> for use with SERCOM */
|
||||
GCLK->GENCTRL[2].reg =
|
||||
GCLK_GENCTRL_DIV(1) | /* 80MHz */
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 |
|
||||
GCLK_GENCTRL_IDC ;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */
|
||||
}
|
||||
|
||||
static inline void uart_init(void)
|
||||
{
|
||||
#if HWREV < 3
|
||||
/* configure SERCOM5 on PB02 */
|
||||
PORT->Group[1].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(3) | /* function D */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0004) | /* PB02 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBDMASK.bit.SERCOM5_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while(SERCOM5->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM5->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM5->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM5->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM5->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM5->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM5->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while(SERCOM5->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#else
|
||||
/* configure SERCOM0 on PA08 */
|
||||
PORT->Group[0].WRCONFIG.reg =
|
||||
PORT_WRCONFIG_WRPINCFG |
|
||||
PORT_WRCONFIG_WRPMUX |
|
||||
PORT_WRCONFIG_PMUX(2) | /* function C */
|
||||
PORT_WRCONFIG_DRVSTR |
|
||||
PORT_WRCONFIG_PINMASK(0x0100) | /* PA08 */
|
||||
PORT_WRCONFIG_PMUXEN;
|
||||
|
||||
MCLK->APBAMASK.bit.SERCOM0_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN; /* setup SERCOM to use GLCK2 -> 80MHz */
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = 0x00; /* disable SERCOM -> enable config */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE);
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = /* CMODE = 0 -> async, SAMPA = 0, FORM = 0 -> USART frame, SMPR = 0 -> arithmetic baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPR(1) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
// SERCOM_USART_CTRLA_FORM(0) | /* 0 = USART Frame, 2 = LIN Master */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0 = Asynchronous, 1 = USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
SERCOM0->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN; /* transmitter enabled */
|
||||
SERCOM0->USART.CTRLC.reg = 0x00;
|
||||
// 21.701388889 @ baud rate of 230400 bit/s, table 33-2, p 918 of DS60001507E
|
||||
SERCOM0->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(7) | SERCOM_USART_BAUD_FRAC_BAUD(21);
|
||||
|
||||
// SERCOM0->USART.INTENSET.reg = SERCOM_USART_INTENSET_TXC;
|
||||
SERCOM0->SPI.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while(SERCOM0->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void uart_send_buffer(uint8_t const *text, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
BOARD_SERCOM->USART.DATA.reg = text[i];
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart_send_str(const char* text)
|
||||
{
|
||||
while (*text) {
|
||||
BOARD_SERCOM->USART.DATA.reg = *text++;
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_SPI_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
init_clock();
|
||||
|
||||
SystemCoreClock = CONF_CPU_FREQUENCY;
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
|
||||
#endif
|
||||
|
||||
uart_init();
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " UART initialized\n");
|
||||
tu_printf(BOARD_NAME " reset cause %#02x\n", RSTC->RCAUSE.reg);
|
||||
#endif
|
||||
|
||||
// Led init
|
||||
gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(LED_PIN, 0);
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " LED pin configured\n");
|
||||
#endif
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
|
||||
NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_3_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
#endif
|
||||
|
||||
|
||||
#if CFG_TUD_ENABLED
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device enabled\n");
|
||||
#endif
|
||||
|
||||
/* USB clock init
|
||||
* The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
|
||||
* for low speed and full speed operation. */
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
|
||||
hri_mclk_set_AHBMASK_USB_bit(MCLK);
|
||||
hri_mclk_set_APBBMASK_USB_bit(MCLK);
|
||||
|
||||
// USB pin init
|
||||
gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA24, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF);
|
||||
gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA25, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF);
|
||||
|
||||
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
|
||||
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);
|
||||
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device configured\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board porting API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void board_led_write(bool state)
|
||||
{
|
||||
gpio_set_pin_level(LED_PIN, state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read(void)
|
||||
{
|
||||
// this board has no button
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_read(uint8_t* buf, int len)
|
||||
{
|
||||
(void) buf; (void) len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_write(void const * buf, int len)
|
||||
{
|
||||
if (len < 0) {
|
||||
uart_send_str(buf);
|
||||
} else {
|
||||
uart_send_buffer(buf, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
volatile uint32_t system_ticks = 0;
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
system_ticks++;
|
||||
}
|
||||
|
||||
uint32_t board_millis(void)
|
||||
{
|
||||
return system_ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Required by __libc_init_array in startup code if we are compiling using
|
||||
// -nostdlib/-nostartfiles.
|
||||
void _init(void)
|
||||
{
|
||||
|
||||
}
|
@ -1,306 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 Jean Gressmann <jean@0x42.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sam.h>
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
#include <hal/include/hal_gpio.h>
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Forward USB interrupt events to TinyUSB IRQ Handler
|
||||
//--------------------------------------------------------------------+
|
||||
void USB_0_Handler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_1_Handler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_2_Handler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USB_3_Handler(void)
|
||||
{
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define LED_PIN PIN_PC18
|
||||
#define BUTTON_PIN PIN_PB31
|
||||
#define BOARD_SERCOM SERCOM2
|
||||
|
||||
/** Initializes the clocks from the external 12 MHz crystal
|
||||
*
|
||||
* The goal of this setup is to preserve the second PLL
|
||||
* for the application code while still having a reasonable
|
||||
* 48 MHz clock for USB / UART.
|
||||
*
|
||||
* GCLK0: CONF_CPU_FREQUENCY (default 120 MHz) from PLL0
|
||||
* GCLK1: unused
|
||||
* GCLK2: 12 MHz from XOSC1
|
||||
* DFLL48M: closed loop from GLCK2
|
||||
* GCLK3: 48 MHz
|
||||
*/
|
||||
static inline void init_clock_xtal(void)
|
||||
{
|
||||
/* configure for a 12MHz crystal connected to XIN1/XOUT1 */
|
||||
OSCCTRL->XOSCCTRL[1].reg =
|
||||
OSCCTRL_XOSCCTRL_STARTUP(6) | // 1.953 ms
|
||||
OSCCTRL_XOSCCTRL_RUNSTDBY |
|
||||
OSCCTRL_XOSCCTRL_ENALC |
|
||||
OSCCTRL_XOSCCTRL_IMULT(4) | OSCCTRL_XOSCCTRL_IPTAT(3) | // 8MHz to 16MHz
|
||||
OSCCTRL_XOSCCTRL_XTALEN |
|
||||
OSCCTRL_XOSCCTRL_ENABLE;
|
||||
while(0 == OSCCTRL->STATUS.bit.XOSCRDY1);
|
||||
|
||||
OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(2) | OSCCTRL_DPLLCTRLB_REFCLK_XOSC1; /* 12MHz / 6 = 2Mhz, input = XOSC1 */
|
||||
OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x0) | OSCCTRL_DPLLRATIO_LDR((CONF_CPU_FREQUENCY / 1000000 / 2) - 1); /* multiply to get CONF_CPU_FREQUENCY (default = 120MHz) */
|
||||
OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_RUNSTDBY | OSCCTRL_DPLLCTRLA_ENABLE;
|
||||
while(0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY); /* wait for the PLL0 to be ready */
|
||||
|
||||
/* configure clock-generator 0 to use DPLL0 as source -> GCLK0 is used for the core */
|
||||
GCLK->GENCTRL[0].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DPLL0 |
|
||||
GCLK_GENCTRL_IDC;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL0); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
// configure GCLK2 for 12MHz from XOSC1
|
||||
GCLK->GENCTRL[2].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_XOSC1 |
|
||||
GCLK_GENCTRL_IDC;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL2); /* wait for the synchronization between clock domains to be complete */
|
||||
|
||||
/* setup DFLL48M to use GLCK2 */
|
||||
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN;
|
||||
|
||||
OSCCTRL->DFLLCTRLA.reg = 0;
|
||||
while(1 == OSCCTRL->DFLLSYNC.bit.ENABLE);
|
||||
|
||||
OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_MODE | OSCCTRL_DFLLCTRLB_WAITLOCK;
|
||||
OSCCTRL->DFLLMUL.bit.MUL = 4; // 4 * 12MHz -> 48MHz
|
||||
|
||||
OSCCTRL->DFLLCTRLA.reg =
|
||||
OSCCTRL_DFLLCTRLA_ENABLE |
|
||||
OSCCTRL_DFLLCTRLA_RUNSTDBY;
|
||||
while(1 == OSCCTRL->DFLLSYNC.bit.ENABLE);
|
||||
|
||||
// setup 48 MHz GCLK3 from DFLL48M
|
||||
GCLK->GENCTRL[3].reg =
|
||||
GCLK_GENCTRL_DIV(0) |
|
||||
GCLK_GENCTRL_RUNSTDBY |
|
||||
GCLK_GENCTRL_GENEN |
|
||||
GCLK_GENCTRL_SRC_DFLL |
|
||||
GCLK_GENCTRL_IDC;
|
||||
while(1 == GCLK->SYNCBUSY.bit.GENCTRL3);
|
||||
}
|
||||
|
||||
/* Initialize SERCOM2 for 115200 bps 8N1 using a 48 MHz clock */
|
||||
static inline void uart_init(void)
|
||||
{
|
||||
gpio_set_pin_function(PIN_PB24, PINMUX_PB24D_SERCOM2_PAD1);
|
||||
gpio_set_pin_function(PIN_PB25, PINMUX_PB25D_SERCOM2_PAD0);
|
||||
|
||||
MCLK->APBBMASK.bit.SERCOM2_ = 1;
|
||||
GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.bit.SWRST = 1; /* reset and disable SERCOM -> enable configuration */
|
||||
while (BOARD_SERCOM->USART.SYNCBUSY.bit.SWRST);
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.reg =
|
||||
SERCOM_USART_CTRLA_SAMPR(0) | /* 0 = 16x / arithmetic baud rate, 1 = 16x / fractional baud rate */
|
||||
SERCOM_USART_CTRLA_SAMPA(0) | /* 16x over sampling */
|
||||
SERCOM_USART_CTRLA_FORM(0) | /* 0x0 USART frame, 0x1 USART frame with parity, ... */
|
||||
SERCOM_USART_CTRLA_DORD | /* LSB first */
|
||||
SERCOM_USART_CTRLA_MODE(1) | /* 0x0 USART with external clock, 0x1 USART with internal clock */
|
||||
SERCOM_USART_CTRLA_RXPO(1) | /* SERCOM PAD[1] is used for data reception */
|
||||
SERCOM_USART_CTRLA_TXPO(0); /* SERCOM PAD[0] is used for data transmission */
|
||||
|
||||
BOARD_SERCOM->USART.CTRLB.reg = /* RXEM = 0 -> receiver disabled, LINCMD = 0 -> normal USART transmission, SFDE = 0 -> start-of-frame detection disabled, SBMODE = 0 -> one stop bit, CHSIZE = 0 -> 8 bits */
|
||||
SERCOM_USART_CTRLB_TXEN | /* transmitter enabled */
|
||||
SERCOM_USART_CTRLB_RXEN; /* receiver enabled */
|
||||
// BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_FRAC_FP(0) | SERCOM_USART_BAUD_FRAC_BAUD(26); /* 48000000/(16*115200) = 26.041666667 */
|
||||
BOARD_SERCOM->USART.BAUD.reg = SERCOM_USART_BAUD_BAUD(63019); /* 65536*(1−16*115200/48000000) */
|
||||
|
||||
BOARD_SERCOM->USART.CTRLA.bit.ENABLE = 1; /* activate SERCOM */
|
||||
while (BOARD_SERCOM->USART.SYNCBUSY.bit.ENABLE); /* wait for SERCOM to be ready */
|
||||
}
|
||||
|
||||
static inline void uart_send_buffer(uint8_t const *text, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
BOARD_SERCOM->USART.DATA.reg = text[i];
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uart_send_str(const char* text)
|
||||
{
|
||||
while (*text) {
|
||||
BOARD_SERCOM->USART.DATA.reg = *text++;
|
||||
while((BOARD_SERCOM->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
// Uncomment this line and change the GCLK for UART/USB to run off the XTAL.
|
||||
// init_clock_xtal();
|
||||
|
||||
SystemCoreClock = CONF_CPU_FREQUENCY;
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
|
||||
#endif
|
||||
|
||||
uart_init();
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " UART initialized\n");
|
||||
tu_printf(BOARD_NAME " reset cause %#02x\n", RSTC->RCAUSE.reg);
|
||||
#endif
|
||||
|
||||
// LED0 init
|
||||
gpio_set_pin_function(LED_PIN, GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
|
||||
board_led_write(0);
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " LED pin configured\n");
|
||||
#endif
|
||||
|
||||
// BTN0 init
|
||||
gpio_set_pin_function(BUTTON_PIN, GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP);
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " Button pin configured\n");
|
||||
#endif
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
|
||||
NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
NVIC_SetPriority(USB_3_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
#endif
|
||||
|
||||
|
||||
#if CFG_TUD_ENABLED
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device enabled\n");
|
||||
#endif
|
||||
|
||||
/* USB clock init
|
||||
* The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
|
||||
* for low speed and full speed operation.
|
||||
*/
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN);
|
||||
hri_mclk_set_AHBMASK_USB_bit(MCLK);
|
||||
hri_mclk_set_APBBMASK_USB_bit(MCLK);
|
||||
|
||||
// USB pin init
|
||||
gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA24, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF);
|
||||
gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA25, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF);
|
||||
|
||||
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
|
||||
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);
|
||||
|
||||
|
||||
#if CFG_TUSB_DEBUG >= 2
|
||||
uart_send_str(BOARD_NAME " USB device configured\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board porting API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void board_led_write(bool state)
|
||||
{
|
||||
gpio_set_pin_level(LED_PIN, !state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read(void)
|
||||
{
|
||||
return (PORT->Group[1].IN.reg & 0x80000000) != 0x80000000;
|
||||
}
|
||||
|
||||
int board_uart_read(uint8_t* buf, int len)
|
||||
{
|
||||
(void) buf; (void) len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_uart_write(void const * buf, int len)
|
||||
{
|
||||
if (len < 0) {
|
||||
uart_send_str(buf);
|
||||
} else {
|
||||
uart_send_buffer(buf, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
volatile uint32_t system_ticks = 0;
|
||||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
system_ticks++;
|
||||
}
|
||||
|
||||
uint32_t board_millis(void)
|
||||
{
|
||||
return system_ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Required by __libc_init_array in startup code if we are compiling using
|
||||
// -nostdlib/-nostartfiles.
|
||||
void _init(void)
|
||||
{
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
DEPS_SUBMODULES += hw/mcu/microchip
|
||||
|
||||
SDK_DIR = hw/mcu/microchip/$(MCU)
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m4
|
||||
|
||||
CFLAGS += \
|
||||
-mthumb \
|
||||
-mlong-calls \
|
||||
-nostdlib -nostartfiles \
|
||||
-DCFG_TUSB_MCU=OPT_MCU_SAME5X
|
||||
|
||||
# SAM driver is flooded with -Wcast-qual which slow down complication significantly
|
||||
CFLAGS_SKIP += -Wcast-qual
|
||||
|
||||
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
|
||||
|
||||
SRC_C += \
|
||||
src/portable/microchip/samd/dcd_samd.c \
|
||||
$(SDK_DIR)/gcc/gcc/startup_$(MCU).c \
|
||||
$(SDK_DIR)/gcc/system_$(MCU).c \
|
||||
$(SDK_DIR)/hal/utils/src/utils_syscalls.c
|
||||
|
||||
INC += \
|
||||
$(TOP)/$(SDK_DIR) \
|
||||
$(TOP)/$(SDK_DIR)/config \
|
||||
$(TOP)/$(SDK_DIR)/include \
|
||||
$(TOP)/$(SDK_DIR)/hal/include \
|
||||
$(TOP)/$(SDK_DIR)/hal/utils/include \
|
||||
$(TOP)/$(SDK_DIR)/hpl/port \
|
||||
$(TOP)/$(SDK_DIR)/hri \
|
||||
$(TOP)/$(SDK_DIR)/CMSIS/Include
|
||||
|
||||
# flash using edbg from https://github.com/ataradov/edbg
|
||||
flash-edbg: $(BUILD)/$(PROJECT).bin
|
||||
edbg --verbose -t $(MCU) -pv -f $<
|
||||
|
||||
flash: flash-edbg
|
@ -1,4 +1,4 @@
|
||||
set(MCU_VARIANT saml21)
|
||||
set(SAM_FAMILY saml21)
|
||||
set(JLINK_DEVICE ATSAML21J18)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/saml21j18b_flash.ld)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
MCU_VARIANT = saml21
|
||||
SAM_FAMILY = saml21
|
||||
|
||||
CFLAGS += -D__SAML21J18B__
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
set(MCU_VARIANT saml22)
|
||||
set(SAM_FAMILY saml22)
|
||||
set(JLINK_DEVICE ATSAML22J18)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
MCU_VARIANT = saml22
|
||||
SAM_FAMILY = saml22
|
||||
|
||||
CFLAGS += -D__SAML22J18A__
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
set(MCU_VARIANT saml22)
|
||||
set(SAM_FAMILY saml22)
|
||||
set(JLINK_DEVICE ATSAML21J18)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
MCU_VARIANT = saml22
|
||||
SAM_FAMILY = saml22
|
||||
|
||||
CFLAGS += -D__SAML22J18A__
|
||||
|
||||
|
@ -3,7 +3,7 @@ include_guard()
|
||||
# include board specific
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
|
||||
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/${MCU_VARIANT})
|
||||
set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY})
|
||||
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
|
||||
|
||||
# toolchain set up
|
||||
@ -27,11 +27,11 @@ function(add_board_target BOARD_TARGET)
|
||||
message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined")
|
||||
endif ()
|
||||
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${MCU_VARIANT}.c)
|
||||
set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c)
|
||||
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
|
||||
|
||||
add_library(${BOARD_TARGET} STATIC
|
||||
${SDK_DIR}/gcc/system_${MCU_VARIANT}.c
|
||||
${SDK_DIR}/gcc/system_${SAM_FAMILY}.c
|
||||
${SDK_DIR}/hal/src/hal_atomic.c
|
||||
${SDK_DIR}/hpl/gclk/hpl_gclk.c
|
||||
${SDK_DIR}/hpl/mclk/hpl_mclk.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
UF2_FAMILY_ID = 0x68ed2b88
|
||||
SDK_DIR = hw/mcu/microchip/$(MCU_VARIANT)
|
||||
SDK_DIR = hw/mcu/microchip/$(SAM_FAMILY)
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m0plus
|
||||
@ -22,8 +22,8 @@ LDFLAGS_GCC += \
|
||||
|
||||
SRC_C += \
|
||||
src/portable/microchip/samd/dcd_samd.c \
|
||||
$(SDK_DIR)/gcc/gcc/startup_$(MCU_VARIANT).c \
|
||||
$(SDK_DIR)/gcc/system_$(MCU_VARIANT).c \
|
||||
$(SDK_DIR)/gcc/gcc/startup_$(SAM_FAMILY).c \
|
||||
$(SDK_DIR)/gcc/system_$(SAM_FAMILY).c \
|
||||
$(SDK_DIR)/hal/src/hal_atomic.c \
|
||||
$(SDK_DIR)/hpl/gclk/hpl_gclk.c \
|
||||
$(SDK_DIR)/hpl/mclk/hpl_mclk.c \
|
||||
|
Loading…
x
Reference in New Issue
Block a user