1/* Copyright (c) 2009 Dmitry Xmelkov 2 All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 * Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in 11 the documentation and/or other materials provided with the 12 distribution. 13 * Neither the name of the copyright holders nor the names of 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 POSSIBILITY OF SUCH DAMAGE. */ 28 29/* $Id: eewr_byte.S 2486 2015-08-20 06:56:42Z pitchumani $ */ 30 31#ifndef __DOXYGEN 32 33#include <avr/io.h> 34 35#if E2END && __AVR_ARCH__ > 1 36 37#include <avr/eeprom.h> 38#include "asmdef.h" 39#include "eedef.h" 40 41ENTRY eeprom_write_byte 42 mov r18, r22 43 44ENTRY eeprom_write_r18 45 46#if __AVR_XMEGA__ /* -------------------------------------------- */ 47 48# ifndef CCP_IOREG_gc 49# define CCP_IOREG_gc 0xD8 /* IO Register Protection */ 50# endif 51# ifndef NVM_CMD_READ_EEPROM_gc 52# define NVM_CMD_READ_EEPROM_gc 0x06 53# endif 54# ifndef NVM_CMD_LOAD_EEPROM_BUFFER_gc 55# define NVM_CMD_LOAD_EEPROM_BUFFER_gc 0x33 56# endif 57# ifndef NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc 58# define NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc 0x35 59# endif 60# ifndef NVM_CMD_ERASE_EEPROM_BUFFER_gc 61# define NVM_CMD_ERASE_EEPROM_BUFFER_gc 0x36 62# endif 63 64 ; Prepare base address of NVM. 65 ldi ZL, lo8(NVM_BASE) 66 ldi ZH, hi8(NVM_BASE) 67 68 ; Wait until NVM is not busy. 691: ldd r19, Z + NVM_STATUS - NVM_BASE 70 sbrc r19, NVM_NVMBUSY_bp 71 rjmp 1b 72 73 ; It has to be noted that for some Xmega parts (Eg. Xmega E family) EEPROM 74 ; is always memory mapped. So it is not possible to disable EEPROM mapping 75 ; explicitly. 76 ; The presence of NVM_EEMAPEN_bm macro (from the part header file) can be 77 ; checked to find out whether the device supports enabling/disabling of 78 ; EEPROM mapping. Absence of NVM_EEMAPEN_bm could be interpreted safely as 79 ; EEPROM always memory mapped and explicit memory mapping of EEPROM is not 80 ; required/invalid. 81#if defined (NVM_EEMAPEN_bm) 82 ; Disable EEPROM mapping into data space. 83 ldd r19, Z + NVM_CTRLB - NVM_BASE 84 andi r19, ~NVM_EEMAPEN_bm 85 std Z + NVM_CTRLB - NVM_BASE, r19 86 87 ; Check the clearance of EEPROM page buffer. 88 ldd r19, Z + NVM_STATUS - NVM_BASE 89 sbrs r19, NVM_EELOAD_bp 90 rjmp 3f ; erase is not required 91 92 ; Note that we have only four clock cycles to write to the CCP 93 ; protected register NVM_CTRLA, after writing to CCP. The 'ldi' 94 ; instruction always takes one clock to execute and 'std' instruction takes 95 ; two clock cycles. We fall within the four cycles that the CCP leaves 96 ; us to write the command execution start bit to the NVM_CTRLA 97 ; register. Note that r18 must be preserved until written to NVM_DATA0 98 99 ; Issue EEPROM Buffer Erase: 100 ldi r19, NVM_CMD_ERASE_EEPROM_BUFFER_gc 101 std Z + NVM_CMD - NVM_BASE, r19 102 ldi r19, CCP_IOREG_gc 103 out CCP, r19 104 ldi r19, NVM_CMDEX_bm 105 std Z + NVM_CTRLA - NVM_BASE, r19 106 107 ; Wait until NVM is not busy. 1082: ldd r19, Z + NVM_STATUS - NVM_BASE 109 sbrc r19, NVM_NVMBUSY_bp 110 rjmp 2b 111 112 ; Issue EEPROM Buffer Load command. 1133: ldi r19, NVM_CMD_LOAD_EEPROM_BUFFER_gc 114 std Z + NVM_CMD - NVM_BASE, r19 115#endif 116 std Z + NVM_ADDR0 - NVM_BASE, addr_lo 117 std Z + NVM_ADDR1 - NVM_BASE, addr_hi 118 std Z + NVM_ADDR2 - NVM_BASE, __zero_reg__ 119#if defined (NVM_EEMAPEN_bm) 120 std Z + NVM_DATA0 - NVM_BASE, r18 121#else 122 movw XL, addr_lo 123 subi XL, lo8(-MAPPED_EEPROM_START) 124 sbci XH, hi8(-MAPPED_EEPROM_START) 125 st X, r18 126#endif 127 128 ; Issue EEPROM Erase & Write command. 129 ldi r18, NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc 130 std Z + NVM_CMD - NVM_BASE, r18 131 ldi r18, CCP_IOREG_gc 132 ldi r19, NVM_CMDEX_bm 133 out CCP, r18 134 std Z + NVM_CTRLA - NVM_BASE, r19 135 136 ; Increment address. 137 adiw addr_lo, 1 138 139 ret 140 141#else /* ---------------------------------------------------- */ 142 1431: sbic _SFR_IO_ADDR (EECR), EEWE 144 rjmp 1b 145 146# if defined (EEPM0) && defined (EEPM1) 147 ; Set programming mode: erase and write. 148 out _SFR_IO_ADDR (EECR), __zero_reg__ 149# elif defined (EEPM0) || defined (EEPM1) 150# error /* Unknown EECR register. */ 151# endif 152 153# ifdef EEARH 154# if E2END > 0xFF 155 out _SFR_IO_ADDR (EEARH), addr_hi 156# else 157 ; This is for chips like ATmega48: the EEAR8 bit must be cleaned. 158 out _SFR_IO_ADDR (EEARH), __zero_reg__ 159# endif 160# endif 161 out _SFR_IO_ADDR (EEARL), addr_lo 162 out _SFR_IO_ADDR (EEDR), r18 163 in __tmp_reg__, _SFR_IO_ADDR (SREG) 164 cli 165 sbi _SFR_IO_ADDR (EECR), EEMWE 166 sbi _SFR_IO_ADDR (EECR), EEWE 167 out _SFR_IO_ADDR (SREG), __tmp_reg__ 168 adiw addr_lo, 1 169 ret 170 171#endif /* ---------------------------------------------------- */ 172 173ENDFUNC 174 175#endif /* E2END && __AVR_ARCH__ > 1 */ 176#endif /* !__DOXYGEN__ */ 177