diff options
Diffstat (limited to 'tmk_core/common/arm_atsam')
-rw-r--r-- | tmk_core/common/arm_atsam/bootloader.c | 51 | ||||
-rw-r--r-- | tmk_core/common/arm_atsam/eeprom.c | 98 | ||||
-rw-r--r-- | tmk_core/common/arm_atsam/printf.c | 66 | ||||
-rw-r--r-- | tmk_core/common/arm_atsam/printf.h | 11 | ||||
-rw-r--r-- | tmk_core/common/arm_atsam/suspend.c | 85 | ||||
-rw-r--r-- | tmk_core/common/arm_atsam/timer.c | 59 |
6 files changed, 370 insertions, 0 deletions
diff --git a/tmk_core/common/arm_atsam/bootloader.c b/tmk_core/common/arm_atsam/bootloader.c new file mode 100644 index 000000000..ba71bfeb0 --- /dev/null +++ b/tmk_core/common/arm_atsam/bootloader.c @@ -0,0 +1,51 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "bootloader.h" +#include "samd51j18a.h" +#include "md_bootloader.h" + +//Set watchdog timer to reset. Directs the bootloader to stay in programming mode. +void bootloader_jump(void) { +#ifdef KEYBOARD_massdrop_ctrl + //CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method. + uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; //The version to match (NULL terminated by compiler) + uint8_t *ver_check = ver_ram_method; //Pointer to version match string for traversal + uint8_t *ver_rom = (uint8_t *)0x21A0; //Pointer to address in ROM where this specific bootloader version would exist + + while (*ver_check && *ver_rom == *ver_check) { //While there are check version characters to match and bootloader's version matches check's version + ver_check++; //Move check version pointer to next character + ver_rom++; //Move ROM version pointer to next character + } + + if (!*ver_check) { //If check version pointer is NULL, all characters have matched + *MAGIC_ADDR = BOOTLOADER_MAGIC; //Set magic number into RAM + NVIC_SystemReset(); //Perform system reset + while (1) {} //Won't get here + } +#endif + + WDT->CTRLA.bit.ENABLE = 0; + while (WDT->SYNCBUSY.bit.ENABLE) {} + while (WDT->CTRLA.bit.ENABLE) {} + WDT->CONFIG.bit.WINDOW = 0; + WDT->CONFIG.bit.PER = 0; + WDT->EWCTRL.bit.EWOFFSET = 0; + WDT->CTRLA.bit.ENABLE = 1; + while (WDT->SYNCBUSY.bit.ENABLE) {} + while (!WDT->CTRLA.bit.ENABLE) {} + while (1) {} //Wait on timeout +} diff --git a/tmk_core/common/arm_atsam/eeprom.c b/tmk_core/common/arm_atsam/eeprom.c new file mode 100644 index 000000000..61cc039ef --- /dev/null +++ b/tmk_core/common/arm_atsam/eeprom.c @@ -0,0 +1,98 @@ +/* Copyright 2017 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "eeprom.h" + +#define EEPROM_SIZE 32 + +static uint8_t buffer[EEPROM_SIZE]; + +uint8_t eeprom_read_byte(const uint8_t *addr) { + uintptr_t offset = (uintptr_t)addr; + return buffer[offset]; +} + +void eeprom_write_byte(uint8_t *addr, uint8_t value) { + uintptr_t offset = (uintptr_t)addr; + buffer[offset] = value; +} + +uint16_t eeprom_read_word(const uint16_t *addr) { + const uint8_t *p = (const uint8_t *)addr; + return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8); +} + +uint32_t eeprom_read_dword(const uint32_t *addr) { + const uint8_t *p = (const uint8_t *)addr; + return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8) + | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24); +} + +void eeprom_read_block(void *buf, const void *addr, uint32_t len) { + const uint8_t *p = (const uint8_t *)addr; + uint8_t *dest = (uint8_t *)buf; + while (len--) { + *dest++ = eeprom_read_byte(p++); + } +} + +void eeprom_write_word(uint16_t *addr, uint16_t value) { + uint8_t *p = (uint8_t *)addr; + eeprom_write_byte(p++, value); + eeprom_write_byte(p, value >> 8); +} + +void eeprom_write_dword(uint32_t *addr, uint32_t value) { + uint8_t *p = (uint8_t *)addr; + eeprom_write_byte(p++, value); + eeprom_write_byte(p++, value >> 8); + eeprom_write_byte(p++, value >> 16); + eeprom_write_byte(p, value >> 24); +} + +void eeprom_write_block(const void *buf, void *addr, uint32_t len) { + uint8_t *p = (uint8_t *)addr; + const uint8_t *src = (const uint8_t *)buf; + while (len--) { + eeprom_write_byte(p++, *src++); + } +} + +void eeprom_update_byte(uint8_t *addr, uint8_t value) { + eeprom_write_byte(addr, value); +} + +void eeprom_update_word(uint16_t *addr, uint16_t value) { + uint8_t *p = (uint8_t *)addr; + eeprom_write_byte(p++, value); + eeprom_write_byte(p, value >> 8); +} + +void eeprom_update_dword(uint32_t *addr, uint32_t value) { + uint8_t *p = (uint8_t *)addr; + eeprom_write_byte(p++, value); + eeprom_write_byte(p++, value >> 8); + eeprom_write_byte(p++, value >> 16); + eeprom_write_byte(p, value >> 24); +} + +void eeprom_update_block(const void *buf, void *addr, uint32_t len) { + uint8_t *p = (uint8_t *)addr; + const uint8_t *src = (const uint8_t *)buf; + while (len--) { + eeprom_write_byte(p++, *src++); + } +} diff --git a/tmk_core/common/arm_atsam/printf.c b/tmk_core/common/arm_atsam/printf.c new file mode 100644 index 000000000..7f298d1fd --- /dev/null +++ b/tmk_core/common/arm_atsam/printf.c @@ -0,0 +1,66 @@ +/* +Copyright 2018 Massdrop Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef CONSOLE_ENABLE + +#include "samd51j18a.h" +#include "arm_atsam_protocol.h" +#include "printf.h" +#include <string.h> +#include <stdarg.h> + +void console_printf(char *fmt, ...) { + while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete + + static char console_printbuf[CONSOLE_PRINTBUF_SIZE]; //Print and send buffer + va_list va; + int result; + + va_start(va, fmt); + result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va); + va_end(va); + + uint32_t irqflags; + char *pconbuf = console_printbuf; //Pointer to start send from + int send_out = CONSOLE_EPSIZE; //Bytes to send per transfer + + while (result > 0) { //While not error and bytes remain + while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete + + irqflags = __get_PRIMASK(); + __disable_irq(); + __DMB(); + + if (result < CONSOLE_EPSIZE) { //If remaining bytes are less than console epsize + memset(udi_hid_con_report, 0, CONSOLE_EPSIZE); //Clear the buffer + send_out = result; //Send remaining size + } + + memcpy(udi_hid_con_report, pconbuf, send_out); //Copy data into the send buffer + + udi_hid_con_b_report_valid = 1; //Set report valid + udi_hid_con_send_report(); //Send report + + __DMB(); + __set_PRIMASK(irqflags); + + result -= send_out; //Decrement result by bytes sent + pconbuf += send_out; //Increment buffer point by bytes sent + } +} + +#endif //CONSOLE_ENABLE diff --git a/tmk_core/common/arm_atsam/printf.h b/tmk_core/common/arm_atsam/printf.h new file mode 100644 index 000000000..1f1c2280b --- /dev/null +++ b/tmk_core/common/arm_atsam/printf.h @@ -0,0 +1,11 @@ +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#define CONSOLE_PRINTBUF_SIZE 512 + +void console_printf(char *fmt, ...); + +#define __xprintf console_printf + +#endif //_PRINTF_H_ + diff --git a/tmk_core/common/arm_atsam/suspend.c b/tmk_core/common/arm_atsam/suspend.c new file mode 100644 index 000000000..e34965df6 --- /dev/null +++ b/tmk_core/common/arm_atsam/suspend.c @@ -0,0 +1,85 @@ +#include "matrix.h" +#include "i2c_master.h" +#include "led_matrix.h" +#include "suspend.h" + +/** \brief Suspend idle + * + * FIXME: needs doc + */ +void suspend_idle(uint8_t time) { + /* Note: Not used anywhere currently */ +} + +/** \brief Run user level Power down + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void suspend_power_down_user (void) { + +} + +/** \brief Run keyboard level Power down + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void suspend_power_down_kb(void) { + suspend_power_down_user(); +} + +/** \brief Suspend power down + * + * FIXME: needs doc + */ +void suspend_power_down(void) +{ + I2C3733_Control_Set(0); //Disable LED driver + + suspend_power_down_kb(); +} + +__attribute__ ((weak)) void matrix_power_up(void) {} +__attribute__ ((weak)) void matrix_power_down(void) {} +bool suspend_wakeup_condition(void) { + matrix_power_up(); + matrix_scan(); + matrix_power_down(); + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + if (matrix_get_row(r)) return true; + } + return false; +} + +/** \brief run user level code immediately after wakeup + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void suspend_wakeup_init_user(void) { + +} + +/** \brief run keyboard level code immediately after wakeup + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void suspend_wakeup_init_kb(void) { + suspend_wakeup_init_user(); +} + +/** \brief run immediately after wakeup + * + * FIXME: needs doc + */ +void suspend_wakeup_init(void) { + /* If LEDs are set to enabled, enable the hardware */ + if (led_enabled) { + I2C3733_Control_Set(1); + } + + suspend_wakeup_init_kb(); +} + diff --git a/tmk_core/common/arm_atsam/timer.c b/tmk_core/common/arm_atsam/timer.c new file mode 100644 index 000000000..bcfe5002c --- /dev/null +++ b/tmk_core/common/arm_atsam/timer.c @@ -0,0 +1,59 @@ +#include "samd51j18a.h" +#include "timer.h" +#include "tmk_core/protocol/arm_atsam/clks.h" + +void set_time(uint64_t tset) +{ + ms_clk = tset; +} + +void timer_init(void) +{ + ms_clk = 0; +} + +uint16_t timer_read(void) +{ + return (uint16_t)ms_clk; +} + +uint32_t timer_read32(void) +{ + return (uint32_t)ms_clk; +} + +uint64_t timer_read64(void) +{ + return ms_clk; +} + +uint16_t timer_elapsed(uint16_t tlast) +{ + return TIMER_DIFF_16(timer_read(), tlast); +} + +uint32_t timer_elapsed32(uint32_t tlast) +{ + return TIMER_DIFF_32(timer_read32(), tlast); +} + +uint32_t timer_elapsed64(uint32_t tlast) +{ + uint64_t tnow = timer_read64(); + return (tnow >= tlast ? tnow - tlast : UINT64_MAX - tlast + tnow); +} + +void timer_clear(void) +{ + ms_clk = 0; +} + +void wait_ms(uint64_t msec) +{ + CLK_delay_ms(msec); +} + +void wait_us(uint16_t usec) +{ + CLK_delay_us(usec); +} |