update files to correct FSF address
[openocd.git] / contrib / loaders / flash / lpcspifi_write.S
1 /***************************************************************************
2 * Copyright (C) 2012 by George Harris *
3 * george@luminairecoffee.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
20
21 .text
22 .syntax unified
23 .cpu cortex-m3
24 .thumb
25 .thumb_func
26
27 /*
28 * Params :
29 * r0 = workarea start, status (out)
30 * r1 = workarea end
31 * r2 = target address (offset from flash base)
32 * r3 = count (bytes)
33 * r4 = page size
34 * Clobbered:
35 * r7 - rp
36 * r8 - wp, tmp
37 * r9 - send/receive data
38 * r10 - temp
39 * r11 - current page end address
40 */
41
42 #define SSP_BASE_HIGH 0x4008
43 #define SSP_BASE_LOW 0x3000
44 #define SSP_CR0_OFFSET 0x00
45 #define SSP_CR1_OFFSET 0x04
46 #define SSP_DATA_OFFSET 0x08
47 #define SSP_CPSR_OFFSET 0x10
48 #define SSP_SR_OFFSET 0x0c
49
50 #define SSP_CLOCK_BASE_HIGH 0x4005
51 #define SSP_CLOCK_BASE_LOW 0x0000
52 #define SSP_BRANCH_CLOCK_BASE_HIGH 0x4005
53 #define SSP_BRANCH_CLOCK_BASE_LOW 0x2000
54 #define SSP_BASE_CLOCK_OFFSET 0x94
55 #define SSP_BRANCH_CLOCK_OFFSET 0x700
56
57 #define IOCONFIG_BASE_HIGH 0x4008
58 #define IOCONFIG_BASE_LOW 0x6000
59 #define IOCONFIG_SCK_OFFSET 0x18c
60 #define IOCONFIG_HOLD_OFFSET 0x190
61 #define IOCONFIG_WP_OFFSET 0x194
62 #define IOCONFIG_MISO_OFFSET 0x198
63 #define IOCONFIG_MOSI_OFFSET 0x19c
64 #define IOCONFIG_CS_OFFSET 0x1a0
65
66 #define IO_BASE_HIGH 0x400f
67 #define IO_BASE_LOW 0x4000
68 #define IO_CS_OFFSET 0xab
69 #define IODIR_BASE_HIGH 0x400f
70 #define IODIR_BASE_LOW 0x6000
71 #define IO_CS_DIR_OFFSET 0x14
72
73
74 setup: /* Initialize SSP pins and module */
75 mov.w r10, #IOCONFIG_BASE_LOW
76 movt r10, #IOCONFIG_BASE_HIGH
77 mov.w r8, #0xea
78 str.w r8, [r10, #IOCONFIG_SCK_OFFSET] /* Configure SCK pin function */
79 mov.w r8, #0x40
80 str.w r8, [r10, #IOCONFIG_HOLD_OFFSET] /* Configure /HOLD pin function */
81 mov.w r8, #0x40
82 str.w r8, [r10, #IOCONFIG_WP_OFFSET] /* Configure /WP pin function */
83 mov.w r8, #0xed
84 str.w r8, [r10, #IOCONFIG_MISO_OFFSET] /* Configure MISO pin function */
85 mov.w r8, #0xed
86 str.w r8, [r10, #IOCONFIG_MOSI_OFFSET] /* Configure MOSI pin function */
87 mov.w r8, #0x44
88 str.w r8, [r10, #IOCONFIG_CS_OFFSET] /* Configure CS pin function */
89
90 mov.w r10, #IODIR_BASE_LOW
91 movt r10, #IODIR_BASE_HIGH
92 mov.w r8, #0x800
93 str r8, [r10, #IO_CS_DIR_OFFSET] /* Set CS as output */
94 mov.w r10, #IO_BASE_LOW
95 movt r10, #IO_BASE_HIGH
96 mov.w r8, #0xff
97 str.w r8, [r10, #IO_CS_OFFSET] /* Set CS high */
98
99 mov.w r10, #SSP_CLOCK_BASE_LOW
100 movt r10, #SSP_CLOCK_BASE_HIGH
101 mov.w r8, #0x0000
102 movt r8, #0x0100
103 str.w r8, [r10, #SSP_BASE_CLOCK_OFFSET] /* Configure SSP0 base clock (use 12 MHz IRC) */
104
105 mov.w r10, #SSP_BRANCH_CLOCK_BASE_LOW
106 movt r10, #SSP_BRANCH_CLOCK_BASE_HIGH
107 mov.w r8, #0x01
108 str.w r8, [r10, #SSP_BRANCH_CLOCK_OFFSET] /* Configure (enable) SSP0 branch clock */
109
110 mov.w r10, #SSP_BASE_LOW
111 movt r10, #SSP_BASE_HIGH
112 mov.w r8, #0x07
113 str.w r8, [r10, #SSP_CR0_OFFSET] /* Set clock postscale */
114 mov.w r8, #0x02
115 str.w r8, [r10, #SSP_CPSR_OFFSET] /* Set clock prescale */
116 str.w r8, [r10, #SSP_CR1_OFFSET] /* Enable SSP in SPI mode */
117
118 mov.w r11, #0x00
119 find_next_page_boundary:
120 add r11, r4 /* Increment to the next page */
121 cmp r11, r2
122 /* If we have not reached the next page boundary after the target address, keep going */
123 bls find_next_page_boundary
124 write_enable:
125 bl cs_down
126 mov.w r9, #0x06 /* Send the write enable command */
127 bl write_data
128 bl cs_up
129
130 bl cs_down
131 mov.w r9, #0x05 /* Get status register */
132 bl write_data
133 mov.w r9, #0x00 /* Dummy data to clock in status */
134 bl write_data
135 bl cs_up
136
137 tst r9, #0x02 /* If the WE bit isn't set, we have a problem. */
138 beq error
139 page_program:
140 bl cs_down
141 mov.w r9, #0x02 /* Send the page program command */
142 bl write_data
143 write_address:
144 lsr r9, r2, #16 /* Send the current 24-bit write address, MSB first */
145 bl write_data
146 lsr r9, r2, #8
147 bl write_data
148 mov.w r9, r2
149 bl write_data
150 wait_fifo:
151 ldr r8, [r0] /* read the write pointer */
152 cmp r8, #0 /* if it's zero, we're gonzo */
153 beq exit
154 ldr r7, [r0, #4] /* read the read pointer */
155 cmp r7, r8 /* wait until they are not equal */
156 beq wait_fifo
157 write:
158 ldrb r9, [r7], #0x01 /* Load one byte from the FIFO, increment the read pointer by 1 */
159 bl write_data /* send the byte to the flash chip */
160
161 cmp r7, r1 /* wrap the read pointer if it is at the end */
162 it cs
163 addcs r7, r0, #8 /* skip loader args */
164 str r7, [r0, #4] /* store the new read pointer */
165 subs r3, r3, #1 /* decrement count */
166 cbz r3, exit /* Exit if we have written everything */
167
168 add r2, #1 /* Increment flash address by 1 */
169 cmp r11, r2 /* See if we have reached the end of a page */
170 bne wait_fifo /* If not, keep writing bytes */
171 bl cs_up /* Otherwise, end the command and keep going w/ the next page */
172 add r11, r4 /* Move up the end-of-page address by the page size*/
173 wait_flash_busy: /* Wait for the flash to finish the previous page write */
174 bl cs_down
175 mov.w r9, #0x05 /* Get status register */
176 bl write_data
177 mov.w r9, #0x00 /* Dummy data to clock in status */
178 bl write_data
179 bl cs_up
180 tst r9, #0x01 /* If it isn't done, keep waiting */
181 bne wait_flash_busy
182 b write_enable /* If it is done, start a new page write */
183 write_data: /* Send/receive 1 byte of data over SSP */
184 mov.w r10, #SSP_BASE_LOW
185 movt r10, #SSP_BASE_HIGH
186 str.w r9, [r10, #SSP_DATA_OFFSET] /* Write supplied data to the SSP data reg */
187 wait_transmit:
188 ldr r9, [r10, #SSP_SR_OFFSET] /* Check SSP status */
189 tst r9, #0x0010 /* Check if BSY bit is set */
190 bne wait_transmit /* If still transmitting, keep waiting */
191 ldr r9, [r10, #SSP_DATA_OFFSET] /* Load received data */
192 bx lr /* Exit subroutine */
193 cs_up:
194 mov.w r8, #0xff
195 b cs_write
196 cs_down:
197 mov.w r8, #0x0000
198 cs_write:
199 mov.w r10, #IO_BASE_LOW
200 movt r10, #IO_BASE_HIGH
201 str.w r8, [r10, #IO_CS_OFFSET]
202 bx lr
203 error:
204 movs r0, #0
205 str r0, [r2, #4] /* set rp = 0 on error */
206 exit:
207 mov r0, r6
208 bkpt #0x00
209
210 .end

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)