Fix flashing less than a full page of data. Verify page at a time.
[fw/altos] / lib / ccdbg-memory.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ccdbg.h"
20
21 /*
22  * Read and write arbitrary memory through the debug port
23  */
24
25 static uint8_t  memory_init[] = {
26         2,      MOV_direct_A,           0x7f,
27         3,      MOV_direct1_direct2,    0x7e, SFR_DPL0,
28         3,      MOV_direct1_direct2,    0x7d, SFR_DPH0,
29         3,      MOV_direct1_direct2,    0x7c, SFR_DPL1,
30         3,      MOV_direct1_direct2,    0x7b, SFR_DPH1,
31         3,      MOV_DPTR_data16,        0,      0,
32 #define HIGH_START      21
33 #define LOW_START       22
34         0,
35 };
36
37
38 static uint8_t write8[] = {
39         2,      MOV_A_data,     0,
40 #define DATA_BYTE       2
41         1,      MOVX_atDPTR_A,
42         1,      INC_DPTR,
43         0
44 };
45
46 static uint8_t read8[] = {
47         1,      MOVX_A_atDPTR,
48         1,      INC_DPTR,
49         0,
50 };
51
52 static uint8_t  memory_fini[] = {
53         2,      MOV_A_direct,           0x7f,
54         3,      MOV_direct1_direct2,    SFR_DPL0, 0x7e,
55         3,      MOV_direct1_direct2,    SFR_DPH0, 0x7d,
56         3,      MOV_direct1_direct2,    SFR_DPL1, 0x7c,
57         3,      MOV_direct1_direct2,    SFR_DPH1, 0x7b,
58         0,
59 };
60
61 uint8_t
62 ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
63 {
64         int i, nl = 0;
65         memory_init[HIGH_START] = addr >> 8;
66         memory_init[LOW_START] = addr;
67         (void) ccdbg_execute(dbg, memory_init);
68         for (i = 0; i < nbytes; i++) {
69                 write8[DATA_BYTE] = *bytes++;
70                 ccdbg_execute(dbg, write8);
71                 if ((i & 0xf) == 0xf) {
72                         ccdbg_debug(CC_DEBUG_MEMORY, ".");
73                         ccdbg_flush();
74                         nl = 1;
75                 }
76                 if ((i & 0xff) == 0xff) {
77                         ccdbg_debug(CC_DEBUG_MEMORY, "\n");
78                         nl = 0;
79                 }
80         }
81         (void) ccdbg_execute(dbg, memory_fini);
82         if (nl)
83                 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
84         return 0;
85 }
86
87 uint8_t
88 ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes)
89 {
90         int i, nl = 0;
91         memory_init[HIGH_START] = addr >> 8;
92         memory_init[LOW_START] = addr;
93         (void) ccdbg_execute(dbg, memory_init);
94         for (i = 0; i < nbytes; i++) {
95                 *bytes++ = ccdbg_execute(dbg, read8);
96                 if ((i & 0xf) == 0xf) {
97                         ccdbg_debug(CC_DEBUG_MEMORY, ".");
98                         ccdbg_flush();
99                         nl = 1;
100                 }
101                 if ((i & 0xff) == 0xff) {
102                         ccdbg_debug(CC_DEBUG_MEMORY, "\n");
103                         nl = 0;
104                 }
105         }
106         (void) ccdbg_execute(dbg, memory_fini);
107         if (nl)
108                 ccdbg_debug(CC_DEBUG_MEMORY, "\n");
109         return 0;
110 }
111
112 uint8_t
113 ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte)
114 {
115         return ccdbg_write_memory(dbg, addr, &byte, 1);
116 }
117
118 uint8_t
119 ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset)
120 {
121         ccdbg_write_memory(dbg, image->address + offset, image->data, image->length);
122         return 0;
123 }
124
125 struct hex_image *
126 ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length)
127 {
128         struct hex_image *image;
129         
130         image = calloc(sizeof(struct hex_image) + length, 1);
131         image->address = address;
132         image->length = length;
133         memset(image->data, 0xff, length);
134         ccdbg_read_memory(dbg, address, image->data, length);
135         return image;
136 }
137
138 static uint8_t sfr_init[] = {
139         2,      MOV_direct_A,           0x7f,
140         0,
141 };
142
143 static uint8_t sfr_fini[] = {
144         2,      MOV_A_direct,           0x7f,
145         0,
146 };
147
148 static uint8_t sfr_read[] = {
149         2,      MOV_A_direct,           0,
150 #define SFR_READ_ADDR   2
151         0,
152 };
153
154 static uint8_t sfr_write[] = {
155         3,      MOV_direct_data,        0,      0,
156 #define SFR_WRITE_ADDR  2
157 #define SFR_WRITE_DATA  3
158         0,
159 };
160
161 uint8_t
162 ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
163 {
164         int     i;
165         (void) ccdbg_execute(dbg, sfr_init);
166         for (i = 0; i < nbytes; i++) {
167                 sfr_read[SFR_READ_ADDR] = addr + i;
168                 *bytes++ = ccdbg_execute(dbg, sfr_read);
169         }
170         (void) ccdbg_execute(dbg, sfr_fini);
171         return 0;
172 }
173
174 uint8_t
175 ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes)
176 {
177         int     i;
178         
179         for (i = 0; i < nbytes; i++) {
180                 sfr_write[SFR_WRITE_ADDR] = addr + i;
181                 sfr_write[SFR_WRITE_DATA] = *bytes++;
182                 ccdbg_execute(dbg, sfr_write);
183         }
184         return 0;
185 }