clang-format changes
This commit is contained in:
		
							parent
							
								
									61af76a10d
								
							
						
					
					
						commit
						b624f32f94
					
				
					 502 changed files with 32259 additions and 39062 deletions
				
			
		| 
						 | 
				
			
			@ -7,63 +7,62 @@
 | 
			
		|||
/* STM32 */
 | 
			
		||||
 | 
			
		||||
/* This code should be checked whether it runs correctly on platforms */
 | 
			
		||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
#    define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
extern uint32_t __ram0_end__;
 | 
			
		||||
#define BOOTLOADER_MAGIC 0xDEADBEEF
 | 
			
		||||
#define MAGIC_ADDR (unsigned long*)(SYMVAL(__ram0_end__) - 4)
 | 
			
		||||
 | 
			
		||||
#    define BOOTLOADER_MAGIC 0xDEADBEEF
 | 
			
		||||
#    define MAGIC_ADDR (unsigned long *)(SYMVAL(__ram0_end__) - 4)
 | 
			
		||||
 | 
			
		||||
/** \brief Jump to the bootloader
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
  *MAGIC_ADDR = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader
 | 
			
		||||
   NVIC_SystemReset();
 | 
			
		||||
    *MAGIC_ADDR = BOOTLOADER_MAGIC;  // set magic flag => reset handler will jump into boot loader
 | 
			
		||||
    NVIC_SystemReset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Enter bootloader mode if requested
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void enter_bootloader_mode_if_requested(void)  {
 | 
			
		||||
  unsigned long* check = MAGIC_ADDR;
 | 
			
		||||
  if(*check == BOOTLOADER_MAGIC)  {
 | 
			
		||||
    *check = 0;
 | 
			
		||||
    __set_CONTROL(0);
 | 
			
		||||
    __set_MSP(*(__IO uint32_t*)STM32_BOOTLOADER_ADDRESS);
 | 
			
		||||
    __enable_irq();
 | 
			
		||||
void enter_bootloader_mode_if_requested(void) {
 | 
			
		||||
    unsigned long *check = MAGIC_ADDR;
 | 
			
		||||
    if (*check == BOOTLOADER_MAGIC) {
 | 
			
		||||
        *check = 0;
 | 
			
		||||
        __set_CONTROL(0);
 | 
			
		||||
        __set_MSP(*(__IO uint32_t *)STM32_BOOTLOADER_ADDRESS);
 | 
			
		||||
        __enable_irq();
 | 
			
		||||
 | 
			
		||||
    typedef void (*BootJump_t)(void);
 | 
			
		||||
    BootJump_t boot_jump = *(BootJump_t*)(STM32_BOOTLOADER_ADDRESS + 4);
 | 
			
		||||
    boot_jump();
 | 
			
		||||
    while(1);
 | 
			
		||||
  }
 | 
			
		||||
 }
 | 
			
		||||
        typedef void (*BootJump_t)(void);
 | 
			
		||||
        BootJump_t boot_jump = *(BootJump_t *)(STM32_BOOTLOADER_ADDRESS + 4);
 | 
			
		||||
        boot_jump();
 | 
			
		||||
        while (1)
 | 
			
		||||
            ;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
 | 
			
		||||
/* Kinetis */
 | 
			
		||||
 | 
			
		||||
#if defined(KIIBOHD_BOOTLOADER)
 | 
			
		||||
#    if defined(KIIBOHD_BOOTLOADER)
 | 
			
		||||
/* Kiibohd Bootloader (MCHCK and Infinity KB) */
 | 
			
		||||
#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
 | 
			
		||||
#        define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
 | 
			
		||||
const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
  __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
 | 
			
		||||
  // request reset
 | 
			
		||||
  SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
 | 
			
		||||
void          bootloader_jump(void) {
 | 
			
		||||
    __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
 | 
			
		||||
    // request reset
 | 
			
		||||
    SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* defined(KIIBOHD_BOOTLOADER) */
 | 
			
		||||
#    else /* defined(KIIBOHD_BOOTLOADER) */
 | 
			
		||||
/* Default for Kinetis - expecting an ARM Teensy */
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
#        include "wait.h"
 | 
			
		||||
void bootloader_jump(void) {
 | 
			
		||||
	wait_ms(100);
 | 
			
		||||
	__BKPT(0);
 | 
			
		||||
    wait_ms(100);
 | 
			
		||||
    __BKPT(0);
 | 
			
		||||
}
 | 
			
		||||
#endif /* defined(KIIBOHD_BOOTLOADER) */
 | 
			
		||||
#    endif /* defined(KIIBOHD_BOOTLOADER) */
 | 
			
		||||
 | 
			
		||||
#else /* neither STM32 nor KINETIS */
 | 
			
		||||
__attribute__((weak))
 | 
			
		||||
void bootloader_jump(void) {}
 | 
			
		||||
__attribute__((weak)) void bootloader_jump(void) {}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										142
									
								
								tmk_core/common/chibios/eeprom_stm32.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										142
									
								
								tmk_core/common/chibios/eeprom_stm32.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							| 
						 | 
				
			
			@ -24,7 +24,7 @@
 | 
			
		|||
 * the functionality use the EEPROM_Init() function. Be sure that by reprogramming
 | 
			
		||||
 * of the controller just affected pages will be deleted. In other case the non
 | 
			
		||||
 * volatile data will be lost.
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/* Private macro -------------------------------------------------------------*/
 | 
			
		||||
/* Private variables ---------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			@ -32,23 +32,22 @@
 | 
			
		|||
 | 
			
		||||
uint8_t DataBuf[FEE_PAGE_SIZE];
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
*  Delete Flash Space used for user Data, deletes the whole space between
 | 
			
		||||
*  RW_PAGE_BASE_ADDRESS and the last uC Flash Page
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 *  Delete Flash Space used for user Data, deletes the whole space between
 | 
			
		||||
 *  RW_PAGE_BASE_ADDRESS and the last uC Flash Page
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
uint16_t EEPROM_Init(void) {
 | 
			
		||||
    // unlock flash
 | 
			
		||||
    FLASH_Unlock();
 | 
			
		||||
 | 
			
		||||
    // Clear Flags
 | 
			
		||||
    //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
 | 
			
		||||
    // FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
 | 
			
		||||
 | 
			
		||||
    return FEE_DENSITY_BYTES;
 | 
			
		||||
}
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
*  Erase the whole reserved Flash Space used for user Data
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
void EEPROM_Erase (void) {
 | 
			
		||||
 | 
			
		||||
 *  Erase the whole reserved Flash Space used for user Data
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
void EEPROM_Erase(void) {
 | 
			
		||||
    int page_num = 0;
 | 
			
		||||
 | 
			
		||||
    // delete all pages from specified start page to the last page
 | 
			
		||||
| 
						 | 
				
			
			@ -58,16 +57,15 @@ void EEPROM_Erase (void) {
 | 
			
		|||
    } while (page_num < FEE_DENSITY_PAGES);
 | 
			
		||||
}
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
*  Writes once data byte to flash on specified address. If a byte is already
 | 
			
		||||
*  written, the whole page must be copied to a buffer, the byte changed and
 | 
			
		||||
*  the manipulated buffer written after PageErase.
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
 | 
			
		||||
 | 
			
		||||
 *  Writes once data byte to flash on specified address. If a byte is already
 | 
			
		||||
 *  written, the whole page must be copied to a buffer, the byte changed and
 | 
			
		||||
 *  the manipulated buffer written after PageErase.
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
 | 
			
		||||
    FLASH_Status FlashStatus = FLASH_COMPLETE;
 | 
			
		||||
 | 
			
		||||
    uint32_t page;
 | 
			
		||||
    int i;
 | 
			
		||||
    int      i;
 | 
			
		||||
 | 
			
		||||
    // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages)
 | 
			
		||||
    if (Address > FEE_DENSITY_BYTES) {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,27 +76,25 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
 | 
			
		|||
    page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
    // if current data is 0xFF, the byte is empty, just overwrite with the new one
 | 
			
		||||
    if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
 | 
			
		||||
 | 
			
		||||
    if ((*(__IO uint16_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
 | 
			
		||||
        FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte));
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
        // Copy Page to a buffer
 | 
			
		||||
        memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page
 | 
			
		||||
        memcpy(DataBuf, (uint8_t *)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE);  // !!! Calculate base address for the desired page
 | 
			
		||||
 | 
			
		||||
        // check if new data is differ to current data, return if not, proceed if yes
 | 
			
		||||
        if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
 | 
			
		||||
        if (DataByte == *(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // manipulate desired data byte in temp data array if new byte is differ to the current
 | 
			
		||||
        DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte;
 | 
			
		||||
 | 
			
		||||
        //Erase Page
 | 
			
		||||
        // Erase Page
 | 
			
		||||
        FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE));
 | 
			
		||||
 | 
			
		||||
        // Write new data (whole page) to flash if data has been changed
 | 
			
		||||
        for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
 | 
			
		||||
        for (i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
 | 
			
		||||
            if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) {
 | 
			
		||||
                FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]));
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -107,98 +103,86 @@ uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
 | 
			
		|||
    return FlashStatus;
 | 
			
		||||
}
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
*  Read once data byte from a specified address.
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
uint8_t EEPROM_ReadDataByte (uint16_t Address) {
 | 
			
		||||
 | 
			
		||||
 *  Read once data byte from a specified address.
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
uint8_t EEPROM_ReadDataByte(uint16_t Address) {
 | 
			
		||||
    uint8_t DataByte = 0xFF;
 | 
			
		||||
 | 
			
		||||
    // Get Byte from specified address
 | 
			
		||||
    DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
 | 
			
		||||
    DataByte = (*(__IO uint8_t *)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
 | 
			
		||||
 | 
			
		||||
    return DataByte;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
*  Wrap library in AVR style functions.
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
uint8_t eeprom_read_byte (const uint8_t *Address)
 | 
			
		||||
{
 | 
			
		||||
    const uint16_t p = (const uint32_t) Address;
 | 
			
		||||
 *  Wrap library in AVR style functions.
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *Address) {
 | 
			
		||||
    const uint16_t p = (const uint32_t)Address;
 | 
			
		||||
    return EEPROM_ReadDataByte(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_byte (uint8_t *Address, uint8_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (uint32_t) Address;
 | 
			
		||||
void eeprom_write_byte(uint8_t *Address, uint8_t Value) {
 | 
			
		||||
    uint16_t p = (uint32_t)Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, Value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_byte (uint8_t *Address, uint8_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (uint32_t) Address;
 | 
			
		||||
void eeprom_update_byte(uint8_t *Address, uint8_t Value) {
 | 
			
		||||
    uint16_t p = (uint32_t)Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, Value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t eeprom_read_word (const uint16_t *Address)
 | 
			
		||||
{
 | 
			
		||||
    const uint16_t p = (const uint32_t) Address;
 | 
			
		||||
    return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8);
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *Address) {
 | 
			
		||||
    const uint16_t p = (const uint32_t)Address;
 | 
			
		||||
    return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_word (uint16_t *Address, uint16_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (uint32_t) Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t) Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
 | 
			
		||||
void eeprom_write_word(uint16_t *Address, uint16_t Value) {
 | 
			
		||||
    uint16_t p = (uint32_t)Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t)Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_word (uint16_t *Address, uint16_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (uint32_t) Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t) Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
 | 
			
		||||
void eeprom_update_word(uint16_t *Address, uint16_t Value) {
 | 
			
		||||
    uint16_t p = (uint32_t)Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t)Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t eeprom_read_dword (const uint32_t *Address)
 | 
			
		||||
{
 | 
			
		||||
    const uint16_t p = (const uint32_t) Address;
 | 
			
		||||
    return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
 | 
			
		||||
        | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *Address) {
 | 
			
		||||
    const uint16_t p = (const uint32_t)Address;
 | 
			
		||||
    return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_dword (uint32_t *Address, uint32_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (const uint32_t) Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t) Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
 | 
			
		||||
    EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
 | 
			
		||||
    EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
 | 
			
		||||
void eeprom_write_dword(uint32_t *Address, uint32_t Value) {
 | 
			
		||||
    uint16_t p = (const uint32_t)Address;
 | 
			
		||||
    EEPROM_WriteDataByte(p, (uint8_t)Value);
 | 
			
		||||
    EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
 | 
			
		||||
    EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16));
 | 
			
		||||
    EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_dword (uint32_t *Address, uint32_t Value)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t p = (const uint32_t) Address;
 | 
			
		||||
    uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
 | 
			
		||||
        | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
 | 
			
		||||
    if(Value != existingValue){
 | 
			
		||||
      EEPROM_WriteDataByte(p, (uint8_t) Value);
 | 
			
		||||
      EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
 | 
			
		||||
      EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
 | 
			
		||||
      EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
 | 
			
		||||
void eeprom_update_dword(uint32_t *Address, uint32_t Value) {
 | 
			
		||||
    uint16_t p             = (const uint32_t)Address;
 | 
			
		||||
    uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p + 1) << 8) | (EEPROM_ReadDataByte(p + 2) << 16) | (EEPROM_ReadDataByte(p + 3) << 24);
 | 
			
		||||
    if (Value != existingValue) {
 | 
			
		||||
        EEPROM_WriteDataByte(p, (uint8_t)Value);
 | 
			
		||||
        EEPROM_WriteDataByte(p + 1, (uint8_t)(Value >> 8));
 | 
			
		||||
        EEPROM_WriteDataByte(p + 2, (uint8_t)(Value >> 16));
 | 
			
		||||
        EEPROM_WriteDataByte(p + 3, (uint8_t)(Value >> 24));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
 | 
			
		||||
    const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
    uint8_t *dest = (uint8_t *)buf;
 | 
			
		||||
    const uint8_t *p    = (const uint8_t *)addr;
 | 
			
		||||
    uint8_t *      dest = (uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        *dest++ = eeprom_read_byte(p++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    uint8_t *      p   = (uint8_t *)addr;
 | 
			
		||||
    const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        eeprom_write_byte(p++, *src++);
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +190,7 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    uint8_t *      p   = (uint8_t *)addr;
 | 
			
		||||
    const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        eeprom_write_byte(p++, *src++);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										64
									
								
								tmk_core/common/chibios/eeprom_stm32.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										64
									
								
								tmk_core/common/chibios/eeprom_stm32.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							| 
						 | 
				
			
			@ -31,53 +31,53 @@
 | 
			
		|||
// HACK ALERT. This definition may not match your processor
 | 
			
		||||
// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
 | 
			
		||||
#if defined(EEPROM_EMU_STM32F303xC)
 | 
			
		||||
  #define MCU_STM32F303CC
 | 
			
		||||
#    define MCU_STM32F303CC
 | 
			
		||||
#elif defined(EEPROM_EMU_STM32F103xB)
 | 
			
		||||
  #define MCU_STM32F103RB
 | 
			
		||||
#    define MCU_STM32F103RB
 | 
			
		||||
#elif defined(EEPROM_EMU_STM32F072xB)
 | 
			
		||||
  #define MCU_STM32F072CB
 | 
			
		||||
#    define MCU_STM32F072CB
 | 
			
		||||
#else
 | 
			
		||||
  #error "not implemented."
 | 
			
		||||
#    error "not implemented."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEPROM_PAGE_SIZE
 | 
			
		||||
    #if defined (MCU_STM32F103RB)
 | 
			
		||||
        #define FEE_PAGE_SIZE    (uint16_t)0x400 // Page size = 1KByte
 | 
			
		||||
        #define FEE_DENSITY_PAGES          2     // How many pages are used
 | 
			
		||||
    #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) || defined(MCU_STM32F072CB)
 | 
			
		||||
        #define FEE_PAGE_SIZE    (uint16_t)0x800 // Page size = 2KByte
 | 
			
		||||
        #define FEE_DENSITY_PAGES          4     // How many pages are used
 | 
			
		||||
    #else
 | 
			
		||||
        #error  "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
 | 
			
		||||
    #endif
 | 
			
		||||
#    if defined(MCU_STM32F103RB)
 | 
			
		||||
#        define FEE_PAGE_SIZE (uint16_t)0x400  // Page size = 1KByte
 | 
			
		||||
#        define FEE_DENSITY_PAGES 2            // How many pages are used
 | 
			
		||||
#    elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB)
 | 
			
		||||
#        define FEE_PAGE_SIZE (uint16_t)0x800  // Page size = 2KByte
 | 
			
		||||
#        define FEE_DENSITY_PAGES 4            // How many pages are used
 | 
			
		||||
#    else
 | 
			
		||||
#        error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEPROM_START_ADDRESS
 | 
			
		||||
    #if defined (MCU_STM32F103RB) || defined(MCU_STM32F072CB)
 | 
			
		||||
        #define FEE_MCU_FLASH_SIZE  128     // Size in Kb
 | 
			
		||||
    #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE)
 | 
			
		||||
        #define FEE_MCU_FLASH_SIZE  512     // Size in Kb
 | 
			
		||||
    #elif defined (MCU_STM32F103RD)
 | 
			
		||||
        #define FEE_MCU_FLASH_SIZE  384     // Size in Kb
 | 
			
		||||
    #elif defined (MCU_STM32F303CC)
 | 
			
		||||
        #define FEE_MCU_FLASH_SIZE  256     // Size in Kb
 | 
			
		||||
    #else
 | 
			
		||||
        #error  "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
 | 
			
		||||
    #endif
 | 
			
		||||
#    if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB)
 | 
			
		||||
#        define FEE_MCU_FLASH_SIZE 128  // Size in Kb
 | 
			
		||||
#    elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE)
 | 
			
		||||
#        define FEE_MCU_FLASH_SIZE 512  // Size in Kb
 | 
			
		||||
#    elif defined(MCU_STM32F103RD)
 | 
			
		||||
#        define FEE_MCU_FLASH_SIZE 384  // Size in Kb
 | 
			
		||||
#    elif defined(MCU_STM32F303CC)
 | 
			
		||||
#        define FEE_MCU_FLASH_SIZE 256  // Size in Kb
 | 
			
		||||
#    else
 | 
			
		||||
#        error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// DONT CHANGE
 | 
			
		||||
// Choose location for the first EEPROM Page address on the top of flash
 | 
			
		||||
#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
 | 
			
		||||
#define FEE_DENSITY_BYTES       ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1)
 | 
			
		||||
#define FEE_LAST_PAGE_ADDRESS   (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
 | 
			
		||||
#define FEE_EMPTY_WORD          ((uint16_t)0xFFFF)
 | 
			
		||||
#define FEE_ADDR_OFFSET(Address)(Address * 2) // 1Byte per Word will be saved to preserve Flash
 | 
			
		||||
#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1)
 | 
			
		||||
#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
 | 
			
		||||
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
 | 
			
		||||
#define FEE_ADDR_OFFSET(Address) (Address * 2)  // 1Byte per Word will be saved to preserve Flash
 | 
			
		||||
 | 
			
		||||
// Use this function to initialize the functionality
 | 
			
		||||
uint16_t EEPROM_Init(void);
 | 
			
		||||
void EEPROM_Erase (void);
 | 
			
		||||
uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte);
 | 
			
		||||
uint8_t EEPROM_ReadDataByte (uint16_t Address);
 | 
			
		||||
void     EEPROM_Erase(void);
 | 
			
		||||
uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
 | 
			
		||||
uint8_t  EEPROM_ReadDataByte(uint16_t Address);
 | 
			
		||||
 | 
			
		||||
#endif  /* __EEPROM_H */
 | 
			
		||||
#endif /* __EEPROM_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,10 +21,10 @@
 | 
			
		|||
 * permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
 * the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. The above copyright notice and this permission notice shall be 
 | 
			
		||||
 * 1. The above copyright notice and this permission notice shall be
 | 
			
		||||
 * included in all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * 2. If the Software is incorporated into a build system that allows 
 | 
			
		||||
 * 2. If the Software is incorporated into a build system that allows
 | 
			
		||||
 * selection among a list of target devices, then similar target
 | 
			
		||||
 * devices manufactured by PJRC.COM must be included in the list of
 | 
			
		||||
 * target devices and selectable in the same manner.
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,6 @@
 | 
			
		|||
 * SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(K20x) /* chip selection */
 | 
			
		||||
/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +50,7 @@
 | 
			
		|||
// (aligned to 2 or 4 byte boundaries) has twice the endurance
 | 
			
		||||
// compared to writing 8 bit bytes.
 | 
			
		||||
//
 | 
			
		||||
#define EEPROM_SIZE 32
 | 
			
		||||
#    define EEPROM_SIZE 32
 | 
			
		||||
 | 
			
		||||
// Writing unaligned 16 or 32 bit data is handled automatically when
 | 
			
		||||
// this is defined, but at a cost of extra code size.  Without this,
 | 
			
		||||
| 
						 | 
				
			
			@ -59,286 +58,271 @@
 | 
			
		|||
// absolutely sure all 16 and 32 bit writes will be aligned, you can
 | 
			
		||||
// remove the extra unnecessary code.
 | 
			
		||||
//
 | 
			
		||||
#define HANDLE_UNALIGNED_WRITES
 | 
			
		||||
#    define HANDLE_UNALIGNED_WRITES
 | 
			
		||||
 | 
			
		||||
// Minimum EEPROM Endurance
 | 
			
		||||
// ------------------------
 | 
			
		||||
#if (EEPROM_SIZE == 2048)	// 35000 writes/byte or 70000 writes/word
 | 
			
		||||
  #define EEESIZE 0x33
 | 
			
		||||
#elif (EEPROM_SIZE == 1024)	// 75000 writes/byte or 150000 writes/word
 | 
			
		||||
  #define EEESIZE 0x34
 | 
			
		||||
#elif (EEPROM_SIZE == 512)	// 155000 writes/byte or 310000 writes/word
 | 
			
		||||
  #define EEESIZE 0x35
 | 
			
		||||
#elif (EEPROM_SIZE == 256)	// 315000 writes/byte or 630000 writes/word
 | 
			
		||||
  #define EEESIZE 0x36
 | 
			
		||||
#elif (EEPROM_SIZE == 128)	// 635000 writes/byte or 1270000 writes/word
 | 
			
		||||
  #define EEESIZE 0x37
 | 
			
		||||
#elif (EEPROM_SIZE == 64)	// 1275000 writes/byte or 2550000 writes/word
 | 
			
		||||
  #define EEESIZE 0x38
 | 
			
		||||
#elif (EEPROM_SIZE == 32)	// 2555000 writes/byte or 5110000 writes/word
 | 
			
		||||
  #define EEESIZE 0x39
 | 
			
		||||
#endif
 | 
			
		||||
#    if (EEPROM_SIZE == 2048)  // 35000 writes/byte or 70000 writes/word
 | 
			
		||||
#        define EEESIZE 0x33
 | 
			
		||||
#    elif (EEPROM_SIZE == 1024)  // 75000 writes/byte or 150000 writes/word
 | 
			
		||||
#        define EEESIZE 0x34
 | 
			
		||||
#    elif (EEPROM_SIZE == 512)  // 155000 writes/byte or 310000 writes/word
 | 
			
		||||
#        define EEESIZE 0x35
 | 
			
		||||
#    elif (EEPROM_SIZE == 256)  // 315000 writes/byte or 630000 writes/word
 | 
			
		||||
#        define EEESIZE 0x36
 | 
			
		||||
#    elif (EEPROM_SIZE == 128)  // 635000 writes/byte or 1270000 writes/word
 | 
			
		||||
#        define EEESIZE 0x37
 | 
			
		||||
#    elif (EEPROM_SIZE == 64)  // 1275000 writes/byte or 2550000 writes/word
 | 
			
		||||
#        define EEESIZE 0x38
 | 
			
		||||
#    elif (EEPROM_SIZE == 32)  // 2555000 writes/byte or 5110000 writes/word
 | 
			
		||||
#        define EEESIZE 0x39
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom initialization
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_initialize(void)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t count=0;
 | 
			
		||||
	uint16_t do_flash_cmd[] = {
 | 
			
		||||
		0xf06f, 0x037f, 0x7003, 0x7803,
 | 
			
		||||
		0xf013, 0x0f80, 0xd0fb, 0x4770};
 | 
			
		||||
	uint8_t status;
 | 
			
		||||
void eeprom_initialize(void) {
 | 
			
		||||
    uint32_t count          = 0;
 | 
			
		||||
    uint16_t do_flash_cmd[] = {0xf06f, 0x037f, 0x7003, 0x7803, 0xf013, 0x0f80, 0xd0fb, 0x4770};
 | 
			
		||||
    uint8_t  status;
 | 
			
		||||
 | 
			
		||||
	if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
 | 
			
		||||
		// FlexRAM is configured as traditional RAM
 | 
			
		||||
		// We need to reconfigure for EEPROM usage
 | 
			
		||||
		FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
 | 
			
		||||
		FTFL->FCCOB4 = EEESIZE; // EEPROM Size
 | 
			
		||||
		FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
 | 
			
		||||
		__disable_irq();
 | 
			
		||||
		// do_flash_cmd() must execute from RAM.  Luckily the C syntax is simple...
 | 
			
		||||
		(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
 | 
			
		||||
		__enable_irq();
 | 
			
		||||
		status = FTFL->FSTAT;
 | 
			
		||||
		if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
 | 
			
		||||
			FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
 | 
			
		||||
			return; // error
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// wait for eeprom to become ready (is this really necessary?)
 | 
			
		||||
	while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
 | 
			
		||||
		if (++count > 20000) break;
 | 
			
		||||
	}
 | 
			
		||||
    if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
 | 
			
		||||
        // FlexRAM is configured as traditional RAM
 | 
			
		||||
        // We need to reconfigure for EEPROM usage
 | 
			
		||||
        FTFL->FCCOB0 = 0x80;     // PGMPART = Program Partition Command
 | 
			
		||||
        FTFL->FCCOB4 = EEESIZE;  // EEPROM Size
 | 
			
		||||
        FTFL->FCCOB5 = 0x03;     // 0K for Dataflash, 32K for EEPROM backup
 | 
			
		||||
        __disable_irq();
 | 
			
		||||
        // do_flash_cmd() must execute from RAM.  Luckily the C syntax is simple...
 | 
			
		||||
        (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
 | 
			
		||||
        __enable_irq();
 | 
			
		||||
        status = FTFL->FSTAT;
 | 
			
		||||
        if (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL)) {
 | 
			
		||||
            FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL));
 | 
			
		||||
            return;  // error
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // wait for eeprom to become ready (is this really necessary?)
 | 
			
		||||
    while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
 | 
			
		||||
        if (++count > 20000) break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define FlexRAM ((uint8_t *)0x14000000)
 | 
			
		||||
#    define FlexRAM ((uint8_t *)0x14000000)
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom read byte
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	if (offset >= EEPROM_SIZE) return 0;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	return FlexRAM[offset];
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    if (offset >= EEPROM_SIZE) return 0;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    return FlexRAM[offset];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom read word
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	if (offset >= EEPROM_SIZE-1) return 0;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	return *(uint16_t *)(&FlexRAM[offset]);
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *addr) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    if (offset >= EEPROM_SIZE - 1) return 0;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    return *(uint16_t *)(&FlexRAM[offset]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom read dword
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	if (offset >= EEPROM_SIZE-3) return 0;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	return *(uint32_t *)(&FlexRAM[offset]);
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *addr) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    if (offset >= EEPROM_SIZE - 3) return 0;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    return *(uint32_t *)(&FlexRAM[offset]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom read block
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	uint8_t *dest = (uint8_t *)buf;
 | 
			
		||||
	uint32_t end = offset + len;
 | 
			
		||||
	
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	if (end > EEPROM_SIZE) end = EEPROM_SIZE;
 | 
			
		||||
	while (offset < end) {
 | 
			
		||||
		*dest++ = FlexRAM[offset++];
 | 
			
		||||
	}
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    uint8_t *dest   = (uint8_t *)buf;
 | 
			
		||||
    uint32_t end    = offset + len;
 | 
			
		||||
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    if (end > EEPROM_SIZE) end = EEPROM_SIZE;
 | 
			
		||||
    while (offset < end) {
 | 
			
		||||
        *dest++ = FlexRAM[offset++];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom is ready
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
int eeprom_is_ready(void)
 | 
			
		||||
{
 | 
			
		||||
	return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
int eeprom_is_ready(void) { return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0; }
 | 
			
		||||
 | 
			
		||||
/** \brief flexram wait
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
static void flexram_wait(void)
 | 
			
		||||
{
 | 
			
		||||
	while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
 | 
			
		||||
		// TODO: timeout
 | 
			
		||||
	}
 | 
			
		||||
static void flexram_wait(void) {
 | 
			
		||||
    while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
 | 
			
		||||
        // TODO: timeout
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom_write_byte
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_write_byte(uint8_t *addr, uint8_t value)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
 | 
			
		||||
	if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	if (FlexRAM[offset] != value) {
 | 
			
		||||
		FlexRAM[offset] = value;
 | 
			
		||||
		flexram_wait();
 | 
			
		||||
	}
 | 
			
		||||
    if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    if (FlexRAM[offset] != value) {
 | 
			
		||||
        FlexRAM[offset] = value;
 | 
			
		||||
        flexram_wait();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom write word
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_write_word(uint16_t *addr, uint16_t value)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
 | 
			
		||||
	if (offset >= EEPROM_SIZE-1) return;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
#ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
	if ((offset & 1) == 0) {
 | 
			
		||||
#endif
 | 
			
		||||
		if (*(uint16_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
			*(uint16_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
#ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
	} else {
 | 
			
		||||
		if (FlexRAM[offset] != value) {
 | 
			
		||||
			FlexRAM[offset] = value;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		if (FlexRAM[offset + 1] != (value >> 8)) {
 | 
			
		||||
			FlexRAM[offset + 1] = value >> 8;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
    if (offset >= EEPROM_SIZE - 1) return;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
#    ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
    if ((offset & 1) == 0) {
 | 
			
		||||
#    endif
 | 
			
		||||
        if (*(uint16_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
            *(uint16_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
            flexram_wait();
 | 
			
		||||
        }
 | 
			
		||||
#    ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
    } else {
 | 
			
		||||
        if (FlexRAM[offset] != value) {
 | 
			
		||||
            FlexRAM[offset] = value;
 | 
			
		||||
            flexram_wait();
 | 
			
		||||
        }
 | 
			
		||||
        if (FlexRAM[offset + 1] != (value >> 8)) {
 | 
			
		||||
            FlexRAM[offset + 1] = value >> 8;
 | 
			
		||||
            flexram_wait();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom write dword
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_write_dword(uint32_t *addr, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
 | 
			
		||||
	if (offset >= EEPROM_SIZE-3) return;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
#ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
	switch (offset & 3) {
 | 
			
		||||
	case 0:
 | 
			
		||||
#endif
 | 
			
		||||
		if (*(uint32_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
			*(uint32_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
#ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
	case 2:
 | 
			
		||||
		if (*(uint16_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
			*(uint16_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
 | 
			
		||||
			*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	default:
 | 
			
		||||
		if (FlexRAM[offset] != value) {
 | 
			
		||||
			FlexRAM[offset] = value;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
 | 
			
		||||
			*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
		if (FlexRAM[offset + 3] != (value >> 24)) {
 | 
			
		||||
			FlexRAM[offset + 3] = value >> 24;
 | 
			
		||||
			flexram_wait();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
    if (offset >= EEPROM_SIZE - 3) return;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
#    ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
    switch (offset & 3) {
 | 
			
		||||
        case 0:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (*(uint32_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
                *(uint32_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
#    ifdef HANDLE_UNALIGNED_WRITES
 | 
			
		||||
        case 2:
 | 
			
		||||
            if (*(uint16_t *)(&FlexRAM[offset]) != value) {
 | 
			
		||||
                *(uint16_t *)(&FlexRAM[offset]) = value;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
 | 
			
		||||
                *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        default:
 | 
			
		||||
            if (FlexRAM[offset] != value) {
 | 
			
		||||
                FlexRAM[offset] = value;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
 | 
			
		||||
                *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            if (FlexRAM[offset + 3] != (value >> 24)) {
 | 
			
		||||
                FlexRAM[offset + 3] = value >> 24;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeprom write block
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
    uint32_t       offset = (uint32_t)addr;
 | 
			
		||||
    const uint8_t *src    = (const uint8_t *)buf;
 | 
			
		||||
 | 
			
		||||
	if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
	if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
	if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
 | 
			
		||||
	if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
 | 
			
		||||
	while (len > 0) {
 | 
			
		||||
		uint32_t lsb = offset & 3;
 | 
			
		||||
		if (lsb == 0 && len >= 4) {
 | 
			
		||||
			// write aligned 32 bits
 | 
			
		||||
			uint32_t val32;
 | 
			
		||||
			val32 = *src++;
 | 
			
		||||
			val32 |= (*src++ << 8);
 | 
			
		||||
			val32 |= (*src++ << 16);
 | 
			
		||||
			val32 |= (*src++ << 24);
 | 
			
		||||
			if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
 | 
			
		||||
				*(uint32_t *)(&FlexRAM[offset]) = val32;
 | 
			
		||||
				flexram_wait();
 | 
			
		||||
			}
 | 
			
		||||
			offset += 4;
 | 
			
		||||
			len -= 4;
 | 
			
		||||
		} else if ((lsb == 0 || lsb == 2) && len >= 2) {
 | 
			
		||||
			// write aligned 16 bits
 | 
			
		||||
			uint16_t val16;
 | 
			
		||||
			val16 = *src++;
 | 
			
		||||
			val16 |= (*src++ << 8);
 | 
			
		||||
			if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
 | 
			
		||||
				*(uint16_t *)(&FlexRAM[offset]) = val16;
 | 
			
		||||
				flexram_wait();
 | 
			
		||||
			}
 | 
			
		||||
			offset += 2;
 | 
			
		||||
			len -= 2;
 | 
			
		||||
		} else {
 | 
			
		||||
			// write 8 bits
 | 
			
		||||
			uint8_t val8 = *src++;
 | 
			
		||||
			if (FlexRAM[offset] != val8) {
 | 
			
		||||
				FlexRAM[offset] = val8;
 | 
			
		||||
				flexram_wait();
 | 
			
		||||
			}
 | 
			
		||||
			offset++;
 | 
			
		||||
			len--;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
    if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
    if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
 | 
			
		||||
    if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
 | 
			
		||||
    if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
 | 
			
		||||
    while (len > 0) {
 | 
			
		||||
        uint32_t lsb = offset & 3;
 | 
			
		||||
        if (lsb == 0 && len >= 4) {
 | 
			
		||||
            // write aligned 32 bits
 | 
			
		||||
            uint32_t val32;
 | 
			
		||||
            val32 = *src++;
 | 
			
		||||
            val32 |= (*src++ << 8);
 | 
			
		||||
            val32 |= (*src++ << 16);
 | 
			
		||||
            val32 |= (*src++ << 24);
 | 
			
		||||
            if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
 | 
			
		||||
                *(uint32_t *)(&FlexRAM[offset]) = val32;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            offset += 4;
 | 
			
		||||
            len -= 4;
 | 
			
		||||
        } else if ((lsb == 0 || lsb == 2) && len >= 2) {
 | 
			
		||||
            // write aligned 16 bits
 | 
			
		||||
            uint16_t val16;
 | 
			
		||||
            val16 = *src++;
 | 
			
		||||
            val16 |= (*src++ << 8);
 | 
			
		||||
            if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
 | 
			
		||||
                *(uint16_t *)(&FlexRAM[offset]) = val16;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            offset += 2;
 | 
			
		||||
            len -= 2;
 | 
			
		||||
        } else {
 | 
			
		||||
            // write 8 bits
 | 
			
		||||
            uint8_t val8 = *src++;
 | 
			
		||||
            if (FlexRAM[offset] != val8) {
 | 
			
		||||
                FlexRAM[offset] = val8;
 | 
			
		||||
                flexram_wait();
 | 
			
		||||
            }
 | 
			
		||||
            offset++;
 | 
			
		||||
            len--;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
void do_flash_cmd(volatile uint8_t *fstat)
 | 
			
		||||
{
 | 
			
		||||
	*fstat = 0x80;
 | 
			
		||||
	while ((*fstat & 0x80) == 0) ; // wait
 | 
			
		||||
    *fstat = 0x80;
 | 
			
		||||
    while ((*fstat & 0x80) == 0) ; // wait
 | 
			
		||||
}
 | 
			
		||||
00000000 <do_flash_cmd>:
 | 
			
		||||
   0:	f06f 037f 	mvn.w	r3, #127	; 0x7f
 | 
			
		||||
| 
						 | 
				
			
			@ -352,128 +336,124 @@ void do_flash_cmd(volatile uint8_t *fstat)
 | 
			
		|||
#elif defined(KL2x) /* chip selection */
 | 
			
		||||
/* Teensy LC (emulated) */
 | 
			
		||||
 | 
			
		||||
#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
#    define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
 | 
			
		||||
 | 
			
		||||
extern uint32_t __eeprom_workarea_start__;
 | 
			
		||||
extern uint32_t __eeprom_workarea_end__;
 | 
			
		||||
 | 
			
		||||
#define EEPROM_SIZE 128
 | 
			
		||||
#    define EEPROM_SIZE 128
 | 
			
		||||
 | 
			
		||||
static uint32_t flashend = 0;
 | 
			
		||||
 | 
			
		||||
void eeprom_initialize(void)
 | 
			
		||||
{
 | 
			
		||||
	const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
void eeprom_initialize(void) {
 | 
			
		||||
    const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		if (*p++ == 0xFFFF) {
 | 
			
		||||
			flashend = (uint32_t)(p - 2);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	} while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
 | 
			
		||||
	flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
 | 
			
		||||
    do {
 | 
			
		||||
        if (*p++ == 0xFFFF) {
 | 
			
		||||
            flashend = (uint32_t)(p - 2);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
 | 
			
		||||
    flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
	const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
	uint16_t val;
 | 
			
		||||
	uint8_t data=0xFF;
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
 | 
			
		||||
    uint32_t        offset = (uint32_t)addr;
 | 
			
		||||
    const uint16_t *p      = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
    const uint16_t *end    = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
    uint16_t        val;
 | 
			
		||||
    uint8_t         data = 0xFF;
 | 
			
		||||
 | 
			
		||||
	if (!end) {
 | 
			
		||||
		eeprom_initialize();
 | 
			
		||||
		end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
	}
 | 
			
		||||
	if (offset < EEPROM_SIZE) {
 | 
			
		||||
		while (p <= end) {
 | 
			
		||||
			val = *p++;
 | 
			
		||||
			if ((val & 255) == offset) data = val >> 8;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return data;
 | 
			
		||||
    if (!end) {
 | 
			
		||||
        eeprom_initialize();
 | 
			
		||||
        end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
    }
 | 
			
		||||
    if (offset < EEPROM_SIZE) {
 | 
			
		||||
        while (p <= end) {
 | 
			
		||||
            val = *p++;
 | 
			
		||||
            if ((val & 255) == offset) data = val >> 8;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
	// with great power comes great responsibility....
 | 
			
		||||
	uint32_t stat;
 | 
			
		||||
	*(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
 | 
			
		||||
	*(uint32_t *)&(FTFA->FCCOB7) = data;
 | 
			
		||||
	__disable_irq();
 | 
			
		||||
	(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
 | 
			
		||||
	__enable_irq();
 | 
			
		||||
	stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
 | 
			
		||||
	if (stat) {
 | 
			
		||||
		FTFA->FSTAT = stat;
 | 
			
		||||
	}
 | 
			
		||||
	MCM->PLACR |= MCM_PLACR_CFCC;
 | 
			
		||||
static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data) {
 | 
			
		||||
    // with great power comes great responsibility....
 | 
			
		||||
    uint32_t stat;
 | 
			
		||||
    *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
 | 
			
		||||
    *(uint32_t *)&(FTFA->FCCOB7) = data;
 | 
			
		||||
    __disable_irq();
 | 
			
		||||
    (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
 | 
			
		||||
    __enable_irq();
 | 
			
		||||
    stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL);
 | 
			
		||||
    if (stat) {
 | 
			
		||||
        FTFA->FSTAT = stat;
 | 
			
		||||
    }
 | 
			
		||||
    MCM->PLACR |= MCM_PLACR_CFCC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_byte(uint8_t *addr, uint8_t data)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
	uint32_t i, val, flashaddr;
 | 
			
		||||
	uint16_t do_flash_cmd[] = {
 | 
			
		||||
		0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
 | 
			
		||||
	uint8_t buf[EEPROM_SIZE];
 | 
			
		||||
void eeprom_write_byte(uint8_t *addr, uint8_t data) {
 | 
			
		||||
    uint32_t        offset = (uint32_t)addr;
 | 
			
		||||
    const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
    uint32_t        i, val, flashaddr;
 | 
			
		||||
    uint16_t        do_flash_cmd[] = {0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
 | 
			
		||||
    uint8_t         buf[EEPROM_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
	if (!end) {
 | 
			
		||||
		eeprom_initialize();
 | 
			
		||||
		end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
	}
 | 
			
		||||
	if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
 | 
			
		||||
		val = (data << 8) | offset;
 | 
			
		||||
		flashaddr = (uint32_t)end;
 | 
			
		||||
		flashend = flashaddr;
 | 
			
		||||
		if ((flashaddr & 2) == 0) {
 | 
			
		||||
			val |= 0xFFFF0000;
 | 
			
		||||
		} else {
 | 
			
		||||
			val <<= 16;
 | 
			
		||||
			val |= 0x0000FFFF;
 | 
			
		||||
		}
 | 
			
		||||
		flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
	} else {
 | 
			
		||||
		for (i=0; i < EEPROM_SIZE; i++) {
 | 
			
		||||
			buf[i] = 0xFF;
 | 
			
		||||
		}
 | 
			
		||||
		val = 0;
 | 
			
		||||
		for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
 | 
			
		||||
			val = *p;
 | 
			
		||||
			if ((val & 255) < EEPROM_SIZE) {
 | 
			
		||||
				buf[val & 255] = val >> 8;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		buf[offset] = data;
 | 
			
		||||
		for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
 | 
			
		||||
			*(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
 | 
			
		||||
			__disable_irq();
 | 
			
		||||
			(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
 | 
			
		||||
			__enable_irq();
 | 
			
		||||
			val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
 | 
			
		||||
			if (val) FTFA->FSTAT = val;
 | 
			
		||||
			MCM->PLACR |= MCM_PLACR_CFCC;
 | 
			
		||||
		}
 | 
			
		||||
		flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
		for (i=0; i < EEPROM_SIZE; i++) {
 | 
			
		||||
			if (buf[i] == 0xFF) continue;
 | 
			
		||||
			if ((flashaddr & 2) == 0) {
 | 
			
		||||
				val = (buf[i] << 8) | i;
 | 
			
		||||
			} else {
 | 
			
		||||
				val = val | (buf[i] << 24) | (i << 16);
 | 
			
		||||
				flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
			}
 | 
			
		||||
			flashaddr += 2;
 | 
			
		||||
		}
 | 
			
		||||
		flashend = flashaddr;
 | 
			
		||||
		if ((flashaddr & 2)) {
 | 
			
		||||
			val |= 0xFFFF0000;
 | 
			
		||||
			flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
    if (offset >= EEPROM_SIZE) return;
 | 
			
		||||
    if (!end) {
 | 
			
		||||
        eeprom_initialize();
 | 
			
		||||
        end = (const uint16_t *)((uint32_t)flashend);
 | 
			
		||||
    }
 | 
			
		||||
    if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
 | 
			
		||||
        val       = (data << 8) | offset;
 | 
			
		||||
        flashaddr = (uint32_t)end;
 | 
			
		||||
        flashend  = flashaddr;
 | 
			
		||||
        if ((flashaddr & 2) == 0) {
 | 
			
		||||
            val |= 0xFFFF0000;
 | 
			
		||||
        } else {
 | 
			
		||||
            val <<= 16;
 | 
			
		||||
            val |= 0x0000FFFF;
 | 
			
		||||
        }
 | 
			
		||||
        flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
    } else {
 | 
			
		||||
        for (i = 0; i < EEPROM_SIZE; i++) {
 | 
			
		||||
            buf[i] = 0xFF;
 | 
			
		||||
        }
 | 
			
		||||
        val = 0;
 | 
			
		||||
        for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
 | 
			
		||||
            val = *p;
 | 
			
		||||
            if ((val & 255) < EEPROM_SIZE) {
 | 
			
		||||
                buf[val & 255] = val >> 8;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        buf[offset] = data;
 | 
			
		||||
        for (flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
 | 
			
		||||
            *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
 | 
			
		||||
            __disable_irq();
 | 
			
		||||
            (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
 | 
			
		||||
            __enable_irq();
 | 
			
		||||
            val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR | FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL);
 | 
			
		||||
            ;
 | 
			
		||||
            if (val) FTFA->FSTAT = val;
 | 
			
		||||
            MCM->PLACR |= MCM_PLACR_CFCC;
 | 
			
		||||
        }
 | 
			
		||||
        flashaddr = (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
 | 
			
		||||
        for (i = 0; i < EEPROM_SIZE; i++) {
 | 
			
		||||
            if (buf[i] == 0xFF) continue;
 | 
			
		||||
            if ((flashaddr & 2) == 0) {
 | 
			
		||||
                val = (buf[i] << 8) | i;
 | 
			
		||||
            } else {
 | 
			
		||||
                val = val | (buf[i] << 24) | (i << 16);
 | 
			
		||||
                flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
            }
 | 
			
		||||
            flashaddr += 2;
 | 
			
		||||
        }
 | 
			
		||||
        flashend = flashaddr;
 | 
			
		||||
        if ((flashaddr & 2)) {
 | 
			
		||||
            val |= 0xFFFF0000;
 | 
			
		||||
            flash_write(do_flash_cmd, flashaddr, val);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -492,141 +472,127 @@ void do_flash_cmd(volatile uint8_t *fstat)
 | 
			
		|||
   c:	4770      	bx	lr
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *addr) {
 | 
			
		||||
    const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
    return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *addr)
 | 
			
		||||
{
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
 | 
			
		||||
		| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *addr) {
 | 
			
		||||
    const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
    return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	uint8_t *dest = (uint8_t *)buf;
 | 
			
		||||
	while (len--) {
 | 
			
		||||
		*dest++ = eeprom_read_byte(p++);
 | 
			
		||||
	}
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
 | 
			
		||||
    const uint8_t *p    = (const uint8_t *)addr;
 | 
			
		||||
    uint8_t *      dest = (uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        *dest++ = eeprom_read_byte(p++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int eeprom_is_ready(void)
 | 
			
		||||
{
 | 
			
		||||
	return 1;
 | 
			
		||||
int eeprom_is_ready(void) { return 1; }
 | 
			
		||||
 | 
			
		||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p, value >> 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_word(uint16_t *addr, uint16_t value)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p, value >> 8);
 | 
			
		||||
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
    eeprom_write_byte(p, value >> 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_dword(uint32_t *addr, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
	eeprom_write_byte(p, value >> 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
	while (len--) {
 | 
			
		||||
		eeprom_write_byte(p++, *src++);
 | 
			
		||||
	}
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
    uint8_t *      p   = (uint8_t *)addr;
 | 
			
		||||
    const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        eeprom_write_byte(p++, *src++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
// No EEPROM supported, so emulate it
 | 
			
		||||
 | 
			
		||||
#define EEPROM_SIZE 32
 | 
			
		||||
#    define EEPROM_SIZE 32
 | 
			
		||||
static uint8_t buffer[EEPROM_SIZE];
 | 
			
		||||
 | 
			
		||||
uint8_t eeprom_read_byte(const uint8_t *addr) {
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	return buffer[offset];
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    return buffer[offset];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_byte(uint8_t *addr, uint8_t value) {
 | 
			
		||||
	uint32_t offset = (uint32_t)addr;
 | 
			
		||||
	buffer[offset] = value;
 | 
			
		||||
    uint32_t offset = (uint32_t)addr;
 | 
			
		||||
    buffer[offset]  = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t eeprom_read_word(const uint16_t *addr) {
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
 | 
			
		||||
    const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
    return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t eeprom_read_dword(const uint32_t *addr) {
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
 | 
			
		||||
		| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
 | 
			
		||||
    const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
    return eeprom_read_byte(p) | (eeprom_read_byte(p + 1) << 8) | (eeprom_read_byte(p + 2) << 16) | (eeprom_read_byte(p + 3) << 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
 | 
			
		||||
	const uint8_t *p = (const uint8_t *)addr;
 | 
			
		||||
	uint8_t *dest = (uint8_t *)buf;
 | 
			
		||||
	while (len--) {
 | 
			
		||||
		*dest++ = eeprom_read_byte(p++);
 | 
			
		||||
	}
 | 
			
		||||
    const uint8_t *p    = (const uint8_t *)addr;
 | 
			
		||||
    uint8_t *      dest = (uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        *dest++ = eeprom_read_byte(p++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_word(uint16_t *addr, uint16_t value) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p, value >> 8);
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p, value >> 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_dword(uint32_t *addr, uint32_t value) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
	eeprom_write_byte(p, value >> 24);
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
    eeprom_write_byte(p, value >> 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
	while (len--) {
 | 
			
		||||
		eeprom_write_byte(p++, *src++);
 | 
			
		||||
	}
 | 
			
		||||
    uint8_t *      p   = (uint8_t *)addr;
 | 
			
		||||
    const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        eeprom_write_byte(p++, *src++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* chip selection */
 | 
			
		||||
// The update functions just calls write for now, but could probably be optimized
 | 
			
		||||
 | 
			
		||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) {
 | 
			
		||||
	eeprom_write_byte(addr, value);
 | 
			
		||||
}
 | 
			
		||||
void eeprom_update_byte(uint8_t *addr, uint8_t value) { eeprom_write_byte(addr, value); }
 | 
			
		||||
 | 
			
		||||
void eeprom_update_word(uint16_t *addr, uint16_t value) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p, value >> 8);
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p, value >> 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_dword(uint32_t *addr, uint32_t value) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	eeprom_write_byte(p++, value);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
	eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
	eeprom_write_byte(p, value >> 24);
 | 
			
		||||
    uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
    eeprom_write_byte(p++, value);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 8);
 | 
			
		||||
    eeprom_write_byte(p++, value >> 16);
 | 
			
		||||
    eeprom_write_byte(p, value >> 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
 | 
			
		||||
	uint8_t *p = (uint8_t *)addr;
 | 
			
		||||
	const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
	while (len--) {
 | 
			
		||||
		eeprom_write_byte(p++, *src++);
 | 
			
		||||
	}
 | 
			
		||||
    uint8_t *      p   = (uint8_t *)addr;
 | 
			
		||||
    const uint8_t *src = (const uint8_t *)buf;
 | 
			
		||||
    while (len--) {
 | 
			
		||||
        eeprom_write_byte(p++, *src++);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										162
									
								
								tmk_core/common/chibios/flash_stm32.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										162
									
								
								tmk_core/common/chibios/flash_stm32.c
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							| 
						 | 
				
			
			@ -17,105 +17,95 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(EEPROM_EMU_STM32F303xC)
 | 
			
		||||
    #define STM32F303xC
 | 
			
		||||
    #include "stm32f3xx.h"
 | 
			
		||||
#    define STM32F303xC
 | 
			
		||||
#    include "stm32f3xx.h"
 | 
			
		||||
#elif defined(EEPROM_EMU_STM32F103xB)
 | 
			
		||||
    #define STM32F103xB
 | 
			
		||||
    #include "stm32f1xx.h"
 | 
			
		||||
#    define STM32F103xB
 | 
			
		||||
#    include "stm32f1xx.h"
 | 
			
		||||
#elif defined(EEPROM_EMU_STM32F072xB)
 | 
			
		||||
    #define STM32F072xB
 | 
			
		||||
    #include "stm32f0xx.h"
 | 
			
		||||
#    define STM32F072xB
 | 
			
		||||
#    include "stm32f0xx.h"
 | 
			
		||||
#else
 | 
			
		||||
    #error "not implemented."
 | 
			
		||||
#    error "not implemented."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "flash_stm32.h"
 | 
			
		||||
 | 
			
		||||
#if defined(EEPROM_EMU_STM32F103xB)
 | 
			
		||||
    #define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
 | 
			
		||||
#    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Delay definition */
 | 
			
		||||
#define EraseTimeout        ((uint32_t)0x00000FFF)
 | 
			
		||||
#define ProgramTimeout      ((uint32_t)0x0000001F)
 | 
			
		||||
#define EraseTimeout ((uint32_t)0x00000FFF)
 | 
			
		||||
#define ProgramTimeout ((uint32_t)0x0000001F)
 | 
			
		||||
 | 
			
		||||
#define ASSERT(exp) (void)((0))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Inserts a time delay.
 | 
			
		||||
  * @param  None
 | 
			
		||||
  * @retval None
 | 
			
		||||
  */
 | 
			
		||||
static void delay(void)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Inserts a time delay.
 | 
			
		||||
 * @param  None
 | 
			
		||||
 * @retval None
 | 
			
		||||
 */
 | 
			
		||||
static void delay(void) {
 | 
			
		||||
    __IO uint32_t i = 0;
 | 
			
		||||
    for(i = 0xFF; i != 0; i--) { }
 | 
			
		||||
    for (i = 0xFF; i != 0; i--) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Returns the FLASH Status.
 | 
			
		||||
  * @param  None
 | 
			
		||||
  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
 | 
			
		||||
  *   FLASH_ERROR_WRP or FLASH_COMPLETE
 | 
			
		||||
  */
 | 
			
		||||
FLASH_Status FLASH_GetStatus(void)
 | 
			
		||||
{
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
 | 
			
		||||
        return FLASH_BUSY;
 | 
			
		||||
 * @brief  Returns the FLASH Status.
 | 
			
		||||
 * @param  None
 | 
			
		||||
 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
 | 
			
		||||
 *   FLASH_ERROR_WRP or FLASH_COMPLETE
 | 
			
		||||
 */
 | 
			
		||||
FLASH_Status FLASH_GetStatus(void) {
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) return FLASH_BUSY;
 | 
			
		||||
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_PGERR) != 0)
 | 
			
		||||
        return FLASH_ERROR_PG;
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_PGERR) != 0) return FLASH_ERROR_PG;
 | 
			
		||||
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
 | 
			
		||||
        return FLASH_ERROR_WRP;
 | 
			
		||||
    if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
 | 
			
		||||
 | 
			
		||||
    if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 )
 | 
			
		||||
        return FLASH_ERROR_OPT;
 | 
			
		||||
    if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
 | 
			
		||||
 | 
			
		||||
    return FLASH_COMPLETE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Waits for a Flash operation to complete or a TIMEOUT to occur.
 | 
			
		||||
  * @param  Timeout: FLASH progamming Timeout
 | 
			
		||||
  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
 | 
			
		||||
  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
  */
 | 
			
		||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Waits for a Flash operation to complete or a TIMEOUT to occur.
 | 
			
		||||
 * @param  Timeout: FLASH progamming Timeout
 | 
			
		||||
 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
 | 
			
		||||
 *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
 */
 | 
			
		||||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
 | 
			
		||||
    FLASH_Status status;
 | 
			
		||||
 | 
			
		||||
    /* Check for the Flash Status */
 | 
			
		||||
    status = FLASH_GetStatus();
 | 
			
		||||
    /* Wait for a Flash operation to complete or a TIMEOUT to occur */
 | 
			
		||||
    while ((status == FLASH_BUSY) && (Timeout != 0x00))
 | 
			
		||||
    {
 | 
			
		||||
    while ((status == FLASH_BUSY) && (Timeout != 0x00)) {
 | 
			
		||||
        delay();
 | 
			
		||||
        status = FLASH_GetStatus();
 | 
			
		||||
        Timeout--;
 | 
			
		||||
    }
 | 
			
		||||
    if (Timeout == 0)
 | 
			
		||||
        status = FLASH_TIMEOUT;
 | 
			
		||||
    if (Timeout == 0) status = FLASH_TIMEOUT;
 | 
			
		||||
    /* Return the operation status */
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Erases a specified FLASH page.
 | 
			
		||||
  * @param  Page_Address: The page address to be erased.
 | 
			
		||||
  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
 | 
			
		||||
  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
  */
 | 
			
		||||
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Erases a specified FLASH page.
 | 
			
		||||
 * @param  Page_Address: The page address to be erased.
 | 
			
		||||
 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
 | 
			
		||||
 *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
 */
 | 
			
		||||
FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
 | 
			
		||||
    FLASH_Status status = FLASH_COMPLETE;
 | 
			
		||||
    /* Check the parameters */
 | 
			
		||||
    ASSERT(IS_FLASH_ADDRESS(Page_Address));
 | 
			
		||||
    /* Wait for last operation to be completed */
 | 
			
		||||
    status = FLASH_WaitForLastOperation(EraseTimeout);
 | 
			
		||||
 | 
			
		||||
    if(status == FLASH_COMPLETE)
 | 
			
		||||
    {
 | 
			
		||||
    if (status == FLASH_COMPLETE) {
 | 
			
		||||
        /* if the previous operation is completed, proceed to erase the page */
 | 
			
		||||
        FLASH->CR |= FLASH_CR_PER;
 | 
			
		||||
        FLASH->AR = Page_Address;
 | 
			
		||||
| 
						 | 
				
			
			@ -123,8 +113,7 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
 | 
			
		|||
 | 
			
		||||
        /* Wait for last operation to be completed */
 | 
			
		||||
        status = FLASH_WaitForLastOperation(EraseTimeout);
 | 
			
		||||
        if(status != FLASH_TIMEOUT)
 | 
			
		||||
        {
 | 
			
		||||
        if (status != FLASH_TIMEOUT) {
 | 
			
		||||
            /* if the erase operation is completed, disable the PER Bit */
 | 
			
		||||
            FLASH->CR &= ~FLASH_CR_PER;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -135,29 +124,25 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Programs a half word at a specified address.
 | 
			
		||||
  * @param  Address: specifies the address to be programmed.
 | 
			
		||||
  * @param  Data: specifies the data to be programmed.
 | 
			
		||||
  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
 | 
			
		||||
  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
  */
 | 
			
		||||
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Programs a half word at a specified address.
 | 
			
		||||
 * @param  Address: specifies the address to be programmed.
 | 
			
		||||
 * @param  Data: specifies the data to be programmed.
 | 
			
		||||
 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
 | 
			
		||||
 *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
 | 
			
		||||
 */
 | 
			
		||||
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
 | 
			
		||||
    FLASH_Status status = FLASH_BAD_ADDRESS;
 | 
			
		||||
 | 
			
		||||
    if (IS_FLASH_ADDRESS(Address))
 | 
			
		||||
    {
 | 
			
		||||
    if (IS_FLASH_ADDRESS(Address)) {
 | 
			
		||||
        /* Wait for last operation to be completed */
 | 
			
		||||
        status = FLASH_WaitForLastOperation(ProgramTimeout);
 | 
			
		||||
        if(status == FLASH_COMPLETE)
 | 
			
		||||
        {
 | 
			
		||||
        if (status == FLASH_COMPLETE) {
 | 
			
		||||
            /* if the previous operation is completed, proceed to program the new data */
 | 
			
		||||
            FLASH->CR |= FLASH_CR_PG;
 | 
			
		||||
            *(__IO uint16_t*)Address = Data;
 | 
			
		||||
            /* Wait for last operation to be completed */
 | 
			
		||||
            status = FLASH_WaitForLastOperation(ProgramTimeout);
 | 
			
		||||
            if(status != FLASH_TIMEOUT)
 | 
			
		||||
            {
 | 
			
		||||
            if (status != FLASH_TIMEOUT) {
 | 
			
		||||
                /* if the program operation is completed, disable the PG Bit */
 | 
			
		||||
                FLASH->CR &= ~FLASH_CR_PG;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -168,39 +153,36 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Unlocks the FLASH Program Erase Controller.
 | 
			
		||||
  * @param  None
 | 
			
		||||
  * @retval None
 | 
			
		||||
  */
 | 
			
		||||
void FLASH_Unlock(void)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Unlocks the FLASH Program Erase Controller.
 | 
			
		||||
 * @param  None
 | 
			
		||||
 * @retval None
 | 
			
		||||
 */
 | 
			
		||||
void FLASH_Unlock(void) {
 | 
			
		||||
    /* Authorize the FPEC Access */
 | 
			
		||||
    FLASH->KEYR = FLASH_KEY1;
 | 
			
		||||
    FLASH->KEYR = FLASH_KEY2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Locks the FLASH Program Erase Controller.
 | 
			
		||||
  * @param  None
 | 
			
		||||
  * @retval None
 | 
			
		||||
  */
 | 
			
		||||
void FLASH_Lock(void)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Locks the FLASH Program Erase Controller.
 | 
			
		||||
 * @param  None
 | 
			
		||||
 * @retval None
 | 
			
		||||
 */
 | 
			
		||||
void FLASH_Lock(void) {
 | 
			
		||||
    /* Set the Lock Bit to lock the FPEC and the FCR */
 | 
			
		||||
    FLASH->CR |= FLASH_CR_LOCK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief  Clears the FLASH's pending flags.
 | 
			
		||||
  * @param  FLASH_FLAG: specifies the FLASH flags to clear.
 | 
			
		||||
  *   This parameter can be any combination of the following values:
 | 
			
		||||
  *     @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag
 | 
			
		||||
  *     @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag
 | 
			
		||||
  *     @arg FLASH_FLAG_EOP: FLASH End of Programming flag
 | 
			
		||||
  * @retval None
 | 
			
		||||
  */
 | 
			
		||||
void FLASH_ClearFlag(uint32_t FLASH_FLAG)
 | 
			
		||||
{
 | 
			
		||||
 * @brief  Clears the FLASH's pending flags.
 | 
			
		||||
 * @param  FLASH_FLAG: specifies the FLASH flags to clear.
 | 
			
		||||
 *   This parameter can be any combination of the following values:
 | 
			
		||||
 *     @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag
 | 
			
		||||
 *     @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag
 | 
			
		||||
 *     @arg FLASH_FLAG_EOP: FLASH End of Programming flag
 | 
			
		||||
 * @retval None
 | 
			
		||||
 */
 | 
			
		||||
void FLASH_ClearFlag(uint32_t FLASH_FLAG) {
 | 
			
		||||
    /* Clear the flags */
 | 
			
		||||
    FLASH->SR = FLASH_FLAG;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								tmk_core/common/chibios/flash_stm32.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										15
									
								
								tmk_core/common/chibios/flash_stm32.h
									
										
									
									
									
										
										
										Executable file → Normal file
									
								
							| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | 
			
		||||
 * DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and 
 | 
			
		||||
 * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
 | 
			
		||||
 * https://github.com/leaflabs/libmaple
 | 
			
		||||
 *
 | 
			
		||||
 * Modifications for QMK and STM32F303 by Yiancar
 | 
			
		||||
| 
						 | 
				
			
			@ -20,22 +20,13 @@
 | 
			
		|||
#define __FLASH_STM32_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "ch.h"
 | 
			
		||||
#include "hal.h"
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
    {
 | 
			
		||||
    FLASH_BUSY = 1,
 | 
			
		||||
    FLASH_ERROR_PG,
 | 
			
		||||
    FLASH_ERROR_WRP,
 | 
			
		||||
    FLASH_ERROR_OPT,
 | 
			
		||||
    FLASH_COMPLETE,
 | 
			
		||||
    FLASH_TIMEOUT,
 | 
			
		||||
    FLASH_BAD_ADDRESS
 | 
			
		||||
    } FLASH_Status;
 | 
			
		||||
typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT, FLASH_COMPLETE, FLASH_TIMEOUT, FLASH_BAD_ADDRESS } FLASH_Status;
 | 
			
		||||
 | 
			
		||||
#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		|||
 | 
			
		||||
#include "printf.h"
 | 
			
		||||
 | 
			
		||||
typedef void (*putcf) (void*,char);
 | 
			
		||||
typedef void (*putcf)(void*, char);
 | 
			
		||||
static putcf stdout_putf;
 | 
			
		||||
static void* stdout_putp;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,206 +35,185 @@ static void* stdout_putp;
 | 
			
		|||
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
 | 
			
		||||
static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
 | 
			
		||||
    {
 | 
			
		||||
    int n=0;
 | 
			
		||||
    unsigned int d=1;
 | 
			
		||||
    while (num/d >= base)
 | 
			
		||||
        d*=base;         
 | 
			
		||||
    while (d!=0) {
 | 
			
		||||
static void uli2a(unsigned long int num, unsigned int base, int uc, char* bf) {
 | 
			
		||||
    int          n = 0;
 | 
			
		||||
    unsigned int d = 1;
 | 
			
		||||
    while (num / d >= base) d *= base;
 | 
			
		||||
    while (d != 0) {
 | 
			
		||||
        int dgt = num / d;
 | 
			
		||||
        num%=d;
 | 
			
		||||
        d/=base;
 | 
			
		||||
        if (n || dgt>0|| d==0) {
 | 
			
		||||
            *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
 | 
			
		||||
        num %= d;
 | 
			
		||||
        d /= base;
 | 
			
		||||
        if (n || dgt > 0 || d == 0) {
 | 
			
		||||
            *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
 | 
			
		||||
            ++n;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    *bf=0;
 | 
			
		||||
    }
 | 
			
		||||
    *bf = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void li2a (long num, char * bf)
 | 
			
		||||
    {
 | 
			
		||||
    if (num<0) {
 | 
			
		||||
        num=-num;
 | 
			
		||||
static void li2a(long num, char* bf) {
 | 
			
		||||
    if (num < 0) {
 | 
			
		||||
        num   = -num;
 | 
			
		||||
        *bf++ = '-';
 | 
			
		||||
        }
 | 
			
		||||
    uli2a(num,10,0,bf);
 | 
			
		||||
    }
 | 
			
		||||
    uli2a(num, 10, 0, bf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
 | 
			
		||||
    {
 | 
			
		||||
    int n=0;
 | 
			
		||||
    unsigned int d=1;
 | 
			
		||||
    while (num/d >= base)
 | 
			
		||||
        d*=base;        
 | 
			
		||||
    while (d!=0) {
 | 
			
		||||
static void ui2a(unsigned int num, unsigned int base, int uc, char* bf) {
 | 
			
		||||
    int          n = 0;
 | 
			
		||||
    unsigned int d = 1;
 | 
			
		||||
    while (num / d >= base) d *= base;
 | 
			
		||||
    while (d != 0) {
 | 
			
		||||
        int dgt = num / d;
 | 
			
		||||
        num%= d;
 | 
			
		||||
        d/=base;
 | 
			
		||||
        if (n || dgt>0 || d==0) {
 | 
			
		||||
            *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
 | 
			
		||||
        num %= d;
 | 
			
		||||
        d /= base;
 | 
			
		||||
        if (n || dgt > 0 || d == 0) {
 | 
			
		||||
            *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
 | 
			
		||||
            ++n;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    *bf=0;
 | 
			
		||||
    }
 | 
			
		||||
    *bf = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void i2a (int num, char * bf)
 | 
			
		||||
    {
 | 
			
		||||
    if (num<0) {
 | 
			
		||||
        num=-num;
 | 
			
		||||
static void i2a(int num, char* bf) {
 | 
			
		||||
    if (num < 0) {
 | 
			
		||||
        num   = -num;
 | 
			
		||||
        *bf++ = '-';
 | 
			
		||||
        }
 | 
			
		||||
    ui2a(num,10,0,bf);
 | 
			
		||||
    }
 | 
			
		||||
    ui2a(num, 10, 0, bf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int a2d(char ch)
 | 
			
		||||
    {
 | 
			
		||||
    if (ch>='0' && ch<='9') 
 | 
			
		||||
        return ch-'0';
 | 
			
		||||
    else if (ch>='a' && ch<='f')
 | 
			
		||||
        return ch-'a'+10;
 | 
			
		||||
    else if (ch>='A' && ch<='F')
 | 
			
		||||
        return ch-'A'+10;
 | 
			
		||||
    else return -1;
 | 
			
		||||
static int a2d(char ch) {
 | 
			
		||||
    if (ch >= '0' && ch <= '9')
 | 
			
		||||
        return ch - '0';
 | 
			
		||||
    else if (ch >= 'a' && ch <= 'f')
 | 
			
		||||
        return ch - 'a' + 10;
 | 
			
		||||
    else if (ch >= 'A' && ch <= 'F')
 | 
			
		||||
        return ch - 'A' + 10;
 | 
			
		||||
    else
 | 
			
		||||
        return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char a2i(char ch, char** src, int base, int* nump) {
 | 
			
		||||
    char* p   = *src;
 | 
			
		||||
    int   num = 0;
 | 
			
		||||
    int   digit;
 | 
			
		||||
    while ((digit = a2d(ch)) >= 0) {
 | 
			
		||||
        if (digit > base) break;
 | 
			
		||||
        num = num * base + digit;
 | 
			
		||||
        ch  = *p++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
static char a2i(char ch, char** src,int base,int* nump)
 | 
			
		||||
    {
 | 
			
		||||
    char* p= *src;
 | 
			
		||||
    int num=0;
 | 
			
		||||
    int digit;
 | 
			
		||||
    while ((digit=a2d(ch))>=0) {
 | 
			
		||||
        if (digit>base) break;
 | 
			
		||||
        num=num*base+digit;
 | 
			
		||||
        ch=*p++;
 | 
			
		||||
        }
 | 
			
		||||
    *src=p;
 | 
			
		||||
    *nump=num;
 | 
			
		||||
    *src  = p;
 | 
			
		||||
    *nump = num;
 | 
			
		||||
    return ch;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void putchw(void* putp,putcf putf,int n, char z, char* bf)
 | 
			
		||||
    {
 | 
			
		||||
    char fc=z? '0' : ' ';
 | 
			
		||||
    char ch;
 | 
			
		||||
    char* p=bf;
 | 
			
		||||
    while (*p++ && n > 0)
 | 
			
		||||
        n--;
 | 
			
		||||
    while (n-- > 0) 
 | 
			
		||||
        putf(putp,fc);
 | 
			
		||||
    while ((ch= *bf++))
 | 
			
		||||
        putf(putp,ch);
 | 
			
		||||
    }
 | 
			
		||||
static void putchw(void* putp, putcf putf, int n, char z, char* bf) {
 | 
			
		||||
    char  fc = z ? '0' : ' ';
 | 
			
		||||
    char  ch;
 | 
			
		||||
    char* p = bf;
 | 
			
		||||
    while (*p++ && n > 0) n--;
 | 
			
		||||
    while (n-- > 0) putf(putp, fc);
 | 
			
		||||
    while ((ch = *bf++)) putf(putp, ch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
 | 
			
		||||
    {
 | 
			
		||||
void tfp_format(void* putp, putcf putf, char* fmt, va_list va) {
 | 
			
		||||
    char bf[12];
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    char ch;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    while ((ch=*(fmt++))) {
 | 
			
		||||
        if (ch!='%') 
 | 
			
		||||
            putf(putp,ch);
 | 
			
		||||
    while ((ch = *(fmt++))) {
 | 
			
		||||
        if (ch != '%')
 | 
			
		||||
            putf(putp, ch);
 | 
			
		||||
        else {
 | 
			
		||||
            char lz=0;
 | 
			
		||||
#ifdef  PRINTF_LONG_SUPPORT
 | 
			
		||||
            char lng=0;
 | 
			
		||||
            char lz = 0;
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
            char lng = 0;
 | 
			
		||||
#endif
 | 
			
		||||
            int w=0;
 | 
			
		||||
            ch=*(fmt++);
 | 
			
		||||
            if (ch=='0') {
 | 
			
		||||
                ch=*(fmt++);
 | 
			
		||||
                lz=1;
 | 
			
		||||
                }
 | 
			
		||||
            if (ch>='0' && ch<='9') {
 | 
			
		||||
                ch=a2i(ch,&fmt,10,&w);
 | 
			
		||||
                }
 | 
			
		||||
#ifdef  PRINTF_LONG_SUPPORT
 | 
			
		||||
            if (ch=='l') {
 | 
			
		||||
                ch=*(fmt++);
 | 
			
		||||
                lng=1;
 | 
			
		||||
            int w = 0;
 | 
			
		||||
            ch    = *(fmt++);
 | 
			
		||||
            if (ch == '0') {
 | 
			
		||||
                ch = *(fmt++);
 | 
			
		||||
                lz = 1;
 | 
			
		||||
            }
 | 
			
		||||
            if (ch >= '0' && ch <= '9') {
 | 
			
		||||
                ch = a2i(ch, &fmt, 10, &w);
 | 
			
		||||
            }
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
            if (ch == 'l') {
 | 
			
		||||
                ch  = *(fmt++);
 | 
			
		||||
                lng = 1;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            switch (ch) {
 | 
			
		||||
                case 0: 
 | 
			
		||||
                case 0:
 | 
			
		||||
                    goto abort;
 | 
			
		||||
                case 'u' : {
 | 
			
		||||
#ifdef  PRINTF_LONG_SUPPORT
 | 
			
		||||
                case 'u': {
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
                    if (lng)
 | 
			
		||||
                        uli2a(va_arg(va, unsigned long int),10,0,bf);
 | 
			
		||||
                        uli2a(va_arg(va, unsigned long int), 10, 0, bf);
 | 
			
		||||
                    else
 | 
			
		||||
#endif
 | 
			
		||||
                    ui2a(va_arg(va, unsigned int),10,0,bf);
 | 
			
		||||
                    putchw(putp,putf,w,lz,bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                    }
 | 
			
		||||
                case 'd' :  {
 | 
			
		||||
#ifdef  PRINTF_LONG_SUPPORT
 | 
			
		||||
                    if (lng)
 | 
			
		||||
                        li2a(va_arg(va, unsigned long int),bf);
 | 
			
		||||
                    else
 | 
			
		||||
#endif
 | 
			
		||||
                    i2a(va_arg(va, int),bf);
 | 
			
		||||
                    putchw(putp,putf,w,lz,bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                    }
 | 
			
		||||
                case 'x': case 'X' : 
 | 
			
		||||
#ifdef  PRINTF_LONG_SUPPORT
 | 
			
		||||
                    if (lng)
 | 
			
		||||
                        uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
 | 
			
		||||
                    else
 | 
			
		||||
#endif
 | 
			
		||||
                    ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
 | 
			
		||||
                    putchw(putp,putf,w,lz,bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'c' : 
 | 
			
		||||
                    putf(putp,(char)(va_arg(va, int)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case 's' : 
 | 
			
		||||
                    putchw(putp,putf,w,0,va_arg(va, char*));
 | 
			
		||||
                    break;
 | 
			
		||||
                case '%' :
 | 
			
		||||
                    putf(putp,ch);
 | 
			
		||||
                default:
 | 
			
		||||
                        ui2a(va_arg(va, unsigned int), 10, 0, bf);
 | 
			
		||||
                    putchw(putp, putf, w, lz, bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'd': {
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
                    if (lng)
 | 
			
		||||
                        li2a(va_arg(va, unsigned long int), bf);
 | 
			
		||||
                    else
 | 
			
		||||
#endif
 | 
			
		||||
                        i2a(va_arg(va, int), bf);
 | 
			
		||||
                    putchw(putp, putf, w, lz, bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'x':
 | 
			
		||||
                case 'X':
 | 
			
		||||
#ifdef PRINTF_LONG_SUPPORT
 | 
			
		||||
                    if (lng)
 | 
			
		||||
                        uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf);
 | 
			
		||||
                    else
 | 
			
		||||
#endif
 | 
			
		||||
                        ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf);
 | 
			
		||||
                    putchw(putp, putf, w, lz, bf);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'c':
 | 
			
		||||
                    putf(putp, (char)(va_arg(va, int)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case 's':
 | 
			
		||||
                    putchw(putp, putf, w, 0, va_arg(va, char*));
 | 
			
		||||
                    break;
 | 
			
		||||
                case '%':
 | 
			
		||||
                    putf(putp, ch);
 | 
			
		||||
                default:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    abort:;
 | 
			
		||||
    }
 | 
			
		||||
abort:;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_printf(void* putp, void (*putf)(void*, char)) {
 | 
			
		||||
    stdout_putf = putf;
 | 
			
		||||
    stdout_putp = putp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void init_printf(void* putp,void (*putf) (void*,char))
 | 
			
		||||
    {
 | 
			
		||||
    stdout_putf=putf;
 | 
			
		||||
    stdout_putp=putp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
void tfp_printf(char *fmt, ...)
 | 
			
		||||
    {
 | 
			
		||||
void tfp_printf(char* fmt, ...) {
 | 
			
		||||
    va_list va;
 | 
			
		||||
    va_start(va,fmt);
 | 
			
		||||
    tfp_format(stdout_putp,stdout_putf,fmt,va);
 | 
			
		||||
    va_start(va, fmt);
 | 
			
		||||
    tfp_format(stdout_putp, stdout_putf, fmt, va);
 | 
			
		||||
    va_end(va);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void putcp(void* p,char c)
 | 
			
		||||
    {
 | 
			
		||||
    *(*((char**)p))++ = c;
 | 
			
		||||
    }
 | 
			
		||||
static void putcp(void* p, char c) { *(*((char**)p))++ = c; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void tfp_sprintf(char* s,char *fmt, ...)
 | 
			
		||||
    {
 | 
			
		||||
void tfp_sprintf(char* s, char* fmt, ...) {
 | 
			
		||||
    va_list va;
 | 
			
		||||
    va_start(va,fmt);
 | 
			
		||||
    tfp_format(&s,putcp,fmt,va);
 | 
			
		||||
    putcp(&s,0);
 | 
			
		||||
    va_start(va, fmt);
 | 
			
		||||
    tfp_format(&s, putcp, fmt, va);
 | 
			
		||||
    putcp(&s, 0);
 | 
			
		||||
    va_end(va);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ version 2.1 of the License, or (at your option) any later version.
 | 
			
		|||
 | 
			
		||||
This library is distributed in the hope that it will be useful,
 | 
			
		||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 | 
			
		||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
			
		||||
See the GNU Lesser General Public License for more details.
 | 
			
		||||
 | 
			
		||||
You 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
 | 
			
		|||
 | 
			
		||||
This library is realy just two files: 'printf.h' and 'printf.c'.
 | 
			
		||||
 | 
			
		||||
They provide a simple and small (+200 loc) printf functionality to 
 | 
			
		||||
They provide a simple and small (+200 loc) printf functionality to
 | 
			
		||||
be used in embedded systems.
 | 
			
		||||
 | 
			
		||||
I've found them so usefull in debugging that I do not bother with a 
 | 
			
		||||
I've found them so usefull in debugging that I do not bother with a
 | 
			
		||||
debugger at all.
 | 
			
		||||
 | 
			
		||||
They are distributed in source form, so to use them, just compile them 
 | 
			
		||||
into your project. 
 | 
			
		||||
They are distributed in source form, so to use them, just compile them
 | 
			
		||||
into your project.
 | 
			
		||||
 | 
			
		||||
Two printf variants are provided: printf and sprintf. 
 | 
			
		||||
Two printf variants are provided: printf and sprintf.
 | 
			
		||||
 | 
			
		||||
The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
 | 
			
		||||
 | 
			
		||||
Zero padding and field width are also supported.
 | 
			
		||||
 | 
			
		||||
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the 
 | 
			
		||||
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
 | 
			
		||||
long specifier is also
 | 
			
		||||
supported. Note that this will pull in some long math routines (pun intended!)
 | 
			
		||||
and thus make your executable noticably longer.
 | 
			
		||||
 | 
			
		||||
The memory foot print of course depends on the target cpu, compiler and 
 | 
			
		||||
compiler options, but a rough guestimate (based on a H8S target) is about 
 | 
			
		||||
1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. 
 | 
			
		||||
Not too bad. Your milage may vary. By hacking the source code you can 
 | 
			
		||||
get rid of some hunred bytes, I'm sure, but personally I feel the balance of 
 | 
			
		||||
The memory foot print of course depends on the target cpu, compiler and
 | 
			
		||||
compiler options, but a rough guestimate (based on a H8S target) is about
 | 
			
		||||
1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
 | 
			
		||||
Not too bad. Your milage may vary. By hacking the source code you can
 | 
			
		||||
get rid of some hunred bytes, I'm sure, but personally I feel the balance of
 | 
			
		||||
functionality and flexibility versus  code size is close to optimal for
 | 
			
		||||
many embedded systems.
 | 
			
		||||
 | 
			
		||||
To use the printf you need to supply your own character output function, 
 | 
			
		||||
To use the printf you need to supply your own character output function,
 | 
			
		||||
something like :
 | 
			
		||||
 | 
			
		||||
    void putc ( void* p, char c)
 | 
			
		||||
| 
						 | 
				
			
			@ -61,25 +61,25 @@ something like :
 | 
			
		|||
        SERIAL_PORT_TX_REGISTER = c;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
Before you can call printf you need to initialize it to use your 
 | 
			
		||||
Before you can call printf you need to initialize it to use your
 | 
			
		||||
character output function with something like:
 | 
			
		||||
 | 
			
		||||
    init_printf(NULL,putc);
 | 
			
		||||
 | 
			
		||||
Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', 
 | 
			
		||||
the NULL (or any pointer) you pass into the 'init_printf' will eventually be 
 | 
			
		||||
passed to your 'putc' routine. This allows you to pass some storage space (or 
 | 
			
		||||
anything realy) to the character output function, if necessary. 
 | 
			
		||||
This is not often needed but it was implemented like that because it made 
 | 
			
		||||
Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
 | 
			
		||||
the NULL (or any pointer) you pass into the 'init_printf' will eventually be
 | 
			
		||||
passed to your 'putc' routine. This allows you to pass some storage space (or
 | 
			
		||||
anything realy) to the character output function, if necessary.
 | 
			
		||||
This is not often needed but it was implemented like that because it made
 | 
			
		||||
implementing the sprintf function so neat (look at the source code).
 | 
			
		||||
 | 
			
		||||
The code is re-entrant, except for the 'init_printf' function, so it 
 | 
			
		||||
is safe to call it from interupts too, although this may result in mixed output. 
 | 
			
		||||
The code is re-entrant, except for the 'init_printf' function, so it
 | 
			
		||||
is safe to call it from interupts too, although this may result in mixed output.
 | 
			
		||||
If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
 | 
			
		||||
 | 
			
		||||
The printf and sprintf functions are actually macros that translate to 
 | 
			
		||||
The printf and sprintf functions are actually macros that translate to
 | 
			
		||||
'tfp_printf' and 'tfp_sprintf'. This makes it possible
 | 
			
		||||
to use them along with 'stdio.h' printf's in a single source file. 
 | 
			
		||||
to use them along with 'stdio.h' printf's in a single source file.
 | 
			
		||||
You just need to undef the names before you include the 'stdio.h'.
 | 
			
		||||
Note that these are not function like macros, so if you have variables
 | 
			
		||||
or struct members with these names, things will explode in your face.
 | 
			
		||||
| 
						 | 
				
			
			@ -92,20 +92,19 @@ For further details see source code.
 | 
			
		|||
regs Kusti, 23.10.2004
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef __TFP_PRINTF__
 | 
			
		||||
#define __TFP_PRINTF__
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
 | 
			
		||||
void init_printf(void* putp,void (*putf) (void*,char));
 | 
			
		||||
void init_printf(void* putp, void (*putf)(void*, char));
 | 
			
		||||
 | 
			
		||||
void tfp_printf(char *fmt, ...);
 | 
			
		||||
void tfp_sprintf(char* s,char *fmt, ...);
 | 
			
		||||
void tfp_printf(char* fmt, ...);
 | 
			
		||||
void tfp_sprintf(char* s, char* fmt, ...);
 | 
			
		||||
 | 
			
		||||
void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
 | 
			
		||||
void tfp_format(void* putp, void (*putf)(void*, char), char* fmt, va_list va);
 | 
			
		||||
 | 
			
		||||
#define printf tfp_printf 
 | 
			
		||||
#define sprintf tfp_sprintf 
 | 
			
		||||
#define printf tfp_printf
 | 
			
		||||
#define sprintf tfp_sprintf
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,14 +12,14 @@
 | 
			
		|||
#if defined(KL2x) || defined(K20x)
 | 
			
		||||
 | 
			
		||||
/* Use Low Power Timer (LPTMR) */
 | 
			
		||||
#define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
 | 
			
		||||
#define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
 | 
			
		||||
#    define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
 | 
			
		||||
#    define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
 | 
			
		||||
 | 
			
		||||
#elif defined(STM32F0XX)
 | 
			
		||||
 | 
			
		||||
/* Use TIM14 manually */
 | 
			
		||||
#define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
 | 
			
		||||
#define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
 | 
			
		||||
#    define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
 | 
			
		||||
#    define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,39 +31,34 @@
 | 
			
		|||
 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
 | 
			
		||||
 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
 | 
			
		||||
 */
 | 
			
		||||
static 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
 | 
			
		||||
};
 | 
			
		||||
static 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};
 | 
			
		||||
 | 
			
		||||
/* interrupt handler */
 | 
			
		||||
OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
 | 
			
		||||
    OSAL_IRQ_PROLOGUE();
 | 
			
		||||
 | 
			
		||||
    /* Software PWM
 | 
			
		||||
    * timer:1111 1111 1111 1111
 | 
			
		||||
    *       \_____/\/ \_______/____  count(0-255)
 | 
			
		||||
    *          \    \______________  duration of step(4)
 | 
			
		||||
    *           \__________________  index of step table(0-63)
 | 
			
		||||
    */
 | 
			
		||||
     * timer:1111 1111 1111 1111
 | 
			
		||||
     *       \_____/\/ \_______/____  count(0-255)
 | 
			
		||||
     *          \    \______________  duration of step(4)
 | 
			
		||||
     *           \__________________  index of step table(0-63)
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    // this works for cca 65536 irqs/sec
 | 
			
		||||
    static union {
 | 
			
		||||
    uint16_t row;
 | 
			
		||||
    struct {
 | 
			
		||||
      uint8_t count:8;
 | 
			
		||||
      uint8_t duration:2;
 | 
			
		||||
      uint8_t index:6;
 | 
			
		||||
    } pwm;
 | 
			
		||||
    } timer = { .row = 0 };
 | 
			
		||||
        uint16_t row;
 | 
			
		||||
        struct {
 | 
			
		||||
            uint8_t count : 8;
 | 
			
		||||
            uint8_t duration : 2;
 | 
			
		||||
            uint8_t index : 6;
 | 
			
		||||
        } pwm;
 | 
			
		||||
    } timer = {.row = 0};
 | 
			
		||||
 | 
			
		||||
    timer.row++;
 | 
			
		||||
 | 
			
		||||
    // LED on
 | 
			
		||||
    if (timer.pwm.count == 0) {
 | 
			
		||||
        led_set(1<<USB_LED_CAPS_LOCK);
 | 
			
		||||
        led_set(1 << USB_LED_CAPS_LOCK);
 | 
			
		||||
    }
 | 
			
		||||
    // LED off
 | 
			
		||||
    if (timer.pwm.count == breathing_table[timer.pwm.index]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,19 +73,18 @@ OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
 | 
			
		|||
 | 
			
		||||
#endif /* common parts for known platforms */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
 | 
			
		||||
 | 
			
		||||
/* LPTMR clock options */
 | 
			
		||||
#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
 | 
			
		||||
#define LPTMR_CLOCK_LPO      1 /* 1kHz clock */
 | 
			
		||||
#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
 | 
			
		||||
#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
 | 
			
		||||
#    define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
 | 
			
		||||
#    define LPTMR_CLOCK_LPO 1      /* 1kHz clock */
 | 
			
		||||
#    define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
 | 
			
		||||
#    define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
 | 
			
		||||
 | 
			
		||||
/* Work around inconsistencies in Freescale naming */
 | 
			
		||||
#if !defined(SIM_SCGC5_LPTMR)
 | 
			
		||||
#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
 | 
			
		||||
#endif
 | 
			
		||||
#    if !defined(SIM_SCGC5_LPTMR)
 | 
			
		||||
#        define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
/* Initialise the timer */
 | 
			
		||||
void sleep_led_init(void) {
 | 
			
		||||
| 
						 | 
				
			
			@ -101,52 +95,52 @@ void sleep_led_init(void) {
 | 
			
		|||
    /* Set the compare value */
 | 
			
		||||
    LPTMR0->CMR = 0;  // trigger on counter value (i.e. every time)
 | 
			
		||||
 | 
			
		||||
    /* Set up clock source and prescaler */
 | 
			
		||||
    /* Software PWM
 | 
			
		||||
    *  ______           ______           __
 | 
			
		||||
    * |  ON  |___OFF___|  ON  |___OFF___|   ....
 | 
			
		||||
    * |<-------------->|<-------------->|<- ....
 | 
			
		||||
    *     PWM period       PWM period
 | 
			
		||||
    *
 | 
			
		||||
    * R                interrupts/period[resolution]
 | 
			
		||||
    * F                periods/second[frequency]
 | 
			
		||||
    * R * F            interrupts/second
 | 
			
		||||
    */
 | 
			
		||||
/* Set up clock source and prescaler */
 | 
			
		||||
/* Software PWM
 | 
			
		||||
 *  ______           ______           __
 | 
			
		||||
 * |  ON  |___OFF___|  ON  |___OFF___|   ....
 | 
			
		||||
 * |<-------------->|<-------------->|<- ....
 | 
			
		||||
 *     PWM period       PWM period
 | 
			
		||||
 *
 | 
			
		||||
 * R                interrupts/period[resolution]
 | 
			
		||||
 * F                periods/second[frequency]
 | 
			
		||||
 * R * F            interrupts/second
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    /* === OPTION 1 === */
 | 
			
		||||
    #if 0
 | 
			
		||||
/* === OPTION 1 === */
 | 
			
		||||
#    if 0
 | 
			
		||||
    //  1kHz LPO
 | 
			
		||||
    //  No prescaler => 1024 irqs/sec
 | 
			
		||||
    //  Note: this is too slow for a smooth breathe
 | 
			
		||||
    LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
 | 
			
		||||
    #endif /* OPTION 1 */
 | 
			
		||||
#    endif /* OPTION 1 */
 | 
			
		||||
 | 
			
		||||
    /* === OPTION 2 === */
 | 
			
		||||
    #if 1
 | 
			
		||||
/* === OPTION 2 === */
 | 
			
		||||
#    if 1
 | 
			
		||||
    //  nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
 | 
			
		||||
    MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
 | 
			
		||||
    #if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
 | 
			
		||||
    MCG->C2 |= MCG_C2_IRCS;  // fast (4MHz) internal ref clock
 | 
			
		||||
#        if defined(KL27)    // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
 | 
			
		||||
    MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
 | 
			
		||||
    #endif /* KL27 */
 | 
			
		||||
    MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
 | 
			
		||||
#        endif                  /* KL27 */
 | 
			
		||||
    MCG->C1 |= MCG_C1_IRCLKEN;  // enable internal ref clock
 | 
			
		||||
    //  to work in stop mode, also MCG_C1_IREFSTEN
 | 
			
		||||
    //  Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
 | 
			
		||||
    //  => approx F=61, R=256, duration = 4
 | 
			
		||||
    LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6);
 | 
			
		||||
    #endif /* OPTION 2 */
 | 
			
		||||
    LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK) | LPTMRx_PSR_PRESCALE(6);
 | 
			
		||||
#    endif /* OPTION 2 */
 | 
			
		||||
 | 
			
		||||
    /* === OPTION 3 === */
 | 
			
		||||
    #if 0
 | 
			
		||||
/* === OPTION 3 === */
 | 
			
		||||
#    if 0
 | 
			
		||||
    //  OSC output (external crystal), usually 8MHz or 16MHz
 | 
			
		||||
    OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
 | 
			
		||||
    //  to work in stop mode, also OSC_CR_EREFSTEN
 | 
			
		||||
    //  Divide by 2^N
 | 
			
		||||
    LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
 | 
			
		||||
    #endif /* OPTION 3 */
 | 
			
		||||
#    endif /* OPTION 3 */
 | 
			
		||||
    /* === END OPTIONS === */
 | 
			
		||||
 | 
			
		||||
    /* Interrupt on TCF set (compare flag) */
 | 
			
		||||
    nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
 | 
			
		||||
    nvicEnableVector(LPTMR0_IRQn, 2);  // vector, priority
 | 
			
		||||
    LPTMR0->CSR |= LPTMRx_CSR_TIE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -205,20 +199,14 @@ void sleep_led_toggle(void) {
 | 
			
		|||
    STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else /* platform selection: not on familiar chips */
 | 
			
		||||
 | 
			
		||||
void sleep_led_init(void) {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
void sleep_led_enable(void) {
 | 
			
		||||
    led_set(1<<USB_LED_CAPS_LOCK);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
void sleep_led_disable(void) {
 | 
			
		||||
    led_set(0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
void sleep_led_init(void) {}
 | 
			
		||||
 | 
			
		||||
void sleep_led_enable(void) { led_set(1 << USB_LED_CAPS_LOCK); }
 | 
			
		||||
 | 
			
		||||
void sleep_led_disable(void) { led_set(0); }
 | 
			
		||||
 | 
			
		||||
void sleep_led_toggle(void) {
 | 
			
		||||
    // not implemented
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,49 +17,44 @@
 | 
			
		|||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void suspend_idle(uint8_t time) {
 | 
			
		||||
	// TODO: this is not used anywhere - what units is 'time' in?
 | 
			
		||||
	wait_ms(time);
 | 
			
		||||
    // TODO: this is not used anywhere - what units is 'time' in?
 | 
			
		||||
    wait_ms(time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Run keyboard level Power down
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void suspend_power_down_user (void) { }
 | 
			
		||||
__attribute__((weak)) void suspend_power_down_user(void) {}
 | 
			
		||||
/** \brief Run keyboard level Power down
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void suspend_power_down_kb(void) {
 | 
			
		||||
  suspend_power_down_user();
 | 
			
		||||
}
 | 
			
		||||
__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
 | 
			
		||||
 | 
			
		||||
/** \brief suspend power down
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void suspend_power_down(void) {
 | 
			
		||||
	// TODO: figure out what to power down and how
 | 
			
		||||
	// shouldn't power down TPM/FTM if we want a breathing LED
 | 
			
		||||
	// also shouldn't power down USB
 | 
			
		||||
    // TODO: figure out what to power down and how
 | 
			
		||||
    // shouldn't power down TPM/FTM if we want a breathing LED
 | 
			
		||||
    // also shouldn't power down USB
 | 
			
		||||
 | 
			
		||||
  suspend_power_down_kb();
 | 
			
		||||
	// on AVR, this enables the watchdog for 15ms (max), and goes to
 | 
			
		||||
	// SLEEP_MODE_PWR_DOWN
 | 
			
		||||
    suspend_power_down_kb();
 | 
			
		||||
    // on AVR, this enables the watchdog for 15ms (max), and goes to
 | 
			
		||||
    // SLEEP_MODE_PWR_DOWN
 | 
			
		||||
 | 
			
		||||
	wait_ms(17);
 | 
			
		||||
    wait_ms(17);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief suspend wakeup condition
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak)) void matrix_power_up(void) {}
 | 
			
		||||
__attribute__ ((weak)) void matrix_power_down(void) {}
 | 
			
		||||
bool suspend_wakeup_condition(void)
 | 
			
		||||
{
 | 
			
		||||
__attribute__((weak)) void matrix_power_up(void) {}
 | 
			
		||||
__attribute__((weak)) void matrix_power_down(void) {}
 | 
			
		||||
bool                       suspend_wakeup_condition(void) {
 | 
			
		||||
    matrix_power_up();
 | 
			
		||||
    matrix_scan();
 | 
			
		||||
    matrix_power_down();
 | 
			
		||||
| 
						 | 
				
			
			@ -73,25 +68,20 @@ bool suspend_wakeup_condition(void)
 | 
			
		|||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void suspend_wakeup_init_user(void) { }
 | 
			
		||||
__attribute__((weak)) void suspend_wakeup_init_user(void) {}
 | 
			
		||||
 | 
			
		||||
/** \brief run keyboard level code immediately after wakeup
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void suspend_wakeup_init_kb(void) {
 | 
			
		||||
  suspend_wakeup_init_user();
 | 
			
		||||
}
 | 
			
		||||
__attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_user(); }
 | 
			
		||||
 | 
			
		||||
/** \brief suspend wakeup condition
 | 
			
		||||
 *
 | 
			
		||||
 * run immediately after wakeup
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void suspend_wakeup_init(void)
 | 
			
		||||
{
 | 
			
		||||
void suspend_wakeup_init(void) {
 | 
			
		||||
    // clear keyboard state
 | 
			
		||||
    // need to do it manually, because we're running from ISR
 | 
			
		||||
    //  and clear_keyboard() calls print
 | 
			
		||||
| 
						 | 
				
			
			@ -111,5 +101,5 @@ void suspend_wakeup_init(void)
 | 
			
		|||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
    backlight_init();
 | 
			
		||||
#endif /* BACKLIGHT_ENABLE */
 | 
			
		||||
  suspend_wakeup_init_kb();
 | 
			
		||||
    suspend_wakeup_init_kb();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,40 +2,32 @@
 | 
			
		|||
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
static systime_t last_systime = 0;
 | 
			
		||||
static systime_t overflow = 0;
 | 
			
		||||
static uint32_t current_time_ms = 0;
 | 
			
		||||
static systime_t last_systime    = 0;
 | 
			
		||||
static systime_t overflow        = 0;
 | 
			
		||||
static uint32_t  current_time_ms = 0;
 | 
			
		||||
 | 
			
		||||
void timer_init(void) {
 | 
			
		||||
  timer_clear();
 | 
			
		||||
}
 | 
			
		||||
void timer_init(void) { timer_clear(); }
 | 
			
		||||
 | 
			
		||||
void timer_clear(void) {
 | 
			
		||||
  last_systime = chVTGetSystemTime();
 | 
			
		||||
  overflow = 0;
 | 
			
		||||
  current_time_ms = 0;
 | 
			
		||||
    last_systime    = chVTGetSystemTime();
 | 
			
		||||
    overflow        = 0;
 | 
			
		||||
    current_time_ms = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t timer_read(void) {
 | 
			
		||||
  return (uint16_t)timer_read32();
 | 
			
		||||
}
 | 
			
		||||
uint16_t timer_read(void) { return (uint16_t)timer_read32(); }
 | 
			
		||||
 | 
			
		||||
uint32_t timer_read32(void) {
 | 
			
		||||
  // Note: We assume that the timer update is called at least once betweeen every wrap around of the system time
 | 
			
		||||
  systime_t current_systime = chVTGetSystemTime();
 | 
			
		||||
  systime_t elapsed = current_systime - last_systime + overflow;
 | 
			
		||||
  uint32_t elapsed_ms = ST2MS(elapsed);
 | 
			
		||||
  current_time_ms += elapsed_ms;
 | 
			
		||||
  overflow = elapsed - MS2ST(elapsed_ms);
 | 
			
		||||
  last_systime = current_systime;
 | 
			
		||||
    // Note: We assume that the timer update is called at least once betweeen every wrap around of the system time
 | 
			
		||||
    systime_t current_systime = chVTGetSystemTime();
 | 
			
		||||
    systime_t elapsed         = current_systime - last_systime + overflow;
 | 
			
		||||
    uint32_t  elapsed_ms      = ST2MS(elapsed);
 | 
			
		||||
    current_time_ms += elapsed_ms;
 | 
			
		||||
    overflow     = elapsed - MS2ST(elapsed_ms);
 | 
			
		||||
    last_systime = current_systime;
 | 
			
		||||
 | 
			
		||||
  return current_time_ms;
 | 
			
		||||
    return current_time_ms;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t timer_elapsed(uint16_t last) {
 | 
			
		||||
  return timer_read() - last;
 | 
			
		||||
}
 | 
			
		||||
uint16_t timer_elapsed(uint16_t last) { return timer_read() - last; }
 | 
			
		||||
 | 
			
		||||
uint32_t timer_elapsed32(uint32_t last) {
 | 
			
		||||
  return timer_read32() - last;
 | 
			
		||||
}
 | 
			
		||||
uint32_t timer_elapsed32(uint32_t last) { return timer_read32() - last; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue