aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common/chibios
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common/chibios')
-rw-r--r--tmk_core/common/chibios/bootloader.c63
-rw-r--r--[-rwxr-xr-x]tmk_core/common/chibios/eeprom_stm32.c142
-rw-r--r--[-rwxr-xr-x]tmk_core/common/chibios/eeprom_stm32.h64
-rw-r--r--tmk_core/common/chibios/eeprom_teensy.c782
-rw-r--r--[-rwxr-xr-x]tmk_core/common/chibios/flash_stm32.c162
-rw-r--r--[-rwxr-xr-x]tmk_core/common/chibios/flash_stm32.h15
-rw-r--r--tmk_core/common/chibios/printf.c277
-rw-r--r--tmk_core/common/chibios/printf.h59
-rw-r--r--tmk_core/common/chibios/sleep_led.c128
-rw-r--r--tmk_core/common/chibios/suspend.c46
-rw-r--r--tmk_core/common/chibios/timer.c46
11 files changed, 827 insertions, 957 deletions
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c
index f9895237b..4cf5dae7e 100644
--- a/tmk_core/common/chibios/bootloader.c
+++ b/tmk_core/common/chibios/bootloader.c
@@ -7,63 +7,62 @@
7/* STM32 */ 7/* STM32 */
8 8
9/* This code should be checked whether it runs correctly on platforms */ 9/* This code should be checked whether it runs correctly on platforms */
10#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) 10# define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
11extern uint32_t __ram0_end__; 11extern uint32_t __ram0_end__;
12#define BOOTLOADER_MAGIC 0xDEADBEEF 12# define BOOTLOADER_MAGIC 0xDEADBEEF
13#define MAGIC_ADDR (unsigned long*)(SYMVAL(__ram0_end__) - 4) 13# define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
14
15 14
16/** \brief Jump to the bootloader 15/** \brief Jump to the bootloader
17 * 16 *
18 * FIXME: needs doc 17 * FIXME: needs doc
19 */ 18 */
20void bootloader_jump(void) { 19void bootloader_jump(void) {
21 *MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader 20 *MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
22 NVIC_SystemReset(); 21 NVIC_SystemReset();
23} 22}
24 23
25/** \brief Enter bootloader mode if requested 24/** \brief Enter bootloader mode if requested
26 * 25 *
27 * FIXME: needs doc 26 * FIXME: needs doc
28 */ 27 */
29void enter_bootloader_mode_if_requested(void) { 28void enter_bootloader_mode_if_requested(void) {
30 unsigned long* check = MAGIC_ADDR; 29 unsigned long *check = MAGIC_ADDR;
31 if(*check == BOOTLOADER_MAGIC) { 30 if (*check == BOOTLOADER_MAGIC) {
32 *check = 0; 31 *check = 0;
33 __set_CONTROL(0); 32 __set_CONTROL(0);
34 __set_MSP(*(__IO uint32_t*)STM32_BOOTLOADER_ADDRESS); 33 __set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
35 __enable_irq(); 34 __enable_irq();
36 35
37 typedef void (*BootJump_t)(void); 36 typedef void (*BootJump_t)(void);
38 BootJump_t boot_jump = *(BootJump_t*)(STM32_BOOTLOADER_ADDRESS + 4); 37 BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
39 boot_jump(); 38 boot_jump();
40 while(1); 39 while (1)
41 } 40 ;
42 } 41 }
42}
43 43
44#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */ 44#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
45/* Kinetis */ 45/* Kinetis */
46 46
47#if defined(KIIBOHD_BOOTLOADER) 47# if defined(KIIBOHD_BOOTLOADER)
48/* Kiibohd Bootloader (MCHCK and Infinity KB) */ 48/* Kiibohd Bootloader (MCHCK and Infinity KB) */
49#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000 49# define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
50const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; 50const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
51void bootloader_jump(void) { 51void bootloader_jump(void) {
52 __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic)); 52 __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
53 // request reset 53 // request reset
54 SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk; 54 SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
55} 55}
56 56
57#else /* defined(KIIBOHD_BOOTLOADER) */ 57# else /* defined(KIIBOHD_BOOTLOADER) */
58/* Default for Kinetis - expecting an ARM Teensy */ 58/* Default for Kinetis - expecting an ARM Teensy */
59#include "wait.h" 59# include "wait.h"
60void bootloader_jump(void) { 60void bootloader_jump(void) {
61 wait_ms(100); 61 wait_ms(100);
62 __BKPT(0); 62 __BKPT(0);
63} 63}
64#endif /* defined(KIIBOHD_BOOTLOADER) */ 64# endif /* defined(KIIBOHD_BOOTLOADER) */
65 65
66#else /* neither STM32 nor KINETIS */ 66#else /* neither STM32 nor KINETIS */
67__attribute__((weak)) 67__attribute__((weak)) void bootloader_jump(void) {}
68void bootloader_jump(void) {}
69#endif 68#endif
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c
index 4b1abc968..926b581c6 100755..100644
--- a/tmk_core/common/chibios/eeprom_stm32.c
+++ b/tmk_core/common/chibios/eeprom_stm32.c
@@ -24,7 +24,7 @@
24 * the functionality use the EEPROM_Init() function. Be sure that by reprogramming 24 * the functionality use the EEPROM_Init() function. Be sure that by reprogramming
25 * of the controller just affected pages will be deleted. In other case the non 25 * of the controller just affected pages will be deleted. In other case the non
26 * volatile data will be lost. 26 * volatile data will be lost.
27******************************************************************************/ 27 ******************************************************************************/
28 28
29/* Private macro -------------------------------------------------------------*/ 29/* Private macro -------------------------------------------------------------*/
30/* Private variables ---------------------------------------------------------*/ 30/* Private variables ---------------------------------------------------------*/
@@ -32,23 +32,22 @@
32 32
33uint8_t DataBuf[FEE_PAGE_SIZE]; 33uint8_t DataBuf[FEE_PAGE_SIZE];
34/***************************************************************************** 34/*****************************************************************************
35* Delete Flash Space used for user Data, deletes the whole space between 35 * Delete Flash Space used for user Data, deletes the whole space between
36* RW_PAGE_BASE_ADDRESS and the last uC Flash Page 36 * RW_PAGE_BASE_ADDRESS and the last uC Flash Page
37******************************************************************************/ 37 ******************************************************************************/
38uint16_t EEPROM_Init(void) { 38uint16_t EEPROM_Init(void) {
39 // unlock flash 39 // unlock flash
40 FLASH_Unlock(); 40 FLASH_Unlock();
41 41
42 // Clear Flags 42 // Clear Flags
43 //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR); 43 // FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
44 44
45 return FEE_DENSITY_BYTES; 45 return FEE_DENSITY_BYTES;
46} 46}
47/***************************************************************************** 47/*****************************************************************************
48* Erase the whole reserved Flash Space used for user Data 48 * Erase the whole reserved Flash Space used for user Data
49******************************************************************************/ 49 ******************************************************************************/
50void EEPROM_Erase (void) { 50void EEPROM_Erase(void) {
51
52 int page_num = 0; 51 int page_num = 0;
53 52
54 // delete all pages from specified start page to the last page 53 // delete all pages from specified start page to the last page
@@ -58,16 +57,15 @@ void EEPROM_Erase (void) {
58 } while (page_num < FEE_DENSITY_PAGES); 57 } while (page_num < FEE_DENSITY_PAGES);
59} 58}
60/***************************************************************************** 59/*****************************************************************************
61* Writes once data byte to flash on specified address. If a byte is already 60 * Writes once data byte to flash on specified address. If a byte is already
62* written, the whole page must be copied to a buffer, the byte changed and 61 * written, the whole page must be copied to a buffer, the byte changed and
63* the manipulated buffer written after PageErase. 62 * the manipulated buffer written after PageErase.
64*******************************************************************************/ 63 *******************************************************************************/
65uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) { 64uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
66
67 FLASH_Status FlashStatus = FLASH_COMPLETE; 65 FLASH_Status FlashStatus = FLASH_COMPLETE;
68 66
69 uint32_t page; 67 uint32_t page;
70 int i; 68 int i;
71 69
72 // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages) 70 // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages)
73 if (Address > FEE_DENSITY_BYTES) { 71 if (Address > FEE_DENSITY_BYTES) {
@@ -78,27 +76,25 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
78 page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE; 76 page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE;
79 77
80 // if current data is 0xFF, the byte is empty, just overwrite with the new one 78 // if current data is 0xFF, the byte is empty, just overwrite with the new one
81 if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) { 79 if ((*(__IO uint16_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
82
83 FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte)); 80 FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte));
84 } else { 81 } else {
85
86 // Copy Page to a buffer 82 // Copy Page to a buffer
87 memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page 83 memcpy(DataBuf, (uint8_t *)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page
88 84
89 // check if new data is differ to current data, return if not, proceed if yes 85 // check if new data is differ to current data, return if not, proceed if yes
90 if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) { 86 if (DataByte == *(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
91 return 0; 87 return 0;
92 } 88 }
93 89
94 // manipulate desired data byte in temp data array if new byte is differ to the current 90 // manipulate desired data byte in temp data array if new byte is differ to the current
95 DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte; 91 DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte;
96 92
97 //Erase Page 93 // Erase Page
98 FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)); 94 FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE));
99 95
100 // Write new data (whole page) to flash if data has been changed 96 // Write new data (whole page) to flash if data has been changed
101 for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) { 97 for (i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
102 if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) { 98 if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) {
103 FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)])); 99 FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]));
104 } 100 }
@@ -107,98 +103,86 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
107 return FlashStatus; 103 return FlashStatus;
108} 104}
109/***************************************************************************** 105/*****************************************************************************
110* Read once data byte from a specified address. 106 * Read once data byte from a specified address.
111*******************************************************************************/ 107 *******************************************************************************/
112uint8_t EEPROM_ReadDataByte (uint16_t Address) { 108uint8_t EEPROM_ReadDataByte(uint16_t Address) {
113
114 uint8_t DataByte = 0xFF; 109 uint8_t DataByte = 0xFF;
115 110
116 // Get Byte from specified address 111 // Get Byte from specified address
117 DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))); 112 DataByte = (*(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
118 113
119 return DataByte; 114 return DataByte;
120} 115}
121 116
122/***************************************************************************** 117/*****************************************************************************
123* Wrap library in AVR style functions. 118 * Wrap library in AVR style functions.
124*******************************************************************************/ 119 *******************************************************************************/
125uint8_t eeprom_read_byte (const uint8_t *Address) 120uint8_t eeprom_read_byte(const uint8_t *Address) {
126{ 121 const uint16_t p = (const uint32_t)Address;
127 const uint16_t p = (const uint32_t) Address;
128 return EEPROM_ReadDataByte(p); 122 return EEPROM_ReadDataByte(p);
129} 123}
130 124
131void eeprom_write_byte (uint8_t *Address, uint8_t Value) 125void eeprom_write_byte(uint8_t *Address, uint8_t Value) {
132{ 126 uint16_t p = (uint32_t)Address;
133 uint16_t p = (uint32_t) Address;
134 EEPROM_WriteDataByte(p, Value); 127 EEPROM_WriteDataByte(p, Value);
135} 128}
136 129
137void eeprom_update_byte (uint8_t *Address, uint8_t Value) 130void eeprom_update_byte(uint8_t *Address, uint8_t Value) {
138{ 131 uint16_t p = (uint32_t)Address;
139 uint16_t p = (uint32_t) Address;
140 EEPROM_WriteDataByte(p, Value); 132 EEPROM_WriteDataByte(p, Value);
141} 133}
142 134
143uint16_t eeprom_read_word (const uint16_t *Address) 135uint16_t eeprom_read_word(const uint16_t *Address) {
144{ 136 const uint16_t p = (const uint32_t)Address;
145 const uint16_t p = (const uint32_t) Address; 137 return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8);
146 return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8);
147} 138}
148 139
149void eeprom_write_word (uint16_t *Address, uint16_t Value) 140void eeprom_write_word(uint16_t *Address, uint16_t Value) {
150{ 141 uint16_t p = (uint32_t)Address;
151 uint16_t p = (uint32_t) Address; 142 EEPROM_WriteDataByte(p, (uint8_t)Value);
152 EEPROM_WriteDataByte(p, (uint8_t) Value); 143 EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
153 EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
154} 144}
155 145
156void eeprom_update_word (uint16_t *Address, uint16_t Value) 146void eeprom_update_word(uint16_t *Address, uint16_t Value) {
157{ 147 uint16_t p = (uint32_t)Address;
158 uint16_t p = (uint32_t) Address; 148 EEPROM_WriteDataByte(p, (uint8_t)Value);
159 EEPROM_WriteDataByte(p, (uint8_t) Value); 149 EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
160 EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
161} 150}
162 151
163uint32_t eeprom_read_dword (const uint32_t *Address) 152uint32_t eeprom_read_dword(const uint32_t *Address) {
164{ 153 const uint16_t p = (const uint32_t)Address;
165 const uint16_t p = (const uint32_t) Address; 154 return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24);
166 return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
167 | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
168} 155}
169 156
170void eeprom_write_dword (uint32_t *Address, uint32_t Value) 157void eeprom_write_dword(uint32_t *Address, uint32_t Value) {
171{ 158 uint16_t p = (const uint32_t)Address;
172 uint16_t p = (const uint32_t) Address; 159 EEPROM_WriteDataByte(p, (uint8_t)Value);
173 EEPROM_WriteDataByte(p, (uint8_t) Value); 160 EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
174 EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8)); 161 EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16));
175 EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16)); 162 EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
176 EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
177} 163}
178 164
179void eeprom_update_dword (uint32_t *Address, uint32_t Value) 165void eeprom_update_dword(uint32_t *Address, uint32_t Value) {
180{ 166 uint16_t p = (const uint32_t)Address;
181 uint16_t p = (const uint32_t) Address; 167 uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24);
182 uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8) 168 if (Value != existingValue) {
183 | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24); 169 EEPROM_WriteDataByte(p, (uint8_t)Value);
184 if(Value != existingValue){ 170 EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
185 EEPROM_WriteDataByte(p, (uint8_t) Value); 171 EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16));
186 EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8)); 172 EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
187 EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
188 EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
189 } 173 }
190} 174}
191 175
192void eeprom_read_block(void *buf, const void *addr, uint32_t len) { 176void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
193 const uint8_t *p = (const uint8_t *)addr; 177 const uint8_t *p = (const uint8_t *)addr;
194 uint8_t *dest = (uint8_t *)buf; 178 uint8_t * dest = (uint8_t *)buf;
195 while (len--) { 179 while (len--) {
196 *dest++ = eeprom_read_byte(p++); 180 *dest++ = eeprom_read_byte(p++);
197 } 181 }
198} 182}
199 183
200void eeprom_write_block(const void *buf, void *addr, uint32_t len) { 184void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
201 uint8_t *p = (uint8_t *)addr; 185 uint8_t * p = (uint8_t *)addr;
202 const uint8_t *src = (const uint8_t *)buf; 186 const uint8_t *src = (const uint8_t *)buf;
203 while (len--) { 187 while (len--) {
204 eeprom_write_byte(p++, *src++); 188 eeprom_write_byte(p++, *src++);
@@ -206,7 +190,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
206} 190}
207 191
208void eeprom_update_block(const void *buf, void *addr, uint32_t len) { 192void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
209 uint8_t *p = (uint8_t *)addr; 193 uint8_t * p = (uint8_t *)addr;
210 const uint8_t *src = (const uint8_t *)buf; 194 const uint8_t *src = (const uint8_t *)buf;
211 while (len--) { 195 while (len--) {
212 eeprom_write_byte(p++, *src++); 196 eeprom_write_byte(p++, *src++);
diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h
index 083eb16ee..e68914595 100755..100644
--- a/tmk_core/common/chibios/eeprom_stm32.h
+++ b/tmk_core/common/chibios/eeprom_stm32.h
@@ -31,53 +31,53 @@
31// HACK ALERT. This definition may not match your processor 31// HACK ALERT. This definition may not match your processor
32// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc 32// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
33#if defined(EEPROM_EMU_STM32F303xC) 33#if defined(EEPROM_EMU_STM32F303xC)
34 #define MCU_STM32F303CC 34# define MCU_STM32F303CC
35#elif defined(EEPROM_EMU_STM32F103xB) 35#elif defined(EEPROM_EMU_STM32F103xB)
36 #define MCU_STM32F103RB 36# define MCU_STM32F103RB
37#elif defined(EEPROM_EMU_STM32F072xB) 37#elif defined(EEPROM_EMU_STM32F072xB)
38 #define MCU_STM32F072CB 38# define MCU_STM32F072CB
39#else 39#else
40 #error "not implemented." 40# error "not implemented."
41#endif 41#endif
42 42
43#ifndef EEPROM_PAGE_SIZE 43#ifndef EEPROM_PAGE_SIZE
44 #if defined (MCU_STM32F103RB) 44# if defined(MCU_STM32F103RB)
45 #define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte 45# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte
46 #define FEE_DENSITY_PAGES 2 // How many pages are used 46# define FEE_DENSITY_PAGES 2 // How many pages are used
47 #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) || defined(MCU_STM32F072CB) 47# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB)
48 #define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte 48# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte
49 #define FEE_DENSITY_PAGES 4 // How many pages are used 49# define FEE_DENSITY_PAGES 4 // How many pages are used
50 #else 50# else
51 #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." 51# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
52 #endif 52# endif
53#endif 53#endif
54 54
55#ifndef EEPROM_START_ADDRESS 55#ifndef EEPROM_START_ADDRESS
56 #if defined (MCU_STM32F103RB) || defined(MCU_STM32F072CB) 56# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB)
57 #define FEE_MCU_FLASH_SIZE 128 // Size in Kb 57# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
58 #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) 58# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE)
59 #define FEE_MCU_FLASH_SIZE 512 // Size in Kb 59# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
60 #elif defined (MCU_STM32F103RD) 60# elif defined(MCU_STM32F103RD)
61 #define FEE_MCU_FLASH_SIZE 384 // Size in Kb 61# define FEE_MCU_FLASH_SIZE 384 // Size in Kb
62 #elif defined (MCU_STM32F303CC) 62# elif defined(MCU_STM32F303CC)
63 #define FEE_MCU_FLASH_SIZE 256 // Size in Kb 63# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
64 #else 64# else
65 #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." 65# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
66 #endif 66# endif
67#endif 67#endif
68 68
69// DONT CHANGE 69// DONT CHANGE
70// Choose location for the first EEPROM Page address on the top of flash 70// Choose location for the first EEPROM Page address on the top of flash
71#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) 71#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
72#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1) 72#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1)
73#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) 73#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
74#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) 74#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
75#define FEE_ADDR_OFFSET(Address)(Address * 2) // 1Byte per Word will be saved to preserve Flash 75#define FEE_ADDR_OFFSET(Address) (Address * 2) // 1Byte per Word will be saved to preserve Flash
76 76
77// Use this function to initialize the functionality 77// Use this function to initialize the functionality
78uint16_t EEPROM_Init(void); 78uint16_t EEPROM_Init(void);
79void EEPROM_Erase (void); 79void EEPROM_Erase(void);
80uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte); 80uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
81uint8_t EEPROM_ReadDataByte (uint16_t Address); 81uint8_t EEPROM_ReadDataByte(uint16_t Address);
82 82
83#endif /* __EEPROM_H */ 83#endif /* __EEPROM_H */
diff --git a/tmk_core/common/chibios/eeprom_teensy.c b/tmk_core/common/chibios/eeprom_teensy.c
index 9061b790c..a4093fb3b 100644
--- a/tmk_core/common/chibios/eeprom_teensy.c
+++ b/tmk_core/common/chibios/eeprom_teensy.c
@@ -21,10 +21,10 @@
21 * permit persons to whom the Software is furnished to do so, subject to 21 * permit persons to whom the Software is furnished to do so, subject to
22 * the following conditions: 22 * the following conditions:
23 * 23 *
24 * 1. The above copyright notice and this permission notice shall be 24 * 1. The above copyright notice and this permission notice shall be
25 * included in all copies or substantial portions of the Software. 25 * included in all copies or substantial portions of the Software.
26 * 26 *
27 * 2. If the Software is incorporated into a build system that allows 27 * 2. If the Software is incorporated into a build system that allows
28 * selection among a list of target devices, then similar target 28 * selection among a list of target devices, then similar target
29 * devices manufactured by PJRC.COM must be included in the list of 29 * devices manufactured by PJRC.COM must be included in the list of
30 * target devices and selectable in the same manner. 30 * target devices and selectable in the same manner.
@@ -39,7 +39,6 @@
39 * SOFTWARE. 39 * SOFTWARE.
40 */ 40 */
41 41
42
43#if defined(K20x) /* chip selection */ 42#if defined(K20x) /* chip selection */
44/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */ 43/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
45 44
@@ -51,7 +50,7 @@
51// (aligned to 2 or 4 byte boundaries) has twice the endurance 50// (aligned to 2 or 4 byte boundaries) has twice the endurance
52// compared to writing 8 bit bytes. 51// compared to writing 8 bit bytes.
53// 52//
54#define EEPROM_SIZE 32 53# define EEPROM_SIZE 32
55 54
56// Writing unaligned 16 or 32 bit data is handled automatically when 55// Writing unaligned 16 or 32 bit data is handled automatically when
57// this is defined, but at a cost of extra code size. Without this, 56// this is defined, but at a cost of extra code size. Without this,
@@ -59,286 +58,271 @@
59// absolutely sure all 16 and 32 bit writes will be aligned, you can 58// absolutely sure all 16 and 32 bit writes will be aligned, you can
60// remove the extra unnecessary code. 59// remove the extra unnecessary code.
61// 60//
62#define HANDLE_UNALIGNED_WRITES 61# define HANDLE_UNALIGNED_WRITES
63 62
64// Minimum EEPROM Endurance 63// Minimum EEPROM Endurance
65// ------------------------ 64// ------------------------
66#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word 65# if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
67 #define EEESIZE 0x33 66# define EEESIZE 0x33
68#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word 67# elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
69 #define EEESIZE 0x34 68# define EEESIZE 0x34
70#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word 69# elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
71 #define EEESIZE 0x35 70# define EEESIZE 0x35
72#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word 71# elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
73 #define EEESIZE 0x36 72# define EEESIZE 0x36
74#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word 73# elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
75 #define EEESIZE 0x37 74# define EEESIZE 0x37
76#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word 75# elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
77 #define EEESIZE 0x38 76# define EEESIZE 0x38
78#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word 77# elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
79 #define EEESIZE 0x39 78# define EEESIZE 0x39
80#endif 79# endif
81 80
82/** \brief eeprom initialization 81/** \brief eeprom initialization
83 * 82 *
84 * FIXME: needs doc 83 * FIXME: needs doc
85 */ 84 */
86void eeprom_initialize(void) 85void eeprom_initialize(void) {
87{ 86 uint32_t count = 0;
88 uint32_t count=0; 87 uint16_t do_flash_cmd[] = {0xf06f, 0x037f, 0x7003, 0x7803, 0xf013, 0x0f80, 0xd0fb, 0x4770};
89 uint16_t do_flash_cmd[] = { 88 uint8_t status;
90 0xf06f, 0x037f, 0x7003, 0x7803, 89
91 0xf013, 0x0f80, 0xd0fb, 0x4770}; 90 if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
92 uint8_t status; 91 // FlexRAM is configured as traditional RAM
93 92 // We need to reconfigure for EEPROM usage
94 if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) { 93 FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
95 // FlexRAM is configured as traditional RAM 94 FTFL->FCCOB4 = EEESIZE; // EEPROM Size
96 // We need to reconfigure for EEPROM usage 95 FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
97 FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command 96 __disable_irq();
98 FTFL->FCCOB4 = EEESIZE; // EEPROM Size 97 // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
99 FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup 98 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
100 __disable_irq(); 99 __enable_irq();
101 // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple... 100 status = FTFL->FSTAT;
102 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT)); 101 if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) {
103 __enable_irq(); 102 FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL));
104 status = FTFL->FSTAT; 103 return; // error
105 if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) { 104 }
106 FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)); 105 }
107 return; // error 106 // wait for eeprom to become ready (is this really necessary?)
108 } 107 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
109 } 108 if (++count > 20000) break;
110 // wait for eeprom to become ready (is this really necessary?) 109 }
111 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { 110}
112 if (++count > 20000) break; 111
113 } 112# define FlexRAM ((uint8_t *)0x14000000)
114}
115
116#define FlexRAM ((uint8_t *)0x14000000)
117 113
118/** \brief eeprom read byte 114/** \brief eeprom read byte
119 * 115 *
120 * FIXME: needs doc 116 * FIXME: needs doc
121 */ 117 */
122uint8_t eeprom_read_byte(const uint8_t *addr) 118uint8_t eeprom_read_byte(const uint8_t *addr) {
123{ 119 uint32_t offset = (uint32_t)addr;
124 uint32_t offset = (uint32_t)addr; 120 if (offset >= EEPROM_SIZE) return 0;
125 if (offset >= EEPROM_SIZE) return 0; 121 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
126 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 122 return FlexRAM[offset];
127 return FlexRAM[offset];
128} 123}
129 124
130/** \brief eeprom read word 125/** \brief eeprom read word
131 * 126 *
132 * FIXME: needs doc 127 * FIXME: needs doc
133 */ 128 */
134uint16_t eeprom_read_word(const uint16_t *addr) 129uint16_t eeprom_read_word(const uint16_t *addr) {
135{ 130 uint32_t offset = (uint32_t)addr;
136 uint32_t offset = (uint32_t)addr; 131 if (offset >= EEPROM_SIZE - 1) return 0;
137 if (offset >= EEPROM_SIZE-1) return 0; 132 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
138 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 133 return *(uint16_t *)(&FlexRAM[offset]);
139 return *(uint16_t *)(&FlexRAM[offset]);
140} 134}
141 135
142/** \brief eeprom read dword 136/** \brief eeprom read dword
143 * 137 *
144 * FIXME: needs doc 138 * FIXME: needs doc
145 */ 139 */
146uint32_t eeprom_read_dword(const uint32_t *addr) 140uint32_t eeprom_read_dword(const uint32_t *addr) {
147{ 141 uint32_t offset = (uint32_t)addr;
148 uint32_t offset = (uint32_t)addr; 142 if (offset >= EEPROM_SIZE - 3) return 0;
149 if (offset >= EEPROM_SIZE-3) return 0; 143 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
150 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 144 return *(uint32_t *)(&FlexRAM[offset]);
151 return *(uint32_t *)(&FlexRAM[offset]);
152} 145}
153 146
154/** \brief eeprom read block 147/** \brief eeprom read block
155 * 148 *
156 * FIXME: needs doc 149 * FIXME: needs doc
157 */ 150 */
158void eeprom_read_block(void *buf, const void *addr, uint32_t len) 151void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
159{ 152 uint32_t offset = (uint32_t)addr;
160 uint32_t offset = (uint32_t)addr; 153 uint8_t *dest = (uint8_t *)buf;
161 uint8_t *dest = (uint8_t *)buf; 154 uint32_t end = offset + len;
162 uint32_t end = offset + len; 155
163 156 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
164 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 157 if (end > EEPROM_SIZE) end = EEPROM_SIZE;
165 if (end > EEPROM_SIZE) end = EEPROM_SIZE; 158 while (offset < end) {
166 while (offset < end) { 159 *dest++ = FlexRAM[offset++];
167 *dest++ = FlexRAM[offset++]; 160 }
168 }
169} 161}
170 162
171/** \brief eeprom is ready 163/** \brief eeprom is ready
172 * 164 *
173 * FIXME: needs doc 165 * FIXME: needs doc
174 */ 166 */
175int eeprom_is_ready(void) 167int eeprom_is_ready(void) { return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; }
176{
177 return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
178}
179 168
180/** \brief flexram wait 169/** \brief flexram wait
181 * 170 *
182 * FIXME: needs doc 171 * FIXME: needs doc
183 */ 172 */
184static void flexram_wait(void) 173static void flexram_wait(void) {
185{ 174 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
186 while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) { 175 // TODO: timeout
187 // TODO: timeout 176 }
188 }
189} 177}
190 178
191/** \brief eeprom_write_byte 179/** \brief eeprom_write_byte
192 * 180 *
193 * FIXME: needs doc 181 * FIXME: needs doc
194 */ 182 */
195void eeprom_write_byte(uint8_t *addr, uint8_t value) 183void eeprom_write_byte(uint8_t *addr, uint8_t value) {
196{ 184 uint32_t offset = (uint32_t)addr;
197 uint32_t offset = (uint32_t)addr;
198 185
199 if (offset >= EEPROM_SIZE) return; 186 if (offset >= EEPROM_SIZE) return;
200 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 187 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
201 if (FlexRAM[offset] != value) { 188 if (FlexRAM[offset] != value) {
202 FlexRAM[offset] = value; 189 FlexRAM[offset] = value;
203 flexram_wait(); 190 flexram_wait();
204 } 191 }
205} 192}
206 193
207/** \brief eeprom write word 194/** \brief eeprom write word
208 * 195 *
209 * FIXME: needs doc 196 * FIXME: needs doc
210 */ 197 */
211void eeprom_write_word(uint16_t *addr, uint16_t value) 198void eeprom_write_word(uint16_t *addr, uint16_t value) {
212{ 199 uint32_t offset = (uint32_t)addr;
213 uint32_t offset = (uint32_t)addr; 200
214 201 if (offset >= EEPROM_SIZE - 1) return;
215 if (offset >= EEPROM_SIZE-1) return; 202 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
216 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 203# ifdef HANDLE_UNALIGNED_WRITES
217#ifdef HANDLE_UNALIGNED_WRITES 204 if ((offset & 1) == 0) {
218 if ((offset & 1) == 0) { 205# endif
219#endif 206 if (*(uint16_t *)(&FlexRAM[offset]) != value) {
220 if (*(uint16_t *)(&FlexRAM[offset]) != value) { 207 *(uint16_t *)(&FlexRAM[offset]) = value;
221 *(uint16_t *)(&FlexRAM[offset]) = value; 208 flexram_wait();
222 flexram_wait(); 209 }
223 } 210# ifdef HANDLE_UNALIGNED_WRITES
224#ifdef HANDLE_UNALIGNED_WRITES 211 } else {
225 } else { 212 if (FlexRAM[offset] != value) {
226 if (FlexRAM[offset] != value) { 213 FlexRAM[offset] = value;
227 FlexRAM[offset] = value; 214 flexram_wait();
228 flexram_wait(); 215 }
229 } 216 if (FlexRAM[offset + 1] != (value >> 8)) {
230 if (FlexRAM[offset + 1] != (value >> 8)) { 217 FlexRAM[offset + 1] = value >> 8;
231 FlexRAM[offset + 1] = value >> 8; 218 flexram_wait();
232 flexram_wait(); 219 }
233 } 220 }
234 } 221# endif
235#endif
236} 222}
237 223
238/** \brief eeprom write dword 224/** \brief eeprom write dword
239 * 225 *
240 * FIXME: needs doc 226 * FIXME: needs doc
241 */ 227 */
242void eeprom_write_dword(uint32_t *addr, uint32_t value) 228void eeprom_write_dword(uint32_t *addr, uint32_t value) {
243{ 229 uint32_t offset = (uint32_t)addr;
244 uint32_t offset = (uint32_t)addr; 230
245 231 if (offset >= EEPROM_SIZE - 3) return;
246 if (offset >= EEPROM_SIZE-3) return; 232 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
247 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 233# ifdef HANDLE_UNALIGNED_WRITES
248#ifdef HANDLE_UNALIGNED_WRITES 234 switch (offset & 3) {
249 switch (offset & 3) { 235 case 0:
250 case 0: 236# endif
251#endif 237 if (*(uint32_t *)(&FlexRAM[offset]) != value) {
252 if (*(uint32_t *)(&FlexRAM[offset]) != value) { 238 *(uint32_t *)(&FlexRAM[offset]) = value;
253 *(uint32_t *)(&FlexRAM[offset]) = value; 239 flexram_wait();
254 flexram_wait(); 240 }
255 } 241 return;
256 return; 242# ifdef HANDLE_UNALIGNED_WRITES
257#ifdef HANDLE_UNALIGNED_WRITES 243 case 2:
258 case 2: 244 if (*(uint16_t *)(&FlexRAM[offset]) != value) {
259 if (*(uint16_t *)(&FlexRAM[offset]) != value) { 245 *(uint16_t *)(&FlexRAM[offset]) = value;
260 *(uint16_t *)(&FlexRAM[offset]) = value; 246 flexram_wait();
261 flexram_wait(); 247 }
262 } 248 if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
263 if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) { 249 *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
264 *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16; 250 flexram_wait();
265 flexram_wait(); 251 }
266 } 252 return;
267 return; 253 default:
268 default: 254 if (FlexRAM[offset] != value) {
269 if (FlexRAM[offset] != value) { 255 FlexRAM[offset] = value;
270 FlexRAM[offset] = value; 256 flexram_wait();
271 flexram_wait(); 257 }
272 } 258 if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
273 if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) { 259 *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
274 *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8; 260 flexram_wait();
275 flexram_wait(); 261 }
276 } 262 if (FlexRAM[offset + 3] != (value >> 24)) {
277 if (FlexRAM[offset + 3] != (value >> 24)) { 263 FlexRAM[offset + 3] = value >> 24;
278 FlexRAM[offset + 3] = value >> 24; 264 flexram_wait();
279 flexram_wait(); 265 }
280 } 266 }
281 } 267# endif
282#endif
283} 268}
284 269
285/** \brief eeprom write block 270/** \brief eeprom write block
286 * 271 *
287 * FIXME: needs doc 272 * FIXME: needs doc
288 */ 273 */
289void eeprom_write_block(const void *buf, void *addr, uint32_t len) 274void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
290{ 275 uint32_t offset = (uint32_t)addr;
291 uint32_t offset = (uint32_t)addr; 276 const uint8_t *src = (const uint8_t *)buf;
292 const uint8_t *src = (const uint8_t *)buf; 277
293 278 if (offset >= EEPROM_SIZE) return;
294 if (offset >= EEPROM_SIZE) return; 279 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
295 if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize(); 280 if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
296 if (len >= EEPROM_SIZE) len = EEPROM_SIZE; 281 if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
297 if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset; 282 while (len > 0) {
298 while (len > 0) { 283 uint32_t lsb = offset & 3;
299 uint32_t lsb = offset & 3; 284 if (lsb == 0 && len >= 4) {
300 if (lsb == 0 && len >= 4) { 285 // write aligned 32 bits
301 // write aligned 32 bits 286 uint32_t val32;
302 uint32_t val32; 287 val32 = *src++;
303 val32 = *src++; 288 val32 |= (*src++ << 8);
304 val32 |= (*src++ << 8); 289 val32 |= (*src++ << 16);
305 val32 |= (*src++ << 16); 290 val32 |= (*src++ << 24);
306 val32 |= (*src++ << 24); 291 if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
307 if (*(uint32_t *)(&FlexRAM[offset]) != val32) { 292 *(uint32_t *)(&FlexRAM[offset]) = val32;
308 *(uint32_t *)(&FlexRAM[offset]) = val32; 293 flexram_wait();
309 flexram_wait(); 294 }
310 } 295 offset += 4;
311 offset += 4; 296 len -= 4;
312 len -= 4; 297 } else if ((lsb == 0 || lsb == 2) && len >= 2) {
313 } else if ((lsb == 0 || lsb == 2) && len >= 2) { 298 // write aligned 16 bits
314 // write aligned 16 bits 299 uint16_t val16;
315 uint16_t val16; 300 val16 = *src++;
316 val16 = *src++; 301 val16 |= (*src++ << 8);
317 val16 |= (*src++ << 8); 302 if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
318 if (*(uint16_t *)(&FlexRAM[offset]) != val16) { 303 *(uint16_t *)(&FlexRAM[offset]) = val16;
319 *(uint16_t *)(&FlexRAM[offset]) = val16; 304 flexram_wait();
320 flexram_wait(); 305 }
321 } 306 offset += 2;
322 offset += 2; 307 len -= 2;
323 len -= 2; 308 } else {
324 } else { 309 // write 8 bits
325 // write 8 bits 310 uint8_t val8 = *src++;
326 uint8_t val8 = *src++; 311 if (FlexRAM[offset] != val8) {
327 if (FlexRAM[offset] != val8) { 312 FlexRAM[offset] = val8;
328 FlexRAM[offset] = val8; 313 flexram_wait();
329 flexram_wait(); 314 }
330 } 315 offset++;
331 offset++; 316 len--;
332 len--; 317 }
333 } 318 }
334 }
335} 319}
336 320
337/* 321/*
338void do_flash_cmd(volatile uint8_t *fstat) 322void do_flash_cmd(volatile uint8_t *fstat)
339{ 323{
340 *fstat = 0x80; 324 *fstat = 0x80;
341 while ((*fstat & 0x80) == 0) ; // wait 325 while ((*fstat & 0x80) == 0) ; // wait
342} 326}
34300000000 <do_flash_cmd>: 32700000000 <do_flash_cmd>:
344 0: f06f 037f mvn.w r3, #127 ; 0x7f 328 0: f06f 037f mvn.w r3, #127 ; 0x7f
@@ -352,128 +336,124 @@ void do_flash_cmd(volatile uint8_t *fstat)
352#elif defined(KL2x) /* chip selection */ 336#elif defined(KL2x) /* chip selection */
353/* Teensy LC (emulated) */ 337/* Teensy LC (emulated) */
354 338
355#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) 339# define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
356 340
357extern uint32_t __eeprom_workarea_start__; 341extern uint32_t __eeprom_workarea_start__;
358extern uint32_t __eeprom_workarea_end__; 342extern uint32_t __eeprom_workarea_end__;
359 343
360#define EEPROM_SIZE 128 344# define EEPROM_SIZE 128
361 345
362static uint32_t flashend = 0; 346static uint32_t flashend = 0;
363 347
364void eeprom_initialize(void) 348void eeprom_initialize(void) {
365{ 349 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
366 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
367 350
368 do { 351 do {
369 if (*p++ == 0xFFFF) { 352 if (*p++ == 0xFFFF) {
370 flashend = (uint32_t)(p - 2); 353 flashend = (uint32_t)(p - 2);
371 return; 354 return;
372 } 355 }
373 } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__)); 356 } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
374 flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1); 357 flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
375} 358}
376 359
377uint8_t eeprom_read_byte(const uint8_t *addr) 360uint8_t eeprom_read_byte(const uint8_t *addr) {
378{ 361 uint32_t offset = (uint32_t)addr;
379 uint32_t offset = (uint32_t)addr; 362 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
380 const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); 363 const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
381 const uint16_t *end = (const uint16_t *)((uint32_t)flashend); 364 uint16_t val;
382 uint16_t val; 365 uint8_t data = 0xFF;
383 uint8_t data=0xFF; 366
384 367 if (!end) {
385 if (!end) { 368 eeprom_initialize();
386 eeprom_initialize(); 369 end = (const uint16_t *)((uint32_t)flashend);
387 end = (const uint16_t *)((uint32_t)flashend); 370 }
388 } 371 if (offset < EEPROM_SIZE) {
389 if (offset < EEPROM_SIZE) { 372 while (p <= end) {
390 while (p <= end) { 373 val = *p++;
391 val = *p++; 374 if ((val & 255) == offset) data = val >> 8;
392 if ((val & 255) == offset) data = val >> 8; 375 }
393 } 376 }
394 } 377 return data;
395 return data; 378}
396} 379
397 380static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data) {
398static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data) 381 // with great power comes great responsibility....
399{ 382 uint32_t stat;
400 // with great power comes great responsibility.... 383 *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
401 uint32_t stat; 384 *(uint32_t *)&(FTFA->FCCOB7) = data;
402 *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC); 385 __disable_irq();
403 *(uint32_t *)&(FTFA->FCCOB7) = data; 386 (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
404 __disable_irq(); 387 __enable_irq();
405 (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT)); 388 stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL);
406 __enable_irq(); 389 if (stat) {
407 stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL); 390 FTFA->FSTAT = stat;
408 if (stat) { 391 }
409 FTFA->FSTAT = stat; 392 MCM->PLACR |= MCM_PLACR_CFCC;
410 } 393}
411 MCM->PLACR |= MCM_PLACR_CFCC; 394
412} 395void eeprom_write_byte(uint8_t *addr, uint8_t data) {
413 396 uint32_t offset = (uint32_t)addr;
414void eeprom_write_byte(uint8_t *addr, uint8_t data) 397 const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
415{ 398 uint32_t i, val, flashaddr;
416 uint32_t offset = (uint32_t)addr; 399 uint16_t do_flash_cmd[] = {0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
417 const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend); 400 uint8_t buf[EEPROM_SIZE];
418 uint32_t i, val, flashaddr; 401
419 uint16_t do_flash_cmd[] = { 402 if (offset >= EEPROM_SIZE) return;
420 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770}; 403 if (!end) {
421 uint8_t buf[EEPROM_SIZE]; 404 eeprom_initialize();
422 405 end = (const uint16_t *)((uint32_t)flashend);
423 if (offset >= EEPROM_SIZE) return; 406 }
424 if (!end) { 407 if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
425 eeprom_initialize(); 408 val = (data << 8) | offset;
426 end = (const uint16_t *)((uint32_t)flashend); 409 flashaddr = (uint32_t)end;
427 } 410 flashend = flashaddr;
428 if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) { 411 if ((flashaddr & 2) == 0) {
429 val = (data << 8) | offset; 412 val |= 0xFFFF0000;
430 flashaddr = (uint32_t)end; 413 } else {
431 flashend = flashaddr; 414 val <<= 16;
432 if ((flashaddr & 2) == 0) { 415 val |= 0x0000FFFF;
433 val |= 0xFFFF0000; 416 }
434 } else { 417 flash_write(do_flash_cmd, flashaddr, val);
435 val <<= 16; 418 } else {
436 val |= 0x0000FFFF; 419 for (i = 0; i < EEPROM_SIZE; i++) {
437 } 420 buf[i] = 0xFF;
438 flash_write(do_flash_cmd, flashaddr, val); 421 }
439 } else { 422 val = 0;
440 for (i=0; i < EEPROM_SIZE; i++) { 423 for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
441 buf[i] = 0xFF; 424 val = *p;
442 } 425 if ((val & 255) < EEPROM_SIZE) {
443 val = 0; 426 buf[val & 255] = val >> 8;
444 for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) { 427 }
445 val = *p; 428 }
446 if ((val & 255) < EEPROM_SIZE) { 429 buf[offset] = data;
447 buf[val & 255] = val >> 8; 430 for (flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
448 } 431 *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
449 } 432 __disable_irq();
450 buf[offset] = data; 433 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
451 for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) { 434 __enable_irq();
452 *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr; 435 val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL);
453 __disable_irq(); 436 ;
454 (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT)); 437 if (val) FTFA->FSTAT = val;
455 __enable_irq(); 438 MCM->PLACR |= MCM_PLACR_CFCC;
456 val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);; 439 }
457 if (val) FTFA->FSTAT = val; 440 flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
458 MCM->PLACR |= MCM_PLACR_CFCC; 441 for (i = 0; i < EEPROM_SIZE; i++) {
459 } 442 if (buf[i] == 0xFF) continue;
460 flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); 443 if ((flashaddr & 2) == 0) {
461 for (i=0; i < EEPROM_SIZE; i++) { 444 val = (buf[i] << 8) | i;
462 if (buf[i] == 0xFF) continue; 445 } else {
463 if ((flashaddr & 2) == 0) { 446 val = val | (buf[i] << 24) | (i << 16);
464 val = (buf[i] << 8) | i; 447 flash_write(do_flash_cmd, flashaddr, val);
465 } else { 448 }
466 val = val | (buf[i] << 24) | (i << 16); 449 flashaddr += 2;
467 flash_write(do_flash_cmd, flashaddr, val); 450 }
468 } 451 flashend = flashaddr;
469 flashaddr += 2; 452 if ((flashaddr & 2)) {
470 } 453 val |= 0xFFFF0000;
471 flashend = flashaddr; 454 flash_write(do_flash_cmd, flashaddr, val);
472 if ((flashaddr & 2)) { 455 }
473 val |= 0xFFFF0000; 456 }
474 flash_write(do_flash_cmd, flashaddr, val);
475 }
476 }
477} 457}
478 458
479/* 459/*
@@ -492,141 +472,127 @@ void do_flash_cmd(volatile uint8_t *fstat)
492 c: 4770 bx lr 472 c: 4770 bx lr
493*/ 473*/
494 474
495 475uint16_t eeprom_read_word(const uint16_t *addr) {
496uint16_t eeprom_read_word(const uint16_t *addr) 476 const uint8_t *p = (const uint8_t *)addr;
497{ 477 return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8);
498 const uint8_t *p = (const uint8_t *)addr;
499 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
500} 478}
501 479
502uint32_t eeprom_read_dword(const uint32_t *addr) 480uint32_t eeprom_read_dword(const uint32_t *addr) {
503{ 481 const uint8_t *p = (const uint8_t *)addr;
504 const uint8_t *p = (const uint8_t *)addr; 482 return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24);
505 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
506 | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
507} 483}
508 484
509void eeprom_read_block(void *buf, const void *addr, uint32_t len) 485void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
510{ 486 const uint8_t *p = (const uint8_t *)addr;
511 const uint8_t *p = (const uint8_t *)addr; 487 uint8_t * dest = (uint8_t *)buf;
512 uint8_t *dest = (uint8_t *)buf; 488 while (len--) {
513 while (len--) { 489 *dest++ = eeprom_read_byte(p++);
514 *dest++ = eeprom_read_byte(p++); 490 }
515 }
516} 491}
517 492
518int eeprom_is_ready(void) 493int eeprom_is_ready(void) { return 1; }
519{
520 return 1;
521}
522 494
523void eeprom_write_word(uint16_t *addr, uint16_t value) 495void eeprom_write_word(uint16_t *addr, uint16_t value) {
524{ 496 uint8_t *p = (uint8_t *)addr;
525 uint8_t *p = (uint8_t *)addr; 497 eeprom_write_byte(p++, value);
526 eeprom_write_byte(p++, value); 498 eeprom_write_byte(p, value >> 8);
527 eeprom_write_byte(p, value >> 8);
528} 499}
529 500
530void eeprom_write_dword(uint32_t *addr, uint32_t value) 501void eeprom_write_dword(uint32_t *addr, uint32_t value) {
531{ 502 uint8_t *p = (uint8_t *)addr;
532 uint8_t *p = (uint8_t *)addr; 503 eeprom_write_byte(p++, value);
533 eeprom_write_byte(p++, value); 504 eeprom_write_byte(p++, value >> 8);
534 eeprom_write_byte(p++, value >> 8); 505 eeprom_write_byte(p++, value >> 16);
535 eeprom_write_byte(p++, value >> 16); 506 eeprom_write_byte(p, value >> 24);
536 eeprom_write_byte(p, value >> 24);
537} 507}
538 508
539void eeprom_write_block(const void *buf, void *addr, uint32_t len) 509void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
540{ 510 uint8_t * p = (uint8_t *)addr;
541 uint8_t *p = (uint8_t *)addr; 511 const uint8_t *src = (const uint8_t *)buf;
542 const uint8_t *src = (const uint8_t *)buf; 512 while (len--) {
543 while (len--) { 513 eeprom_write_byte(p++, *src++);
544 eeprom_write_byte(p++, *src++); 514 }
545 }
546} 515}
547 516
548#else 517#else
549// No EEPROM supported, so emulate it 518// No EEPROM supported, so emulate it
550 519
551#define EEPROM_SIZE 32 520# define EEPROM_SIZE 32
552static uint8_t buffer[EEPROM_SIZE]; 521static uint8_t buffer[EEPROM_SIZE];
553 522
554uint8_t eeprom_read_byte(const uint8_t *addr) { 523uint8_t eeprom_read_byte(const uint8_t *addr) {
555 uint32_t offset = (uint32_t)addr; 524 uint32_t offset = (uint32_t)addr;
556 return buffer[offset]; 525 return buffer[offset];
557} 526}
558 527
559void eeprom_write_byte(uint8_t *addr, uint8_t value) { 528void eeprom_write_byte(uint8_t *addr, uint8_t value) {
560 uint32_t offset = (uint32_t)addr; 529 uint32_t offset = (uint32_t)addr;
561 buffer[offset] = value; 530 buffer[offset] = value;
562} 531}
563 532
564uint16_t eeprom_read_word(const uint16_t *addr) { 533uint16_t eeprom_read_word(const uint16_t *addr) {
565 const uint8_t *p = (const uint8_t *)addr; 534 const uint8_t *p = (const uint8_t *)addr;
566 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8); 535 return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8);
567} 536}
568 537
569uint32_t eeprom_read_dword(const uint32_t *addr) { 538uint32_t eeprom_read_dword(const uint32_t *addr) {
570 const uint8_t *p = (const uint8_t *)addr; 539 const uint8_t *p = (const uint8_t *)addr;
571 return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8) 540 return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24);
572 | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
573} 541}
574 542
575void eeprom_read_block(void *buf, const void *addr, uint32_t len) { 543void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
576 const uint8_t *p = (const uint8_t *)addr; 544 const uint8_t *p = (const uint8_t *)addr;
577 uint8_t *dest = (uint8_t *)buf; 545 uint8_t * dest = (uint8_t *)buf;
578 while (len--) { 546 while (len--) {
579 *dest++ = eeprom_read_byte(p++); 547 *dest++ = eeprom_read_byte(p++);
580 } 548 }
581} 549}
582 550
583void eeprom_write_word(uint16_t *addr, uint16_t value) { 551void eeprom_write_word(uint16_t *addr, uint16_t value) {
584 uint8_t *p = (uint8_t *)addr; 552 uint8_t *p = (uint8_t *)addr;
585 eeprom_write_byte(p++, value); 553 eeprom_write_byte(p++, value);
586 eeprom_write_byte(p, value >> 8); 554 eeprom_write_byte(p, value >> 8);
587} 555}
588 556
589void eeprom_write_dword(uint32_t *addr, uint32_t value) { 557void eeprom_write_dword(uint32_t *addr, uint32_t value) {
590 uint8_t *p = (uint8_t *)addr; 558 uint8_t *p = (uint8_t *)addr;
591 eeprom_write_byte(p++, value); 559 eeprom_write_byte(p++, value);
592 eeprom_write_byte(p++, value >> 8); 560 eeprom_write_byte(p++, value >> 8);
593 eeprom_write_byte(p++, value >> 16); 561 eeprom_write_byte(p++, value >> 16);
594 eeprom_write_byte(p, value >> 24); 562 eeprom_write_byte(p, value >> 24);
595} 563}
596 564
597void eeprom_write_block(const void *buf, void *addr, uint32_t len) { 565void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
598 uint8_t *p = (uint8_t *)addr; 566 uint8_t * p = (uint8_t *)addr;
599 const uint8_t *src = (const uint8_t *)buf; 567 const uint8_t *src = (const uint8_t *)buf;
600 while (len--) { 568 while (len--) {
601 eeprom_write_byte(p++, *src++); 569 eeprom_write_byte(p++, *src++);
602 } 570 }
603} 571}
604 572
605#endif /* chip selection */ 573#endif /* chip selection */
606// The update functions just calls write for now, but could probably be optimized 574// The update functions just calls write for now, but could probably be optimized
607 575
608void eeprom_update_byte(uint8_t *addr, uint8_t value) { 576void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); }
609 eeprom_write_byte(addr, value);
610}
611 577
612void eeprom_update_word(uint16_t *addr, uint16_t value) { 578void eeprom_update_word(uint16_t *addr, uint16_t value) {
613 uint8_t *p = (uint8_t *)addr; 579 uint8_t *p = (uint8_t *)addr;
614 eeprom_write_byte(p++, value); 580 eeprom_write_byte(p++, value);
615 eeprom_write_byte(p, value >> 8); 581 eeprom_write_byte(p, value >> 8);
616} 582}
617 583
618void eeprom_update_dword(uint32_t *addr, uint32_t value) { 584void eeprom_update_dword(uint32_t *addr, uint32_t value) {
619 uint8_t *p = (uint8_t *)addr; 585 uint8_t *p = (uint8_t *)addr;
620 eeprom_write_byte(p++, value); 586 eeprom_write_byte(p++, value);
621 eeprom_write_byte(p++, value >> 8); 587 eeprom_write_byte(p++, value >> 8);
622 eeprom_write_byte(p++, value >> 16); 588 eeprom_write_byte(p++, value >> 16);
623 eeprom_write_byte(p, value >> 24); 589 eeprom_write_byte(p, value >> 24);
624} 590}
625 591
626void eeprom_update_block(const void *buf, void *addr, uint32_t len) { 592void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
627 uint8_t *p = (uint8_t *)addr; 593 uint8_t * p = (uint8_t *)addr;
628 const uint8_t *src = (const uint8_t *)buf; 594 const uint8_t *src = (const uint8_t *)buf;
629 while (len--) { 595 while (len--) {
630 eeprom_write_byte(p++, *src++); 596 eeprom_write_byte(p++, *src++);
631 } 597 }
632} 598}
diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c
index 832bf3908..e166fc5e6 100755..100644
--- a/tmk_core/common/chibios/flash_stm32.c
+++ b/tmk_core/common/chibios/flash_stm32.c
@@ -17,105 +17,95 @@
17 */ 17 */
18 18
19#if defined(EEPROM_EMU_STM32F303xC) 19#if defined(EEPROM_EMU_STM32F303xC)
20 #define STM32F303xC 20# define STM32F303xC
21 #include "stm32f3xx.h" 21# include "stm32f3xx.h"
22#elif defined(EEPROM_EMU_STM32F103xB) 22#elif defined(EEPROM_EMU_STM32F103xB)
23 #define STM32F103xB 23# define STM32F103xB
24 #include "stm32f1xx.h" 24# include "stm32f1xx.h"
25#elif defined(EEPROM_EMU_STM32F072xB) 25#elif defined(EEPROM_EMU_STM32F072xB)
26 #define STM32F072xB 26# define STM32F072xB
27 #include "stm32f0xx.h" 27# include "stm32f0xx.h"
28#else 28#else
29 #error "not implemented." 29# error "not implemented."
30#endif 30#endif
31 31
32#include "flash_stm32.h" 32#include "flash_stm32.h"
33 33
34#if defined(EEPROM_EMU_STM32F103xB) 34#if defined(EEPROM_EMU_STM32F103xB)
35 #define FLASH_SR_WRPERR FLASH_SR_WRPRTERR 35# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
36#endif 36#endif
37 37
38/* Delay definition */ 38/* Delay definition */
39#define EraseTimeout ((uint32_t)0x00000FFF) 39#define EraseTimeout ((uint32_t)0x00000FFF)
40#define ProgramTimeout ((uint32_t)0x0000001F) 40#define ProgramTimeout ((uint32_t)0x0000001F)
41 41
42#define ASSERT(exp) (void)((0)) 42#define ASSERT(exp) (void)((0))
43 43
44/** 44/**
45 * @brief Inserts a time delay. 45 * @brief Inserts a time delay.
46 * @param None 46 * @param None
47 * @retval None 47 * @retval None
48 */ 48 */
49static void delay(void) 49static void delay(void) {
50{
51 __IO uint32_t i = 0; 50 __IO uint32_t i = 0;
52 for(i = 0xFF; i != 0; i--) { } 51 for (i = 0xFF; i != 0; i--) {
52 }
53} 53}
54 54
55/** 55/**
56 * @brief Returns the FLASH Status. 56 * @brief Returns the FLASH Status.
57 * @param None 57 * @param None
58 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, 58 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
59 * FLASH_ERROR_WRP or FLASH_COMPLETE 59 * FLASH_ERROR_WRP or FLASH_COMPLETE
60 */ 60 */
61FLASH_Status FLASH_GetStatus(void) 61FLASH_Status FLASH_GetStatus(void) {
62{ 62 if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) return FLASH_BUSY;
63 if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
64 return FLASH_BUSY;
65 63
66 if ((FLASH->SR & FLASH_SR_PGERR) != 0) 64 if ((FLASH->SR & FLASH_SR_PGERR) != 0) return FLASH_ERROR_PG;
67 return FLASH_ERROR_PG;
68 65
69 if ((FLASH->SR & FLASH_SR_WRPERR) != 0 ) 66 if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
70 return FLASH_ERROR_WRP;
71 67
72 if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 ) 68 if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
73 return FLASH_ERROR_OPT;
74 69
75 return FLASH_COMPLETE; 70 return FLASH_COMPLETE;
76} 71}
77 72
78/** 73/**
79 * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. 74 * @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
80 * @param Timeout: FLASH progamming Timeout 75 * @param Timeout: FLASH progamming Timeout
81 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, 76 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
82 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. 77 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
83 */ 78 */
84FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) 79FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
85{
86 FLASH_Status status; 80 FLASH_Status status;
87 81
88 /* Check for the Flash Status */ 82 /* Check for the Flash Status */
89 status = FLASH_GetStatus(); 83 status = FLASH_GetStatus();
90 /* Wait for a Flash operation to complete or a TIMEOUT to occur */ 84 /* Wait for a Flash operation to complete or a TIMEOUT to occur */
91 while ((status == FLASH_BUSY) && (Timeout != 0x00)) 85 while ((status == FLASH_BUSY) && (Timeout != 0x00)) {
92 {
93 delay(); 86 delay();
94 status = FLASH_GetStatus(); 87 status = FLASH_GetStatus();
95 Timeout--; 88 Timeout--;
96 } 89 }
97 if (Timeout == 0) 90 if (Timeout == 0) status = FLASH_TIMEOUT;
98 status = FLASH_TIMEOUT;
99 /* Return the operation status */ 91 /* Return the operation status */
100 return status; 92 return status;
101} 93}
102 94
103/** 95/**
104 * @brief Erases a specified FLASH page. 96 * @brief Erases a specified FLASH page.
105 * @param Page_Address: The page address to be erased. 97 * @param Page_Address: The page address to be erased.
106 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, 98 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
107 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. 99 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
108 */ 100 */
109FLASH_Status FLASH_ErasePage(uint32_t Page_Address) 101FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
110{
111 FLASH_Status status = FLASH_COMPLETE; 102 FLASH_Status status = FLASH_COMPLETE;
112 /* Check the parameters */ 103 /* Check the parameters */
113 ASSERT(IS_FLASH_ADDRESS(Page_Address)); 104 ASSERT(IS_FLASH_ADDRESS(Page_Address));
114 /* Wait for last operation to be completed */ 105 /* Wait for last operation to be completed */
115 status = FLASH_WaitForLastOperation(EraseTimeout); 106 status = FLASH_WaitForLastOperation(EraseTimeout);
116 107
117 if(status == FLASH_COMPLETE) 108 if (status == FLASH_COMPLETE) {
118 {
119 /* if the previous operation is completed, proceed to erase the page */ 109 /* if the previous operation is completed, proceed to erase the page */
120 FLASH->CR |= FLASH_CR_PER; 110 FLASH->CR |= FLASH_CR_PER;
121 FLASH->AR = Page_Address; 111 FLASH->AR = Page_Address;
@@ -123,8 +113,7 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
123 113
124 /* Wait for last operation to be completed */ 114 /* Wait for last operation to be completed */
125 status = FLASH_WaitForLastOperation(EraseTimeout); 115 status = FLASH_WaitForLastOperation(EraseTimeout);
126 if(status != FLASH_TIMEOUT) 116 if (status != FLASH_TIMEOUT) {
127 {
128 /* if the erase operation is completed, disable the PER Bit */ 117 /* if the erase operation is completed, disable the PER Bit */
129 FLASH->CR &= ~FLASH_CR_PER; 118 FLASH->CR &= ~FLASH_CR_PER;
130 } 119 }
@@ -135,29 +124,25 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
135} 124}
136 125
137/** 126/**
138 * @brief Programs a half word at a specified address. 127 * @brief Programs a half word at a specified address.
139 * @param Address: specifies the address to be programmed. 128 * @param Address: specifies the address to be programmed.
140 * @param Data: specifies the data to be programmed. 129 * @param Data: specifies the data to be programmed.
141 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, 130 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
142 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. 131 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
143 */ 132 */
144FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) 133FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
145{
146 FLASH_Status status = FLASH_BAD_ADDRESS; 134 FLASH_Status status = FLASH_BAD_ADDRESS;
147 135
148 if (IS_FLASH_ADDRESS(Address)) 136 if (IS_FLASH_ADDRESS(Address)) {
149 {
150 /* Wait for last operation to be completed */ 137 /* Wait for last operation to be completed */
151 status = FLASH_WaitForLastOperation(ProgramTimeout); 138 status = FLASH_WaitForLastOperation(ProgramTimeout);
152 if(status == FLASH_COMPLETE) 139 if (status == FLASH_COMPLETE) {
153 {
154 /* if the previous operation is completed, proceed to program the new data */ 140 /* if the previous operation is completed, proceed to program the new data */
155 FLASH->CR |= FLASH_CR_PG; 141 FLASH->CR |= FLASH_CR_PG;
156 *(__IO uint16_t*)Address = Data; 142 *(__IO uint16_t*)Address = Data;
157 /* Wait for last operation to be completed */ 143 /* Wait for last operation to be completed */
158 status = FLASH_WaitForLastOperation(ProgramTimeout); 144 status = FLASH_WaitForLastOperation(ProgramTimeout);
159 if(status != FLASH_TIMEOUT) 145 if (status != FLASH_TIMEOUT) {
160 {
161 /* if the program operation is completed, disable the PG Bit */ 146 /* if the program operation is completed, disable the PG Bit */
162 FLASH->CR &= ~FLASH_CR_PG; 147 FLASH->CR &= ~FLASH_CR_PG;
163 } 148 }
@@ -168,39 +153,36 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
168} 153}
169 154
170/** 155/**
171 * @brief Unlocks the FLASH Program Erase Controller. 156 * @brief Unlocks the FLASH Program Erase Controller.
172 * @param None 157 * @param None
173 * @retval None 158 * @retval None
174 */ 159 */
175void FLASH_Unlock(void) 160void FLASH_Unlock(void) {
176{
177 /* Authorize the FPEC Access */ 161 /* Authorize the FPEC Access */
178 FLASH->KEYR = FLASH_KEY1; 162 FLASH->KEYR = FLASH_KEY1;
179 FLASH->KEYR = FLASH_KEY2; 163 FLASH->KEYR = FLASH_KEY2;
180} 164}
181 165
182/** 166/**
183 * @brief Locks the FLASH Program Erase Controller. 167 * @brief Locks the FLASH Program Erase Controller.
184 * @param None 168 * @param None
185 * @retval None 169 * @retval None
186 */ 170 */
187void FLASH_Lock(void) 171void FLASH_Lock(void) {
188{
189 /* Set the Lock Bit to lock the FPEC and the FCR */ 172 /* Set the Lock Bit to lock the FPEC and the FCR */
190 FLASH->CR |= FLASH_CR_LOCK; 173 FLASH->CR |= FLASH_CR_LOCK;
191} 174}
192 175
193/** 176/**
194 * @brief Clears the FLASH's pending flags. 177 * @brief Clears the FLASH's pending flags.
195 * @param FLASH_FLAG: specifies the FLASH flags to clear. 178 * @param FLASH_FLAG: specifies the FLASH flags to clear.
196 * This parameter can be any combination of the following values: 179 * This parameter can be any combination of the following values:
197 * @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag 180 * @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag
198 * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag 181 * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag
199 * @arg FLASH_FLAG_EOP: FLASH End of Programming flag 182 * @arg FLASH_FLAG_EOP: FLASH End of Programming flag
200 * @retval None 183 * @retval None
201 */ 184 */
202void FLASH_ClearFlag(uint32_t FLASH_FLAG) 185void FLASH_ClearFlag(uint32_t FLASH_FLAG) {
203{
204 /* Clear the flags */ 186 /* Clear the flags */
205 FLASH->SR = FLASH_FLAG; 187 FLASH->SR = FLASH_FLAG;
206} 188}
diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h
index 3c99cc566..33ab7867d 100755..100644
--- a/tmk_core/common/chibios/flash_stm32.h
+++ b/tmk_core/common/chibios/flash_stm32.h
@@ -10,7 +10,7 @@
10 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 10 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
11 * DEALINGS IN THE SOFTWARE. 11 * DEALINGS IN THE SOFTWARE.
12 * 12 *
13 * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and 13 * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
14 * https://github.com/leaflabs/libmaple 14 * https://github.com/leaflabs/libmaple
15 * 15 *
16 * Modifications for QMK and STM32F303 by Yiancar 16 * Modifications for QMK and STM32F303 by Yiancar
@@ -20,22 +20,13 @@
20#define __FLASH_STM32_H 20#define __FLASH_STM32_H
21 21
22#ifdef __cplusplus 22#ifdef __cplusplus
23 extern "C" { 23extern "C" {
24#endif 24#endif
25 25
26#include "ch.h" 26#include "ch.h"
27#include "hal.h" 27#include "hal.h"
28 28
29typedef enum 29typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT, FLASH_COMPLETE, FLASH_TIMEOUT, FLASH_BAD_ADDRESS } FLASH_Status;
30 {
31 FLASH_BUSY = 1,
32 FLASH_ERROR_PG,
33 FLASH_ERROR_WRP,
34 FLASH_ERROR_OPT,
35 FLASH_COMPLETE,
36 FLASH_TIMEOUT,
37 FLASH_BAD_ADDRESS
38 } FLASH_Status;
39 30
40#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) 31#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF))
41 32
diff --git a/tmk_core/common/chibios/printf.c b/tmk_core/common/chibios/printf.c
index 72e3d4f8c..dbd059448 100644
--- a/tmk_core/common/chibios/printf.c
+++ b/tmk_core/common/chibios/printf.c
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 26
27#include "printf.h" 27#include "printf.h"
28 28
29typedef void (*putcf) (void*,char); 29typedef void (*putcf)(void*, char);
30static putcf stdout_putf; 30static putcf stdout_putf;
31static void* stdout_putp; 31static void* stdout_putp;
32 32
@@ -35,206 +35,185 @@ static void* stdout_putp;
35 35
36#ifdef PRINTF_LONG_SUPPORT 36#ifdef PRINTF_LONG_SUPPORT
37 37
38static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf) 38static void uli2a(unsigned long int num, unsigned int base, int uc, char* bf) {
39 { 39 int n = 0;
40 int n=0; 40 unsigned int d = 1;
41 unsigned int d=1; 41 while (num / d >= base) d *= base;
42 while (num/d >= base) 42 while (d != 0) {
43 d*=base;
44 while (d!=0) {
45 int dgt = num / d; 43 int dgt = num / d;
46 num%=d; 44 num %= d;
47 d/=base; 45 d /= base;
48 if (n || dgt>0|| d==0) { 46 if (n || dgt > 0 || d == 0) {
49 *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); 47 *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
50 ++n; 48 ++n;
51 }
52 } 49 }
53 *bf=0;
54 } 50 }
51 *bf = 0;
52}
55 53
56static void li2a (long num, char * bf) 54static void li2a(long num, char* bf) {
57 { 55 if (num < 0) {
58 if (num<0) { 56 num = -num;
59 num=-num;
60 *bf++ = '-'; 57 *bf++ = '-';
61 }
62 uli2a(num,10,0,bf);
63 } 58 }
59 uli2a(num, 10, 0, bf);
60}
64 61
65#endif 62#endif
66 63
67static void ui2a(unsigned int num, unsigned int base, int uc,char * bf) 64static void ui2a(unsigned int num, unsigned int base, int uc, char* bf) {
68 { 65 int n = 0;
69 int n=0; 66 unsigned int d = 1;
70 unsigned int d=1; 67 while (num / d >= base) d *= base;
71 while (num/d >= base) 68 while (d != 0) {
72 d*=base;
73 while (d!=0) {
74 int dgt = num / d; 69 int dgt = num / d;
75 num%= d; 70 num %= d;
76 d/=base; 71 d /= base;
77 if (n || dgt>0 || d==0) { 72 if (n || dgt > 0 || d == 0) {
78 *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10); 73 *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
79 ++n; 74 ++n;
80 }
81 } 75 }
82 *bf=0;
83 } 76 }
77 *bf = 0;
78}
84 79
85static void i2a (int num, char * bf) 80static void i2a(int num, char* bf) {
86 { 81 if (num < 0) {
87 if (num<0) { 82 num = -num;
88 num=-num;
89 *bf++ = '-'; 83 *bf++ = '-';
90 }
91 ui2a(num,10,0,bf);
92 } 84 }
93 85 ui2a(num, 10, 0, bf);
94static int a2d(char ch) 86}
95 { 87
96 if (ch>='0' && ch<='9') 88static int a2d(char ch) {
97 return ch-'0'; 89 if (ch >= '0' && ch <= '9')
98 else if (ch>='a' && ch<='f') 90 return ch - '0';
99 return ch-'a'+10; 91 else if (ch >= 'a' && ch <= 'f')
100 else if (ch>='A' && ch<='F') 92 return ch - 'a' + 10;
101 return ch-'A'+10; 93 else if (ch >= 'A' && ch <= 'F')
102 else return -1; 94 return ch - 'A' + 10;
95 else
96 return -1;
97}
98
99static char a2i(char ch, char** src, int base, int* nump) {
100 char* p = *src;
101 int num = 0;
102 int digit;
103 while ((digit = a2d(ch)) >= 0) {
104 if (digit > base) break;
105 num = num * base + digit;
106 ch = *p++;
103 } 107 }
104 108 *src = p;
105static char a2i(char ch, char** src,int base,int* nump) 109 *nump = num;
106 {
107 char* p= *src;
108 int num=0;
109 int digit;
110 while ((digit=a2d(ch))>=0) {
111 if (digit>base) break;
112 num=num*base+digit;
113 ch=*p++;
114 }
115 *src=p;
116 *nump=num;
117 return ch; 110 return ch;
118 } 111}
119 112
120static void putchw(void* putp,putcf putf,int n, char z, char* bf) 113static void putchw(void* putp, putcf putf, int n, char z, char* bf) {
121 { 114 char fc = z ? '0' : ' ';
122 char fc=z? '0' : ' '; 115 char ch;
123 char ch; 116 char* p = bf;
124 char* p=bf; 117 while (*p++ && n > 0) n--;
125 while (*p++ && n > 0) 118 while (n-- > 0) putf(putp, fc);
126 n--; 119 while ((ch = *bf++)) putf(putp, ch);
127 while (n-- > 0) 120}
128 putf(putp,fc); 121
129 while ((ch= *bf++)) 122void tfp_format(void* putp, putcf putf, char* fmt, va_list va) {
130 putf(putp,ch);
131 }
132
133void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
134 {
135 char bf[12]; 123 char bf[12];
136
137 char ch;
138 124
125 char ch;
139 126
140 while ((ch=*(fmt++))) { 127 while ((ch = *(fmt++))) {
141 if (ch!='%') 128 if (ch != '%')
142 putf(putp,ch); 129 putf(putp, ch);
143 else { 130 else {
144 char lz=0; 131 char lz = 0;
145#ifdef PRINTF_LONG_SUPPORT 132#ifdef PRINTF_LONG_SUPPORT
146 char lng=0; 133 char lng = 0;
147#endif 134#endif
148 int w=0; 135 int w = 0;
149 ch=*(fmt++); 136 ch = *(fmt++);
150 if (ch=='0') { 137 if (ch == '0') {
151 ch=*(fmt++); 138 ch = *(fmt++);
152 lz=1; 139 lz = 1;
153 } 140 }
154 if (ch>='0' && ch<='9') { 141 if (ch >= '0' && ch <= '9') {
155 ch=a2i(ch,&fmt,10,&w); 142 ch = a2i(ch, &fmt, 10, &w);
156 } 143 }
157#ifdef PRINTF_LONG_SUPPORT 144#ifdef PRINTF_LONG_SUPPORT
158 if (ch=='l') { 145 if (ch == 'l') {
159 ch=*(fmt++); 146 ch = *(fmt++);
160 lng=1; 147 lng = 1;
161 } 148 }
162#endif 149#endif
163 switch (ch) { 150 switch (ch) {
164 case 0: 151 case 0:
165 goto abort; 152 goto abort;
166 case 'u' : { 153 case 'u': {
167#ifdef PRINTF_LONG_SUPPORT 154#ifdef PRINTF_LONG_SUPPORT
168 if (lng) 155 if (lng)
169 uli2a(va_arg(va, unsigned long int),10,0,bf); 156 uli2a(va_arg(va, unsigned long int), 10, 0, bf);
170 else 157 else
171#endif 158#endif
172 ui2a(va_arg(va, unsigned int),10,0,bf); 159 ui2a(va_arg(va, unsigned int), 10, 0, bf);
173 putchw(putp,putf,w,lz,bf); 160 putchw(putp, putf, w, lz, bf);
174 break; 161 break;
175 } 162 }
176 case 'd' : { 163 case 'd': {
177#ifdef PRINTF_LONG_SUPPORT 164#ifdef PRINTF_LONG_SUPPORT
178 if (lng) 165 if (lng)
179 li2a(va_arg(va, unsigned long int),bf); 166 li2a(va_arg(va, unsigned long int), bf);
180 else 167 else
181#endif 168#endif
182 i2a(va_arg(va, int),bf); 169 i2a(va_arg(va, int), bf);
183 putchw(putp,putf,w,lz,bf); 170 putchw(putp, putf, w, lz, bf);
184 break; 171 break;
185 } 172 }
186 case 'x': case 'X' : 173 case 'x':
187#ifdef PRINTF_LONG_SUPPORT 174 case 'X':
175#ifdef PRINTF_LONG_SUPPORT
188 if (lng) 176 if (lng)
189 uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf); 177 uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf);
190 else 178 else
191#endif 179#endif
192 ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf); 180 ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf);
193 putchw(putp,putf,w,lz,bf); 181 putchw(putp, putf, w, lz, bf);
194 break; 182 break;
195 case 'c' : 183 case 'c':
196 putf(putp,(char)(va_arg(va, int))); 184 putf(putp, (char)(va_arg(va, int)));
197 break; 185 break;
198 case 's' : 186 case 's':
199 putchw(putp,putf,w,0,va_arg(va, char*)); 187 putchw(putp, putf, w, 0, va_arg(va, char*));
200 break; 188 break;
201 case '%' : 189 case '%':
202 putf(putp,ch); 190 putf(putp, ch);
203 default: 191 default:
204 break; 192 break;
205 }
206 } 193 }
207 } 194 }
208 abort:;
209 } 195 }
196abort:;
197}
210 198
199void init_printf(void* putp, void (*putf)(void*, char)) {
200 stdout_putf = putf;
201 stdout_putp = putp;
202}
211 203
212void init_printf(void* putp,void (*putf) (void*,char)) 204void tfp_printf(char* fmt, ...) {
213 {
214 stdout_putf=putf;
215 stdout_putp=putp;
216 }
217
218void tfp_printf(char *fmt, ...)
219 {
220 va_list va; 205 va_list va;
221 va_start(va,fmt); 206 va_start(va, fmt);
222 tfp_format(stdout_putp,stdout_putf,fmt,va); 207 tfp_format(stdout_putp, stdout_putf, fmt, va);
223 va_end(va); 208 va_end(va);
224 } 209}
225
226static void putcp(void* p,char c)
227 {
228 *(*((char**)p))++ = c;
229 }
230 210
211static void putcp(void* p, char c) { *(*((char**)p))++ = c; }
231 212
232 213void tfp_sprintf(char* s, char* fmt, ...) {
233void tfp_sprintf(char* s,char *fmt, ...)
234 {
235 va_list va; 214 va_list va;
236 va_start(va,fmt); 215 va_start(va, fmt);
237 tfp_format(&s,putcp,fmt,va); 216 tfp_format(&s, putcp, fmt, va);
238 putcp(&s,0); 217 putcp(&s, 0);
239 va_end(va); 218 va_end(va);
240 } 219}
diff --git a/tmk_core/common/chibios/printf.h b/tmk_core/common/chibios/printf.h
index 678a100c6..2cdf55ed9 100644
--- a/tmk_core/common/chibios/printf.h
+++ b/tmk_core/common/chibios/printf.h
@@ -15,7 +15,7 @@ version 2.1 of the License, or (at your option) any later version.
15 15
16This library is distributed in the hope that it will be useful, 16This library is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of 17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19See the GNU Lesser General Public License for more details. 19See the GNU Lesser General Public License for more details.
20 20
21You should have received a copy of the GNU Lesser General Public 21You should have received a copy of the GNU Lesser General Public
@@ -24,35 +24,35 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 24
25This library is realy just two files: 'printf.h' and 'printf.c'. 25This library is realy just two files: 'printf.h' and 'printf.c'.
26 26
27They provide a simple and small (+200 loc) printf functionality to 27They provide a simple and small (+200 loc) printf functionality to
28be used in embedded systems. 28be used in embedded systems.
29 29
30I've found them so usefull in debugging that I do not bother with a 30I've found them so usefull in debugging that I do not bother with a
31debugger at all. 31debugger at all.
32 32
33They are distributed in source form, so to use them, just compile them 33They are distributed in source form, so to use them, just compile them
34into your project. 34into your project.
35 35
36Two printf variants are provided: printf and sprintf. 36Two printf variants are provided: printf and sprintf.
37 37
38The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. 38The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
39 39
40Zero padding and field width are also supported. 40Zero padding and field width are also supported.
41 41
42If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the 42If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
43long specifier is also 43long specifier is also
44supported. Note that this will pull in some long math routines (pun intended!) 44supported. Note that this will pull in some long math routines (pun intended!)
45and thus make your executable noticably longer. 45and thus make your executable noticably longer.
46 46
47The memory foot print of course depends on the target cpu, compiler and 47The memory foot print of course depends on the target cpu, compiler and
48compiler options, but a rough guestimate (based on a H8S target) is about 48compiler options, but a rough guestimate (based on a H8S target) is about
491.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. 491.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
50Not too bad. Your milage may vary. By hacking the source code you can 50Not too bad. Your milage may vary. By hacking the source code you can
51get rid of some hunred bytes, I'm sure, but personally I feel the balance of 51get rid of some hunred bytes, I'm sure, but personally I feel the balance of
52functionality and flexibility versus code size is close to optimal for 52functionality and flexibility versus code size is close to optimal for
53many embedded systems. 53many embedded systems.
54 54
55To use the printf you need to supply your own character output function, 55To use the printf you need to supply your own character output function,
56something like : 56something like :
57 57
58 void putc ( void* p, char c) 58 void putc ( void* p, char c)
@@ -61,25 +61,25 @@ something like :
61 SERIAL_PORT_TX_REGISTER = c; 61 SERIAL_PORT_TX_REGISTER = c;
62 } 62 }
63 63
64Before you can call printf you need to initialize it to use your 64Before you can call printf you need to initialize it to use your
65character output function with something like: 65character output function with something like:
66 66
67 init_printf(NULL,putc); 67 init_printf(NULL,putc);
68 68
69Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', 69Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
70the NULL (or any pointer) you pass into the 'init_printf' will eventually be 70the NULL (or any pointer) you pass into the 'init_printf' will eventually be
71passed to your 'putc' routine. This allows you to pass some storage space (or 71passed to your 'putc' routine. This allows you to pass some storage space (or
72anything realy) to the character output function, if necessary. 72anything realy) to the character output function, if necessary.
73This is not often needed but it was implemented like that because it made 73This is not often needed but it was implemented like that because it made
74implementing the sprintf function so neat (look at the source code). 74implementing the sprintf function so neat (look at the source code).
75 75
76The code is re-entrant, except for the 'init_printf' function, so it 76The code is re-entrant, except for the 'init_printf' function, so it
77is safe to call it from interupts too, although this may result in mixed output. 77is safe to call it from interupts too, although this may result in mixed output.
78If you rely on re-entrancy, take care that your 'putc' function is re-entrant! 78If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
79 79
80The printf and sprintf functions are actually macros that translate to 80The printf and sprintf functions are actually macros that translate to
81'tfp_printf' and 'tfp_sprintf'. This makes it possible 81'tfp_printf' and 'tfp_sprintf'. This makes it possible
82to use them along with 'stdio.h' printf's in a single source file. 82to use them along with 'stdio.h' printf's in a single source file.
83You just need to undef the names before you include the 'stdio.h'. 83You just need to undef the names before you include the 'stdio.h'.
84Note that these are not function like macros, so if you have variables 84Note that these are not function like macros, so if you have variables
85or struct members with these names, things will explode in your face. 85or struct members with these names, things will explode in your face.
@@ -92,20 +92,19 @@ For further details see source code.
92regs Kusti, 23.10.2004 92regs Kusti, 23.10.2004
93*/ 93*/
94 94
95
96#ifndef __TFP_PRINTF__ 95#ifndef __TFP_PRINTF__
97#define __TFP_PRINTF__ 96#define __TFP_PRINTF__
98 97
99#include <stdarg.h> 98#include <stdarg.h>
100 99
101void init_printf(void* putp,void (*putf) (void*,char)); 100void init_printf(void* putp, void (*putf)(void*, char));
102 101
103void tfp_printf(char *fmt, ...); 102void tfp_printf(char* fmt, ...);
104void tfp_sprintf(char* s,char *fmt, ...); 103void tfp_sprintf(char* s, char* fmt, ...);
105 104
106void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va); 105void tfp_format(void* putp, void (*putf)(void*, char), char* fmt, va_list va);
107 106
108#define printf tfp_printf 107#define printf tfp_printf
109#define sprintf tfp_sprintf 108#define sprintf tfp_sprintf
110 109
111#endif 110#endif
diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c
index 4c35cfcba..df1a1b5fc 100644
--- a/tmk_core/common/chibios/sleep_led.c
+++ b/tmk_core/common/chibios/sleep_led.c
@@ -12,14 +12,14 @@
12#if defined(KL2x) || defined(K20x) 12#if defined(KL2x) || defined(K20x)
13 13
14/* Use Low Power Timer (LPTMR) */ 14/* Use Low Power Timer (LPTMR) */
15#define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR 15# define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
16#define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF 16# define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
17 17
18#elif defined(STM32F0XX) 18#elif defined(STM32F0XX)
19 19
20/* Use TIM14 manually */ 20/* Use TIM14 manually */
21#define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER 21# define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
22#define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF 22# define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
23 23
24#endif 24#endif
25 25
@@ -31,39 +31,34 @@
31 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 31 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
32 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } 32 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
33 */ 33 */
34static const uint8_t breathing_table[64] = { 34static const uint8_t breathing_table[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
350, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
3615, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
37255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
3815, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
39};
40 35
41/* interrupt handler */ 36/* interrupt handler */
42OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) { 37OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
43 OSAL_IRQ_PROLOGUE(); 38 OSAL_IRQ_PROLOGUE();
44 39
45 /* Software PWM 40 /* Software PWM
46 * timer:1111 1111 1111 1111 41 * timer:1111 1111 1111 1111
47 * \_____/\/ \_______/____ count(0-255) 42 * \_____/\/ \_______/____ count(0-255)
48 * \ \______________ duration of step(4) 43 * \ \______________ duration of step(4)
49 * \__________________ index of step table(0-63) 44 * \__________________ index of step table(0-63)
50 */ 45 */
51 46
52 // this works for cca 65536 irqs/sec 47 // this works for cca 65536 irqs/sec
53 static union { 48 static union {
54 uint16_t row; 49 uint16_t row;
55 struct { 50 struct {
56 uint8_t count:8; 51 uint8_t count : 8;
57 uint8_t duration:2; 52 uint8_t duration : 2;
58 uint8_t index:6; 53 uint8_t index : 6;
59 } pwm; 54 } pwm;
60 } timer = { .row = 0 }; 55 } timer = {.row = 0};
61 56
62 timer.row++; 57 timer.row++;
63 58
64 // LED on 59 // LED on
65 if (timer.pwm.count == 0) { 60 if (timer.pwm.count == 0) {
66 led_set(1<<USB_LED_CAPS_LOCK); 61 led_set(1 << USB_LED_CAPS_LOCK);
67 } 62 }
68 // LED off 63 // LED off
69 if (timer.pwm.count == breathing_table[timer.pwm.index]) { 64 if (timer.pwm.count == breathing_table[timer.pwm.index]) {
@@ -78,19 +73,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
78 73
79#endif /* common parts for known platforms */ 74#endif /* common parts for known platforms */
80 75
81
82#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */ 76#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
83 77
84/* LPTMR clock options */ 78/* LPTMR clock options */
85#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */ 79# define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
86#define LPTMR_CLOCK_LPO 1 /* 1kHz clock */ 80# define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
87#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */ 81# define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
88#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */ 82# define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
89 83
90/* Work around inconsistencies in Freescale naming */ 84/* Work around inconsistencies in Freescale naming */
91#if !defined(SIM_SCGC5_LPTMR) 85# if !defined(SIM_SCGC5_LPTMR)
92#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER 86# define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
93#endif 87# endif
94 88
95/* Initialise the timer */ 89/* Initialise the timer */
96void sleep_led_init(void) { 90void sleep_led_init(void) {
@@ -101,52 +95,52 @@ void sleep_led_init(void) {
101 /* Set the compare value */ 95 /* Set the compare value */
102 LPTMR0->CMR = 0; // trigger on counter value (i.e. every time) 96 LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
103 97
104 /* Set up clock source and prescaler */ 98/* Set up clock source and prescaler */
105 /* Software PWM 99/* Software PWM
106 * ______ ______ __ 100 * ______ ______ __
107 * | ON |___OFF___| ON |___OFF___| .... 101 * | ON |___OFF___| ON |___OFF___| ....
108 * |<-------------->|<-------------->|<- .... 102 * |<-------------->|<-------------->|<- ....
109 * PWM period PWM period 103 * PWM period PWM period
110 * 104 *
111 * R interrupts/period[resolution] 105 * R interrupts/period[resolution]
112 * F periods/second[frequency] 106 * F periods/second[frequency]
113 * R * F interrupts/second 107 * R * F interrupts/second
114 */ 108 */
115 109
116 /* === OPTION 1 === */ 110/* === OPTION 1 === */
117 #if 0 111# if 0
118 // 1kHz LPO 112 // 1kHz LPO
119 // No prescaler => 1024 irqs/sec 113 // No prescaler => 1024 irqs/sec
120 // Note: this is too slow for a smooth breathe 114 // Note: this is too slow for a smooth breathe
121 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP; 115 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
122 #endif /* OPTION 1 */ 116# endif /* OPTION 1 */
123 117
124 /* === OPTION 2 === */ 118/* === OPTION 2 === */
125 #if 1 119# if 1
126 // nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z) 120 // nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
127 MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock 121 MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
128 #if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others 122# if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
129 MCG->MC |= MCG_MC_LIRC_DIV2_DIV2; 123 MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
130 #endif /* KL27 */ 124# endif /* KL27 */
131 MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock 125 MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
132 // to work in stop mode, also MCG_C1_IREFSTEN 126 // to work in stop mode, also MCG_C1_IREFSTEN
133 // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec => 127 // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
134 // => approx F=61, R=256, duration = 4 128 // => approx F=61, R=256, duration = 4
135 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6); 129 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK) | LPTMRx_PSR_PRESCALE(6);
136 #endif /* OPTION 2 */ 130# endif /* OPTION 2 */
137 131
138 /* === OPTION 3 === */ 132/* === OPTION 3 === */
139 #if 0 133# if 0
140 // OSC output (external crystal), usually 8MHz or 16MHz 134 // OSC output (external crystal), usually 8MHz or 16MHz
141 OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock 135 OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
142 // to work in stop mode, also OSC_CR_EREFSTEN 136 // to work in stop mode, also OSC_CR_EREFSTEN
143 // Divide by 2^N 137 // Divide by 2^N
144 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7); 138 LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
145 #endif /* OPTION 3 */ 139# endif /* OPTION 3 */
146 /* === END OPTIONS === */ 140 /* === END OPTIONS === */
147 141
148 /* Interrupt on TCF set (compare flag) */ 142 /* Interrupt on TCF set (compare flag) */
149 nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority 143 nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
150 LPTMR0->CSR |= LPTMRx_CSR_TIE; 144 LPTMR0->CSR |= LPTMRx_CSR_TIE;
151} 145}
152 146
@@ -205,20 +199,14 @@ void sleep_led_toggle(void) {
205 STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN; 199 STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN;
206} 200}
207 201
208
209#else /* platform selection: not on familiar chips */ 202#else /* platform selection: not on familiar chips */
210 203
211void sleep_led_init(void) { 204void sleep_led_init(void) {}
212} 205
213 206void sleep_led_enable(void) { led_set(1 << USB_LED_CAPS_LOCK); }
214void sleep_led_enable(void) { 207
215 led_set(1<<USB_LED_CAPS_LOCK); 208void sleep_led_disable(void) { led_set(0); }
216} 209
217
218void sleep_led_disable(void) {
219 led_set(0);
220}
221
222void sleep_led_toggle(void) { 210void sleep_led_toggle(void) {
223 // not implemented 211 // not implemented
224} 212}
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
index 6027d69b7..ae1c6f53e 100644
--- a/tmk_core/common/chibios/suspend.c
+++ b/tmk_core/common/chibios/suspend.c
@@ -17,49 +17,44 @@
17 * FIXME: needs doc 17 * FIXME: needs doc
18 */ 18 */
19void suspend_idle(uint8_t time) { 19void suspend_idle(uint8_t time) {
20 // TODO: this is not used anywhere - what units is 'time' in? 20 // TODO: this is not used anywhere - what units is 'time' in?
21 wait_ms(time); 21 wait_ms(time);
22} 22}
23 23
24/** \brief Run keyboard level Power down 24/** \brief Run keyboard level Power down
25 * 25 *
26 * FIXME: needs doc 26 * FIXME: needs doc
27 */ 27 */
28__attribute__ ((weak)) 28__attribute__((weak)) void suspend_power_down_user(void) {}
29void suspend_power_down_user (void) { }
30/** \brief Run keyboard level Power down 29/** \brief Run keyboard level Power down
31 * 30 *
32 * FIXME: needs doc 31 * FIXME: needs doc
33 */ 32 */
34__attribute__ ((weak)) 33__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
35void suspend_power_down_kb(void) {
36 suspend_power_down_user();
37}
38 34
39/** \brief suspend power down 35/** \brief suspend power down
40 * 36 *
41 * FIXME: needs doc 37 * FIXME: needs doc
42 */ 38 */
43void suspend_power_down(void) { 39void suspend_power_down(void) {
44 // TODO: figure out what to power down and how 40 // TODO: figure out what to power down and how
45 // shouldn't power down TPM/FTM if we want a breathing LED 41 // shouldn't power down TPM/FTM if we want a breathing LED
46 // also shouldn't power down USB 42 // also shouldn't power down USB
47 43
48 suspend_power_down_kb(); 44 suspend_power_down_kb();
49 // on AVR, this enables the watchdog for 15ms (max), and goes to 45 // on AVR, this enables the watchdog for 15ms (max), and goes to
50 // SLEEP_MODE_PWR_DOWN 46 // SLEEP_MODE_PWR_DOWN
51 47
52 wait_ms(17); 48 wait_ms(17);
53} 49}
54 50
55/** \brief suspend wakeup condition 51/** \brief suspend wakeup condition
56 * 52 *
57 * FIXME: needs doc 53 * FIXME: needs doc
58 */ 54 */
59__attribute__ ((weak)) void matrix_power_up(void) {} 55__attribute__((weak)) void matrix_power_up(void) {}
60__attribute__ ((weak)) void matrix_power_down(void) {} 56__attribute__((weak)) void matrix_power_down(void) {}
61bool suspend_wakeup_condition(void) 57bool suspend_wakeup_condition(void) {
62{
63 matrix_power_up(); 58 matrix_power_up();
64 matrix_scan(); 59 matrix_scan();
65 matrix_power_down(); 60 matrix_power_down();
@@ -73,25 +68,20 @@ bool suspend_wakeup_condition(void)
73 * 68 *
74 * FIXME: needs doc 69 * FIXME: needs doc
75 */ 70 */
76__attribute__ ((weak)) 71__attribute__((weak)) void suspend_wakeup_init_user(void) {}
77void suspend_wakeup_init_user(void) { }
78 72
79/** \brief run keyboard level code immediately after wakeup 73/** \brief run keyboard level code immediately after wakeup
80 * 74 *
81 * FIXME: needs doc 75 * FIXME: needs doc
82 */ 76 */
83__attribute__ ((weak)) 77__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
84void suspend_wakeup_init_kb(void) {
85 suspend_wakeup_init_user();
86}
87 78
88/** \brief suspend wakeup condition 79/** \brief suspend wakeup condition
89 * 80 *
90 * run immediately after wakeup 81 * run immediately after wakeup
91 * FIXME: needs doc 82 * FIXME: needs doc
92 */ 83 */
93void suspend_wakeup_init(void) 84void suspend_wakeup_init(void) {
94{
95 // clear keyboard state 85 // clear keyboard state
96 // need to do it manually, because we're running from ISR 86 // need to do it manually, because we're running from ISR
97 // and clear_keyboard() calls print 87 // and clear_keyboard() calls print
@@ -111,5 +101,5 @@ void suspend_wakeup_init(void)
111#ifdef BACKLIGHT_ENABLE 101#ifdef BACKLIGHT_ENABLE
112 backlight_init(); 102 backlight_init();
113#endif /* BACKLIGHT_ENABLE */ 103#endif /* BACKLIGHT_ENABLE */
114 suspend_wakeup_init_kb(); 104 suspend_wakeup_init_kb();
115} 105}
diff --git a/tmk_core/common/chibios/timer.c b/tmk_core/common/chibios/timer.c
index 473e533ca..1ce9d1d17 100644
--- a/tmk_core/common/chibios/timer.c
+++ b/tmk_core/common/chibios/timer.c
@@ -2,40 +2,32 @@
2 2
3#include "timer.h" 3#include "timer.h"
4 4
5static systime_t last_systime = 0; 5static systime_t last_systime = 0;
6static systime_t overflow = 0; 6static systime_t overflow = 0;
7static uint32_t current_time_ms = 0; 7static uint32_t current_time_ms = 0;
8 8
9void timer_init(void) { 9void timer_init(void) { timer_clear(); }
10 timer_clear();
11}
12 10
13void timer_clear(void) { 11void timer_clear(void) {
14 last_systime = chVTGetSystemTime(); 12 last_systime = chVTGetSystemTime();
15 overflow = 0; 13 overflow = 0;
16 current_time_ms = 0; 14 current_time_ms = 0;
17} 15}
18 16
19uint16_t timer_read(void) { 17uint16_t timer_read(void) { return (uint16_t)timer_read32(); }
20 return (uint16_t)timer_read32();
21}
22 18
23uint32_t timer_read32(void) { 19uint32_t timer_read32(void) {
24 // Note: We assume that the timer update is called at least once betweeen every wrap around of the system time 20 // Note: We assume that the timer update is called at least once betweeen every wrap around of the system time
25 systime_t current_systime = chVTGetSystemTime(); 21 systime_t current_systime = chVTGetSystemTime();
26 systime_t elapsed = current_systime - last_systime + overflow; 22 systime_t elapsed = current_systime - last_systime + overflow;
27 uint32_t elapsed_ms = ST2MS(elapsed); 23 uint32_t elapsed_ms = ST2MS(elapsed);
28 current_time_ms += elapsed_ms; 24 current_time_ms += elapsed_ms;
29 overflow = elapsed - MS2ST(elapsed_ms); 25 overflow = elapsed - MS2ST(elapsed_ms);
30 last_systime = current_systime; 26 last_systime = current_systime;
31 27
32 return current_time_ms; 28 return current_time_ms;
33} 29}
34 30
35uint16_t timer_elapsed(uint16_t last) { 31uint16_t timer_elapsed(uint16_t last) { return timer_read() - last; }
36 return timer_read() - last;
37}
38 32
39uint32_t timer_elapsed32(uint32_t last) { 33uint32_t timer_elapsed32(uint32_t last) { return timer_read32() - last; }
40 return timer_read32() - last;
41}