diff options
Diffstat (limited to 'keyboard/infinity/mbed-infinity')
-rw-r--r-- | keyboard/infinity/mbed-infinity/README | 39 | ||||
-rw-r--r-- | keyboard/infinity/mbed-infinity/USBHAL_KL25Z.cpp | 557 | ||||
-rw-r--r-- | keyboard/infinity/mbed-infinity/cmsis_nvic.c | 55 | ||||
-rw-r--r-- | keyboard/infinity/mbed-infinity/infinity.ld | 156 | ||||
-rw-r--r-- | keyboard/infinity/mbed-infinity/system_MK20D5.c | 299 |
5 files changed, 1106 insertions, 0 deletions
diff --git a/keyboard/infinity/mbed-infinity/README b/keyboard/infinity/mbed-infinity/README new file mode 100644 index 0000000000..b0d226f793 --- /dev/null +++ b/keyboard/infinity/mbed-infinity/README @@ -0,0 +1,39 @@ +mbed fix for Infinity +===================== +Without linker script patch it doesn't place vector table in final binary. +And clock is configured to 48MHz using internal clock reference and FLL multiplication. + + +mbed/targets/cmsis/TARGET_Freescale/TARGET_K20D50M/system_MK20D5.c + Fix SystemInit: clock setup for internal clock. Inifinity has no external Xtal. + +mbed/targets/cmsis/TARGET_Freescale/TARGET_K20D50M/cmsis_nvic.c + Fix NVIC vector address of firmware 0x1000 instead of 0x0 + +mbed/targets/cmsis/TARGET_Freescale/TARGET_K20D50M/TOOLCHAIN_GCC_ARM/MK20D5.ld + Fix memory map for Infinity bootloader + Flash starts at 0x1000 + No flash config bytes sector + +USBDevice/USBDevice/USBHAL_KL25Z.cpp + Fix USB clock setup, see below. + + +2015/01/04 Based on mbed-sdk @2f63fa7d78a26. + + + +Kinetis USB config +================== +Clock source: Internal reference clock wth FLL + SIM_SOPT[USBSRC] = 1(MCGPLLCLK/MCGFLLCLK) + SIM_SOPT[PLLSEL] = 0(MCGFLLCLK) + +Clock dividor: + SIM_CLKDIV2[USBDIV] = 0 + SIM_CLKDIV2[USBFAC] = 0 + +Clock enable: + SIM_SCGC4[USBOTG] = 1 + + diff --git a/keyboard/infinity/mbed-infinity/USBHAL_KL25Z.cpp b/keyboard/infinity/mbed-infinity/USBHAL_KL25Z.cpp new file mode 100644 index 0000000000..90f02fa322 --- /dev/null +++ b/keyboard/infinity/mbed-infinity/USBHAL_KL25Z.cpp @@ -0,0 +1,557 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* 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. +*/ + +#if defined(TARGET_KL25Z) | defined(TARGET_KL43Z) | defined(TARGET_KL46Z) | defined(TARGET_K20D50M) | defined(TARGET_K64F) | defined(TARGET_K22F) + +#include "USBHAL.h" + +USBHAL * USBHAL::instance; + +static volatile int epComplete = 0; + +// Convert physical endpoint number to register bit +#define EP(endpoint) (1<<(endpoint)) + +// Convert physical to logical +#define PHY_TO_LOG(endpoint) ((endpoint)>>1) + +// Get endpoint direction +#define IN_EP(endpoint) ((endpoint) & 1U ? true : false) +#define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) + +#define BD_OWN_MASK (1<<7) +#define BD_DATA01_MASK (1<<6) +#define BD_KEEP_MASK (1<<5) +#define BD_NINC_MASK (1<<4) +#define BD_DTS_MASK (1<<3) +#define BD_STALL_MASK (1<<2) + +#define TX 1 +#define RX 0 +#define ODD 0 +#define EVEN 1 +// this macro waits a physical endpoint number +#define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd))) + +#define SETUP_TOKEN 0x0D +#define IN_TOKEN 0x09 +#define OUT_TOKEN 0x01 +#define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) + +// for each endpt: 8 bytes +typedef struct BDT { + uint8_t info; // BD[0:7] + uint8_t dummy; // RSVD: BD[8:15] + uint16_t byte_count; // BD[16:32] + uint32_t address; // Addr +} BDT; + + +// there are: +// * 16 bidirectionnal endpt -> 32 physical endpt +// * as there are ODD and EVEN buffer -> 32*2 bdt +__attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; +uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2]; +uint8_t * endpoint_buffer_iso[2*2]; + +static uint8_t set_addr = 0; +static uint8_t addr = 0; + +static uint32_t Data1 = 0x55555555; + +static uint32_t frameNumber() { + return((USB0->FRMNUML | (USB0->FRMNUMH << 8)) & 0x07FF); +} + +uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { + return 0; +} + +USBHAL::USBHAL(void) { + // Disable IRQ + NVIC_DisableIRQ(USB0_IRQn); + +#if defined(TARGET_K64F) + MPU->CESR=0; +#endif + // fill in callback array + epCallback[0] = &USBHAL::EP1_OUT_callback; + epCallback[1] = &USBHAL::EP1_IN_callback; + epCallback[2] = &USBHAL::EP2_OUT_callback; + epCallback[3] = &USBHAL::EP2_IN_callback; + epCallback[4] = &USBHAL::EP3_OUT_callback; + epCallback[5] = &USBHAL::EP3_IN_callback; + epCallback[6] = &USBHAL::EP4_OUT_callback; + epCallback[7] = &USBHAL::EP4_IN_callback; + epCallback[8] = &USBHAL::EP5_OUT_callback; + epCallback[9] = &USBHAL::EP5_IN_callback; + epCallback[10] = &USBHAL::EP6_OUT_callback; + epCallback[11] = &USBHAL::EP6_IN_callback; + epCallback[12] = &USBHAL::EP7_OUT_callback; + epCallback[13] = &USBHAL::EP7_IN_callback; + epCallback[14] = &USBHAL::EP8_OUT_callback; + epCallback[15] = &USBHAL::EP8_IN_callback; + epCallback[16] = &USBHAL::EP9_OUT_callback; + epCallback[17] = &USBHAL::EP9_IN_callback; + epCallback[18] = &USBHAL::EP10_OUT_callback; + epCallback[19] = &USBHAL::EP10_IN_callback; + epCallback[20] = &USBHAL::EP11_OUT_callback; + epCallback[21] = &USBHAL::EP11_IN_callback; + epCallback[22] = &USBHAL::EP12_OUT_callback; + epCallback[23] = &USBHAL::EP12_IN_callback; + epCallback[24] = &USBHAL::EP13_OUT_callback; + epCallback[25] = &USBHAL::EP13_IN_callback; + epCallback[26] = &USBHAL::EP14_OUT_callback; + epCallback[27] = &USBHAL::EP14_IN_callback; + epCallback[28] = &USBHAL::EP15_OUT_callback; + epCallback[29] = &USBHAL::EP15_IN_callback; + +#if defined(TARGET_KL43Z) + // enable USBFS clock + SIM->SCGC4 |= SIM_SCGC4_USBFS_MASK; + + // enable the IRC48M clock + USB0->CLK_RECOVER_IRC_EN |= USB_CLK_RECOVER_IRC_EN_IRC_EN_MASK; + + // enable the USB clock recovery tuning + USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK; + + // choose usb src clock + SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK; +#elif defined(TARGET_INFINITY) + // USB clock source: FLL + SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK; + + // enable OTG clock + SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; +#else + // choose usb src as PLL + SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; + SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | (1 << SIM_SOPT2_PLLFLLSEL_SHIFT)); + + // enable OTG clock + SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; +#endif + + // Attach IRQ + instance = this; + NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr); + NVIC_EnableIRQ(USB0_IRQn); + + // USB Module Configuration + // Reset USB Module + USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; + while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); + + // Set BDT Base Register + USB0->BDTPAGE1 = (uint8_t)((uint32_t)bdt>>8); + USB0->BDTPAGE2 = (uint8_t)((uint32_t)bdt>>16); + USB0->BDTPAGE3 = (uint8_t)((uint32_t)bdt>>24); + + // Clear interrupt flag + USB0->ISTAT = 0xff; + + // USB Interrupt Enablers + USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK | + USB_INTEN_SOFTOKEN_MASK | + USB_INTEN_ERROREN_MASK | + USB_INTEN_USBRSTEN_MASK; + + // Disable weak pull downs + USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK); + + USB0->USBTRC0 |= 0x40; +} + +USBHAL::~USBHAL(void) { } + +void USBHAL::connect(void) { + // enable USB + USB0->CTL |= USB_CTL_USBENSOFEN_MASK; + // Pull up enable + USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; +} + +void USBHAL::disconnect(void) { + // disable USB + USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; + // Pull up disable + USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; + + //Free buffers if required: + for (int i = 0; i<(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2; i++) { + free(endpoint_buffer[i]); + endpoint_buffer[i] = NULL; + } + free(endpoint_buffer_iso[2]); + endpoint_buffer_iso[2] = NULL; + free(endpoint_buffer_iso[0]); + endpoint_buffer_iso[0] = NULL; +} + +void USBHAL::configureDevice(void) { + // not needed +} + +void USBHAL::unconfigureDevice(void) { + // not needed +} + +void USBHAL::setAddress(uint8_t address) { + // we don't set the address now otherwise the usb controller does not ack + // we set a flag instead + // see usbisr when an IN token is received + set_addr = 1; + addr = address; +} + +bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { + uint32_t handshake_flag = 0; + uint8_t * buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return false; + } + + uint32_t log_endpoint = PHY_TO_LOG(endpoint); + + if ((flags & ISOCHRONOUS) == 0) { + handshake_flag = USB_ENDPT_EPHSHK_MASK; + if (IN_EP(endpoint)) { + if (endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] == NULL) + endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)] = (uint8_t *) malloc (64*2); + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD)][0]; + } else { + if (endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] == NULL) + endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)] = (uint8_t *) malloc (64*2); + buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD)][0]; + } + } else { + if (IN_EP(endpoint)) { + if (endpoint_buffer_iso[2] == NULL) + endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2); + buf = &endpoint_buffer_iso[2][0]; + } else { + if (endpoint_buffer_iso[0] == NULL) + endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2); + buf = &endpoint_buffer_iso[0][0]; + } + } + + // IN endpt -> device to host (TX) + if (IN_EP(endpoint)) { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran + bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; + } + // OUT endpt -> host to device (RX) + else { + USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) + USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; + bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; + bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; + } + + Data1 |= (1 << endpoint); + + return true; +} + +// read setup packet +void USBHAL::EP0setup(uint8_t *buffer) { + uint32_t sz; + endpointReadResult(EP0OUT, buffer, &sz); +} + +void USBHAL::EP0readStage(void) { + Data1 &= ~1UL; // set DATA0 + bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); +} + +void USBHAL::EP0read(void) { + uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); + bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; +} + +uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { + uint32_t sz; + endpointReadResult(EP0OUT, buffer, &sz); + return sz; +} + +void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { + endpointWrite(EP0IN, buffer, size); +} + +void USBHAL::EP0getWriteResult(void) { +} + +void USBHAL::EP0stall(void) { + stallEndpoint(EP0OUT); +} + +EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { + endpoint = PHY_TO_LOG(endpoint); + uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); + bdt[idx].byte_count = maximumSize; + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { + uint32_t n, sz, idx, setup = 0; + uint8_t not_iso; + uint8_t * ep_buf; + + uint32_t log_endpoint = PHY_TO_LOG(endpoint); + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return EP_INVALID; + } + + // if read on a IN endpoint -> error + if (IN_EP(endpoint)) { + return EP_INVALID; + } + + idx = EP_BDT_IDX(log_endpoint, RX, 0); + sz = bdt[idx].byte_count; + not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; + + //for isochronous endpoint, we don't wait an interrupt + if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { + return EP_PENDING; + } + + if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { + setup = 1; + } + + // non iso endpoint + if (not_iso) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[0]; + } + + for (n = 0; n < sz; n++) { + buffer[n] = ep_buf[n]; + } + + if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { + if (setup && (buffer[6] == 0)) // if no setup data stage, + Data1 &= ~1UL; // set DATA0 + else + Data1 ^= (1 << endpoint); + } + + if (((Data1 >> endpoint) & 1)) { + bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; + } + else { + bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; + } + + USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; + *bytesRead = sz; + + epComplete &= ~EP(endpoint); + return EP_COMPLETED; +} + +EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { + uint32_t idx, n; + uint8_t * ep_buf; + + if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { + return EP_INVALID; + } + + // if write on a OUT endpoint -> error + if (OUT_EP(endpoint)) { + return EP_INVALID; + } + + idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); + bdt[idx].byte_count = size; + + + // non iso endpoint + if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { + ep_buf = endpoint_buffer[idx]; + } else { + ep_buf = endpoint_buffer_iso[2]; + } + + for (n = 0; n < size; n++) { + ep_buf[n] = data[n]; + } + + if ((Data1 >> endpoint) & 1) { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; + } else { + bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; + } + + Data1 ^= (1 << endpoint); + + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { + if (epComplete & EP(endpoint)) { + epComplete &= ~EP(endpoint); + return EP_COMPLETED; + } + + return EP_PENDING; +} + +void USBHAL::stallEndpoint(uint8_t endpoint) { + USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; +} + +void USBHAL::unstallEndpoint(uint8_t endpoint) { + USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; +} + +bool USBHAL::getEndpointStallState(uint8_t endpoint) { + uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); + return (stall) ? true : false; +} + +void USBHAL::remoteWakeup(void) { + // [TODO] +} + + +void USBHAL::_usbisr(void) { + instance->usbisr(); +} + + +void USBHAL::usbisr(void) { + uint8_t i; + uint8_t istat = USB0->ISTAT; + + // reset interrupt + if (istat & USB_ISTAT_USBRST_MASK) { + // disable all endpt + for(i = 0; i < 16; i++) { + USB0->ENDPOINT[i].ENDPT = 0x00; + } + + // enable control endpoint + realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); + realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); + + Data1 = 0x55555555; + USB0->CTL |= USB_CTL_ODDRST_MASK; + + USB0->ISTAT = 0xFF; // clear all interrupt status flags + USB0->ERRSTAT = 0xFF; // clear all error flags + USB0->ERREN = 0xFF; // enable error interrupt sources + USB0->ADDR = 0x00; // set default address + + return; + } + + // resume interrupt + if (istat & USB_ISTAT_RESUME_MASK) { + USB0->ISTAT = USB_ISTAT_RESUME_MASK; + } + + // SOF interrupt + if (istat & USB_ISTAT_SOFTOK_MASK) { + USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; + // SOF event, read frame number + SOF(frameNumber()); + } + + // stall interrupt + if (istat & 1<<7) { + if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) + USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; + USB0->ISTAT |= USB_ISTAT_STALL_MASK; + } + + // token interrupt + if (istat & 1<<3) { + uint32_t num = (USB0->STAT >> 4) & 0x0F; + uint32_t dir = (USB0->STAT >> 3) & 0x01; + uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; + + // setup packet + if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { + Data1 &= ~0x02; + bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; + bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; + + // EP0 SETUP event (SETUP data received) + EP0setupCallback(); + + } else { + // OUT packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { + if (num == 0) + EP0out(); + else { + epComplete |= (1 << EP(num)); + if ((instance->*(epCallback[EP(num) - 2]))()) { + epComplete &= ~(1 << EP(num)); + } + } + } + + // IN packet + if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { + if (num == 0) { + EP0in(); + if (set_addr == 1) { + USB0->ADDR = addr & 0x7F; + set_addr = 0; + } + } + else { + epComplete |= (1 << (EP(num) + 1)); + if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { + epComplete &= ~(1 << (EP(num) + 1)); + } + } + } + } + + USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; + } + + // sleep interrupt + if (istat & 1<<4) { + USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; + } + + // error interrupt + if (istat & USB_ISTAT_ERROR_MASK) { + USB0->ERRSTAT = 0xFF; + USB0->ISTAT |= USB_ISTAT_ERROR_MASK; + } +} + + +#endif diff --git a/keyboard/infinity/mbed-infinity/cmsis_nvic.c b/keyboard/infinity/mbed-infinity/cmsis_nvic.c new file mode 100644 index 0000000000..985c1d33f5 --- /dev/null +++ b/keyboard/infinity/mbed-infinity/cmsis_nvic.c @@ -0,0 +1,55 @@ +/* mbed Microcontroller Library + * CMSIS-style functionality to support dynamic vectors + ******************************************************************************* + * Copyright (c) 2011 ARM Limited. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of ARM Limited nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ +#include "cmsis_nvic.h" + +#define NVIC_RAM_VECTOR_ADDRESS (0x1FFFE000) // Vectors positioned at start of RAM +#define NVIC_FLASH_VECTOR_ADDRESS (0x1000) // Initial vector position in flash + +void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) { + uint32_t *vectors = (uint32_t*)SCB->VTOR; + uint32_t i; + + // Copy and switch to dynamic vectors if the first time called + if (SCB->VTOR == NVIC_FLASH_VECTOR_ADDRESS) { + uint32_t *old_vectors = vectors; + vectors = (uint32_t*)NVIC_RAM_VECTOR_ADDRESS; + for (i=0; i<NVIC_NUM_VECTORS; i++) { + vectors[i] = old_vectors[i]; + } + SCB->VTOR = (uint32_t)NVIC_RAM_VECTOR_ADDRESS; + } + vectors[IRQn + 16] = vector; +} + +uint32_t NVIC_GetVector(IRQn_Type IRQn) { + uint32_t *vectors = (uint32_t*)SCB->VTOR; + return vectors[IRQn + 16]; +} diff --git a/keyboard/infinity/mbed-infinity/infinity.ld b/keyboard/infinity/mbed-infinity/infinity.ld new file mode 100644 index 0000000000..decdaa26e0 --- /dev/null +++ b/keyboard/infinity/mbed-infinity/infinity.ld @@ -0,0 +1,156 @@ +/* + * Linker script for Massdrop Infinity + * Infinity has bootloader in top 4KB sector of flash and app should be placed after the area. + * + * based on mbed.org K20 ARM GCC linker script file: MK20D5.ld + */ + +MEMORY +{ + /* Infinity blootloader uses 4KB */ + FLASH (rx) : ORIGIN = 4K, LENGTH = 128K - 4K + RAM (rwx) : ORIGIN = 0x1FFFE0F8, LENGTH = 16K - 0xF8 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * _reset_init : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + __vector_table = .; + KEEP(*(.isr_vector)) + *(.text.Reset_Handler) + *(.text.System_Init) + . = ALIGN(4); + + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + __bss_start__ = .; + *(.bss*) + *(COMMON) + __bss_end__ = .; + } > RAM + + .heap : + { + __end__ = .; + end = __end__; + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy : + { + *(.stack) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/keyboard/infinity/mbed-infinity/system_MK20D5.c b/keyboard/infinity/mbed-infinity/system_MK20D5.c new file mode 100644 index 0000000000..4f4e2a2624 --- /dev/null +++ b/keyboard/infinity/mbed-infinity/system_MK20D5.c @@ -0,0 +1,299 @@ +/* +** ################################################################### +** Compilers: ARM Compiler +** Freescale C/C++ for Embedded ARM +** GNU C Compiler +** IAR ANSI C/C++ Compiler for ARM +** +** Reference manuals: K20P64M50SF0RM Rev. 1, Oct 2011 +** K20P32M50SF0RM Rev. 1, Oct 2011 +** K20P48M50SF0RM Rev. 1, Oct 2011 +** +** Version: rev. 1.0, 2011-12-15 +** +** Abstract: +** Provides a system configuration function and a global variable that +** contains the system frequency. It configures the device and initializes +** the oscillator (PLL) that is part of the microcontroller device. +** +** Copyright: 2011 Freescale Semiconductor, Inc. All Rights Reserved. +** +** http: www.freescale.com +** mail: support@freescale.com +** +** Revisions: +** - rev. 1.0 (2011-12-15) +** Initial version +** +** ################################################################### +*/ + +/** + * @file MK20D5 + * @version 1.0 + * @date 2011-12-15 + * @brief Device specific configuration file for MK20D5 (implementation file) + * + * Provides a system configuration function and a global variable that contains + * the system frequency. It configures the device and initializes the oscillator + * (PLL) that is part of the microcontroller device. + */ + +#include <stdint.h> +#include "MK20D5.h" + +#define DISABLE_WDOG 1 + +#define CLOCK_SETUP 3 +/* Predefined clock setups + 0 ... Multipurpose Clock Generator (MCG) in FLL Engaged Internal (FEI) mode + Reference clock source for MCG module is the slow internal clock source 32.768kHz + Core clock = 41.94MHz, BusClock = 41.94MHz + 1 ... Multipurpose Clock Generator (MCG) in PLL Engaged External (PEE) mode + Reference clock source for MCG module is an external crystal 8MHz + Core clock = 48MHz, BusClock = 48MHz + 2 ... Multipurpose Clock Generator (MCG) in Bypassed Low Power External (BLPE) mode + Core clock/Bus clock derived directly from an external crystal 8MHz with no multiplication + Core clock = 8MHz, BusClock = 8MHz +*/ + +/*---------------------------------------------------------------------------- + Define clock source values + *----------------------------------------------------------------------------*/ +#if (CLOCK_SETUP == 0) + #define CPU_XTAL_CLK_HZ 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */ + #define CPU_XTAL32k_CLK_HZ 32768u /* Value of the external 32k crystal or oscillator clock frequency in Hz */ + #define CPU_INT_SLOW_CLK_HZ 32768u /* Value of the slow internal oscillator clock frequency in Hz */ + #define CPU_INT_FAST_CLK_HZ 4000000u /* Value of the fast internal oscillator clock frequency in Hz */ + #define DEFAULT_SYSTEM_CLOCK 41943040u /* Default System clock value */ +#elif (CLOCK_SETUP == 1) + #define CPU_XTAL_CLK_HZ 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */ + #define CPU_XTAL32k_CLK_HZ 32768u /* Value of the external 32k crystal or oscillator clock frequency in Hz */ + #define CPU_INT_SLOW_CLK_HZ 32768u /* Value of the slow internal oscillator clock frequency in Hz */ + #define CPU_INT_FAST_CLK_HZ 4000000u /* Value of the fast internal oscillator clock frequency in Hz */ + #define DEFAULT_SYSTEM_CLOCK 48000000u /* Default System clock value */ +#elif (CLOCK_SETUP == 2) + #define CPU_XTAL_CLK_HZ 8000000u /* Value of the external crystal or oscillator clock frequency in Hz */ + #define CPU_XTAL32k_CLK_HZ 32768u /* Value of the external 32k crystal or oscillator clock frequency in Hz */ + #define CPU_INT_SLOW_CLK_HZ 32768u /* Value of the slow internal oscillator clock frequency in Hz */ + #define CPU_INT_FAST_CLK_HZ 4000000u /* Value of the fast internal oscillator clock frequency in Hz */ + #define DEFAULT_SYSTEM_CLOCK 8000000u /* Default System clock value */ +#elif (CLOCK_SETUP == 3) + /* for Infinity */ + #define CPU_XTAL_CLK_HZ 8000000u + #define CPU_XTAL32k_CLK_HZ 32768u + #define CPU_INT_SLOW_CLK_HZ 32768u + #define CPU_INT_FAST_CLK_HZ 4000000u + #define DEFAULT_SYSTEM_CLOCK 48000000u +#endif + + +/* ---------------------------------------------------------------------------- + -- Core clock + ---------------------------------------------------------------------------- */ + +uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK; + +/* ---------------------------------------------------------------------------- + -- SystemInit() + ---------------------------------------------------------------------------- */ + +void SystemInit (void) { +#if (DISABLE_WDOG) + /* Disable the WDOG module */ + /* WDOG_UNLOCK: WDOGUNLOCK=0xC520 */ + WDOG->UNLOCK = (uint16_t)0xC520u; /* Key 1 */ + /* WDOG_UNLOCK : WDOGUNLOCK=0xD928 */ + WDOG->UNLOCK = (uint16_t)0xD928u; /* Key 2 */ + /* WDOG_STCTRLH: ??=0,DISTESTWDOG=0,BYTESEL=0,TESTSEL=0,TESTWDOG=0,??=0,STNDBYEN=1,WAITEN=1,STOPEN=1,DBGEN=0,ALLOWUPDATE=1,WINEN=0,IRQRSTEN=0,CLKSRC=1,WDOGEN=0 */ + WDOG->STCTRLH = (uint16_t)0x01D2u; +#endif /* (DISABLE_WDOG) */ +#if (CLOCK_SETUP == 0) + /* SIM->CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=1,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ + SIM->CLKDIV1 = (uint32_t)0x00110000u; /* Update system prescalers */ + /* Switch to FEI Mode */ + /* MCG->C1: CLKS=0,FRDIV=0,IREFS=1,IRCLKEN=1,IREFSTEN=0 */ + MCG->C1 = (uint8_t)0x06u; + /* MCG->C2: ??=0,??=0,RANGE0=0,HGO=0,EREFS=0,LP=0,IRCS=0 */ + MCG->C2 = (uint8_t)0x00u; + /* MCG_C4: DMX32=0,DRST_DRS=1 */ + MCG->C4 = (uint8_t)((MCG->C4 & (uint8_t)~(uint8_t)0xC0u) | (uint8_t)0x20u); + /* MCG->C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV0=0 */ + MCG->C5 = (uint8_t)0x00u; + /* MCG->C6: LOLIE=0,PLLS=0,CME=0,VDIV0=0 */ + MCG->C6 = (uint8_t)0x00u; + while((MCG->S & MCG_S_IREFST_MASK) == 0u) { /* Check that the source of the FLL reference clock is the internal reference clock. */ + } + while((MCG->S & 0x0Cu) != 0x00u) { /* Wait until output of the FLL is selected */ + } +#elif (CLOCK_SETUP == 1) + /* SIM->CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=1,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ + SIM->CLKDIV1 = (uint32_t)0x00110000u; /* Update system prescalers */ + /* Switch to FBE Mode */ + /* OSC0->CR: ERCLKEN=0,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ + OSC0->CR = (uint8_t)0x00u; + /* MCG->C7: OSCSEL=0 */ + MCG->C7 = (uint8_t)0x00u; + /* MCG->C2: ??=0,??=0,RANGE0=2,HGO=0,EREFS=1,LP=0,IRCS=0 */ + MCG->C2 = (uint8_t)0x24u; + /* MCG->C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ + MCG->C1 = (uint8_t)0x9Au; + /* MCG->C4: DMX32=0,DRST_DRS=0 */ + MCG->C4 &= (uint8_t)~(uint8_t)0xE0u; + /* MCG->C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV0=3 */ + MCG->C5 = (uint8_t)0x03u; + /* MCG->C6: LOLIE=0,PLLS=0,CME=0,VDIV0=0 */ + MCG->C6 = (uint8_t)0x00u; + while((MCG->S & MCG_S_OSCINIT0_MASK) == 0u) { /* Check that the oscillator is running */ + } +#if 0 /* ARM: THIS CHECK IS REMOVED DUE TO BUG WITH SLOW IRC IN REV. 1.0 */ + while((MCG->S & MCG_S_IREFST_MASK) != 0u) { /* Check that the source of the FLL reference clock is the external reference clock. */ + } +#endif + while((MCG->S & 0x0Cu) != 0x08u) { /* Wait until external reference clock is selected as MCG output */ + } + /* Switch to PBE Mode */ + /* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV0=3 */ + MCG->C5 = (uint8_t)0x03u; + /* MCG->C6: LOLIE=0,PLLS=1,CME=0,VDIV0=0 */ + MCG->C6 = (uint8_t)0x40u; + while((MCG->S & MCG_S_PLLST_MASK) == 0u) { /* Wait until the source of the PLLS clock has switched to the PLL */ + } + while((MCG->S & MCG_S_LOCK0_MASK) == 0u) { /* Wait until locked */ + } + /* Switch to PEE Mode */ + /* MCG->C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ + MCG->C1 = (uint8_t)0x1Au; + while((MCG->S & 0x0Cu) != 0x0Cu) { /* Wait until output of the PLL is selected */ + } + while((MCG->S & MCG_S_LOCK0_MASK) == 0u) { /* Wait until locked */ + } +#elif (CLOCK_SETUP == 2) + /* SIM_CLKDIV1: OUTDIV1=0,OUTDIV2=0,OUTDIV3=1,OUTDIV4=1,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0,??=0 */ + SIM->CLKDIV1 = (uint32_t)0x00110000u; /* Update system prescalers */ + /* Switch to FBE Mode */ + /* OSC0->CR: ERCLKEN=0,??=0,EREFSTEN=0,??=0,SC2P=0,SC4P=0,SC8P=0,SC16P=0 */ + OSC0->CR = (uint8_t)0x00u; + /* MCG->C7: OSCSEL=0 */ + MCG->C7 = (uint8_t)0x00u; + /* MCG->C2: ??=0,??=0,RANGE0=2,HGO=0,EREFS=1,LP=0,IRCS=0 */ + MCG->C2 = (uint8_t)0x24u; + /* MCG->C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=1,IREFSTEN=0 */ + MCG->C1 = (uint8_t)0x9Au; + /* MCG->C4: DMX32=0,DRST_DRS=0 */ + MCG->C4 &= (uint8_t)~(uint8_t)0xE0u; + /* MCG->C5: ??=0,PLLCLKEN=0,PLLSTEN=0,PRDIV0=0 */ + MCG->C5 = (uint8_t)0x00u; + /* MCG->C6: LOLIE=0,PLLS=0,CME=0,VDIV0=0 */ + MCG->C6 = (uint8_t)0x00u; + while((MCG->S & MCG_S_OSCINIT0_MASK) == 0u) { /* Check that the oscillator is running */ + } +#if 0 /* ARM: THIS CHECK IS REMOVED DUE TO BUG WITH SLOW IRC IN REV. 1.0 */ + while((MCG->S & MCG_S_IREFST_MASK) != 0u) { /* Check that the source of the FLL reference clock is the external reference clock. */ + } +#endif + while((MCG->S & 0x0CU) != 0x08u) { /* Wait until external reference clock is selected as MCG output */ + } + /* Switch to BLPE Mode */ + /* MCG->C2: ??=0,??=0,RANGE0=2,HGO=0,EREFS=1,LP=0,IRCS=0 */ + MCG->C2 = (uint8_t)0x24u; + +#elif (CLOCK_SETUP == 3) + /* for Infinity FEI: 48MHz */ + + /* OUTDIV1(core/system): 48/1, OUTDIV2(bus): 48/1, OUTDIV4(flash): 48/2 */ + SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(1); + MCG->C1 = MCG_C1_IREFS_MASK | MCG_C1_IRCLKEN_MASK; + /* 32.768KHz x FLL(1464) = 48MHz */ + MCG->C4 = MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS(1); + /* USB clock source: MCGPLLCLK/MCGFLLCLK */ + //SIM->SOPT2 = SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_TRACECLKSEL_MASK; + + while((MCG->S & MCG_S_IREFST_MASK) == 0u) { } + while((MCG->S & 0x0Cu) != 0x00u) { } +#endif +} + +/* ---------------------------------------------------------------------------- + -- SystemCoreClockUpdate() + ---------------------------------------------------------------------------- */ + +void SystemCoreClockUpdate (void) { + uint32_t MCGOUTClock; /* Variable to store output clock frequency of the MCG module */ + uint8_t Divider; + + if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x0u) { + /* Output of FLL or PLL is selected */ + if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { + /* FLL is selected */ + if ((MCG->C1 & MCG_C1_IREFS_MASK) == 0x0u) { + /* External reference clock is selected */ + if ((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u) { + MCGOUTClock = CPU_XTAL_CLK_HZ; /* System oscillator drives MCG clock */ + } else { /* (!((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u)) */ + MCGOUTClock = CPU_XTAL32k_CLK_HZ; /* RTC 32 kHz oscillator drives MCG clock */ + } /* (!((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u)) */ + Divider = (uint8_t)(1u << ((MCG->C1 & MCG_C1_FRDIV_MASK) >> MCG_C1_FRDIV_SHIFT)); + MCGOUTClock = (MCGOUTClock / Divider); /* Calculate the divided FLL reference clock */ + if ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x0u) { + MCGOUTClock /= 32u; /* If high range is enabled, additional 32 divider is active */ + } /* ((MCG->C2 & MCG_C2_RANGE0_MASK) != 0x0u) */ + } else { /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x0u)) */ + MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* The slow internal reference clock is selected */ + } /* (!((MCG->C1 & MCG_C1_IREFS_MASK) == 0x0u)) */ + /* Select correct multiplier to calculate the MCG output clock */ + switch (MCG->C4 & (MCG_C4_DMX32_MASK | MCG_C4_DRST_DRS_MASK)) { + case 0x0u: + MCGOUTClock *= 640u; + break; + case 0x20u: + MCGOUTClock *= 1280u; + break; + case 0x40u: + MCGOUTClock *= 1920u; + break; + case 0x60u: + MCGOUTClock *= 2560u; + break; + case 0x80u: + MCGOUTClock *= 732u; + break; + case 0xA0u: + MCGOUTClock *= 1464u; + break; + case 0xC0u: + MCGOUTClock *= 2197u; + break; + case 0xE0u: + MCGOUTClock *= 2929u; + break; + default: + break; + } + } else { /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u)) */ + /* PLL is selected */ + Divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK)); + MCGOUTClock = (uint32_t)(CPU_XTAL_CLK_HZ / Divider); /* Calculate the PLL reference clock */ + Divider = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u); + MCGOUTClock *= Divider; /* Calculate the MCG output clock */ + } /* (!((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u)) */ + } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x40u) { + /* Internal reference clock is selected */ + if ((MCG->C2 & MCG_C2_IRCS_MASK) == 0x0u) { + MCGOUTClock = CPU_INT_SLOW_CLK_HZ; /* Slow internal reference clock selected */ + } else { /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x0u)) */ + MCGOUTClock = CPU_INT_FAST_CLK_HZ / (1 << ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT)); /* Fast internal reference clock selected */ + } /* (!((MCG->C2 & MCG_C2_IRCS_MASK) == 0x0u)) */ + } else if ((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80u) { + /* External reference clock is selected */ + if ((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u) { + MCGOUTClock = CPU_XTAL_CLK_HZ; /* System oscillator drives MCG clock */ + } else { /* (!((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u)) */ + MCGOUTClock = CPU_XTAL32k_CLK_HZ; /* RTC 32 kHz oscillator drives MCG clock */ + } /* (!((MCG->C7 & MCG_C7_OSCSEL_MASK) == 0x0u)) */ + } else { /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80u)) */ + /* Reserved value */ + return; + } /* (!((MCG->C1 & MCG_C1_CLKS_MASK) == 0x80u)) */ + SystemCoreClock = (MCGOUTClock / (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT))); +} |