1fa761336a807288310c6c5513a87623e8908a7f
[fw/openocd] / contrib / loaders / flash / kinetis_ke / kinetis_ke_flash.s
1 /***************************************************************************
2  *   Copyright (C) 2015 by Ivan Meleca                                     *
3  *   ivan@artekit.eu                                                       *
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
16         /* Params:
17          * r0 = flash destination address, status
18          * r1 = longword count
19          * r2 = workarea start address
20          * r3 = workarea end address
21          */
22
23         .text
24         .cpu cortex-m0plus
25         .code 16
26         .thumb_func
27
28         .align  2
29
30         /* r5 = rp
31          * r6 = wp, tmp
32          * r7 = tmp
33          */
34
35 wait_fifo:
36         ldr     r6, [r2, #0]    /* read wp */
37         cmp     r6, #0                  /* abort if wp == 0 */
38         beq     exit
39         ldr     r5, [r2, #4]    /* read rp */
40         cmp     r5, r6                  /* wait until rp != wp */
41         beq     wait_fifo
42
43         ldr             r6, fstat               /* Clear error flags */
44         mov             r7, #48
45         strb    r7, [r6]
46
47         ldr             r6, fccobix             /* FCCOBIX = 0 */
48         mov             r7, #0
49         strb    r7, [r6]
50
51         ldr     r6, fccobhi             /* Program FLASH command */
52         mov             r7, #6                  /* FCCOBHI = 6 */
53         strb    r7, [r6]
54
55         lsr             r7, r0, #16             /* FCCOBLO = flash destination address >> 16 */
56         ldr             r6, fccoblo
57         strb    r7, [r6]
58
59         ldr             r6, fccobix             /* Index for lower byte address bits[15:0] */
60         mov             r7, #1
61         strb    r7, [r6]                /* FCCOBIX = 1*/
62
63         uxtb    r7, r0                  /* Memory address bits[15:0] */
64         ldr     r6, fccoblo
65         strb    r7, [r6]                /* FCCOBLO = flash destination address */
66
67         lsr             r7, r0, #8
68         ldr             r6, fccobhi
69         strb    r7, [r6]                /* FCCOBHI = flash destination address >> 8 */
70
71         ldr             r6, fccobix             /* FCCOBIX = 2 */
72         mov             r7, #2
73         strb    r7, [r6]
74
75         ldrb    r7, [r5, #1]    /* FCCOBHI = rp >> 8 */
76         ldr             r6, fccobhi
77         strb    r7, [r6]
78
79         ldrb    r7, [r5]                /* FCCOBLO = rp */
80         ldr     r6, fccoblo
81         strb    r7, [r6]
82
83         ldr             r6, fccobix             /* FCCOBIX = 3 */
84         mov             r7, #3
85         strb    r7, [r6]
86
87         ldrb    r7, [r5, #3]    /* FCCOBHI = rp >> 24 */
88         ldr             r6, fccobhi
89         strb    r7, [r6]
90
91         ldrb    r7, [r5, #2]    /* FCCOBLO = rp >> 16 */
92         ldr             r6, fccoblo
93         strb    r7, [r6]
94
95         sub             r1, r1, #1              /* Two words (4 bytes) queued, decrement counter */
96         add             r0, r0, #4              /* flash address += 4 */
97         add             r5, r5, #4              /* rp += 4 */
98
99         cmp     r5, r3                  /* Wrap? */
100         bcc     no_wrap
101         mov     r5, r2
102         add     r5, r5, #8
103
104 no_wrap:
105         cmp             r1, #0                  /* Done? */
106         beq             execute
107
108         ldr     r6, [r2, #0]    /* read wp */
109         cmp     r6, r5
110         beq             execute                 /* execute if rp == wp */
111
112         ldr             r6, fccobix             /* FCCOBIX = 4 */
113         mov             r7, #4
114         strb    r7, [r6]
115
116         ldrb    r7, [r5, #1]    /* FCCOBHI = rp >> 8 */
117         ldr             r6, fccobhi
118         strb    r7, [r6]
119
120         ldrb    r7, [r5]                /* FCCOBLO = rp */
121         ldr     r6, fccoblo
122         strb    r7, [r6]
123
124         ldr             r6, fccobix             /* FCCOBIX = 5 */
125         mov             r7, #5
126         strb    r7, [r6]
127
128         ldrb    r7, [r5, #3]    /* FCCOBHI = rp >> 24 */
129         ldr             r6, fccobhi
130         strb    r7, [r6]
131
132         ldrb    r7, [r5, #2]    /* FCCOBLO = rp >> 16 */
133         ldr             r6, fccoblo
134         strb    r7, [r6]
135
136         sub             r1, r1, #1              /* Two words (4 bytes) queued, decrement counter */
137         add             r0, r0, #4              /* flash address += 4 */
138         add             r5, r5, #4              /* rp += 4 */
139
140         cmp     r5, r3                  /* Wrap? */
141         bcc     execute
142         mov     r5, r2
143         add     r5, r5, #8
144
145 execute:
146         ldr             r6, fstat               /* Launch the command */
147         mov             r7, #128
148         strb    r7, [r6]
149
150 wait_busy:
151         ldr             r6, fstat
152         ldrb    r6, [r6]                /* Wait until finished */
153         tst             r6, r7
154         beq             wait_busy
155
156         mov             r7, #48                 /* Check error */
157         tst             r6, r7
158         bne             error
159
160         mov             r6, #0                  /* Clear error */
161
162         str     r5, [r2, #4]    /* Store rp */
163
164         cmp             r1, #0                  /* Done? */
165         beq             done
166         b               wait_fifo
167
168 error:
169         mov             r0, #0
170         str     r0, [r2, #4]    /* set rp = 0 on error */
171
172 done:
173         mov             r0, r6                  /* Set result code */
174         bkpt    #0
175
176         .align  2
177 fstat:
178         .word   0
179 fccobix:
180         .word   0
181 fccobhi:
182         .word   0
183 fccoblo:
184         .word   0