diff options
author | Edward Fewell | 2017-12-18 20:55:01 -0600 |
---|---|---|
committer | Edward Fewell | 2017-12-18 20:55:01 -0600 |
commit | 2749f0d0372b410be91cee7134fef4cd14da7bf4 (patch) | |
tree | e5dc98555be0839a3edb8e8af2aa7bfa88eee32f | |
parent | 9f688ff4b1fe0acf7b742b8682f66b75a0bb811f (diff) | |
download | openocd-2749f0d0372b410be91cee7134fef4cd14da7bf4.tar.gz openocd-2749f0d0372b410be91cee7134fef4cd14da7bf4.tar.xz openocd-2749f0d0372b410be91cee7134fef4cd14da7bf4.zip |
Add support for CC32xx and CC3220SF targets
-rw-r--r-- | openocd/Makefile.in | 45 | ||||
-rw-r--r-- | openocd/src/flash/nor/Makefile.am | 2 | ||||
-rw-r--r-- | openocd/src/flash/nor/cc3220sf.c | 435 | ||||
-rw-r--r-- | openocd/src/flash/nor/cc3220sf.h | 135 | ||||
-rw-r--r-- | openocd/src/flash/nor/drivers.c | 2 | ||||
-rw-r--r-- | openocd/tcl/board/ti_cc3220sf_launchpad.cfg | 7 | ||||
-rw-r--r-- | openocd/tcl/board/ti_cc32xx_launchpad.cfg | 7 | ||||
-rw-r--r-- | openocd/tcl/target/ti_cc32xx.cfg | 71 |
8 files changed, 684 insertions, 20 deletions
diff --git a/openocd/Makefile.in b/openocd/Makefile.in index b52ccf6..399e401 100644 --- a/openocd/Makefile.in +++ b/openocd/Makefile.in | |||
@@ -238,26 +238,26 @@ am__objects_3 = src/flash/nor/aduc702x.lo src/flash/nor/aducm360.lo \ | |||
238 | src/flash/nor/at91sam4l.lo src/flash/nor/at91samd.lo \ | 238 | src/flash/nor/at91sam4l.lo src/flash/nor/at91samd.lo \ |
239 | src/flash/nor/at91sam3.lo src/flash/nor/at91sam7.lo \ | 239 | src/flash/nor/at91sam3.lo src/flash/nor/at91sam7.lo \ |
240 | src/flash/nor/atsamv.lo src/flash/nor/avrf.lo \ | 240 | src/flash/nor/atsamv.lo src/flash/nor/avrf.lo \ |
241 | src/flash/nor/cfi.lo src/flash/nor/dsp5680xx_flash.lo \ | 241 | src/flash/nor/cc3220sf.lo src/flash/nor/cfi.lo \ |
242 | src/flash/nor/efm32.lo src/flash/nor/em357.lo \ | 242 | src/flash/nor/dsp5680xx_flash.lo src/flash/nor/efm32.lo \ |
243 | src/flash/nor/faux.lo src/flash/nor/fm3.lo \ | 243 | src/flash/nor/em357.lo src/flash/nor/faux.lo \ |
244 | src/flash/nor/fm4.lo src/flash/nor/jtagspi.lo \ | 244 | src/flash/nor/fm3.lo src/flash/nor/fm4.lo \ |
245 | src/flash/nor/kinetis.lo src/flash/nor/kinetis_ke.lo \ | 245 | src/flash/nor/jtagspi.lo src/flash/nor/kinetis.lo \ |
246 | src/flash/nor/lpc2000.lo src/flash/nor/lpc288x.lo \ | 246 | src/flash/nor/kinetis_ke.lo src/flash/nor/lpc2000.lo \ |
247 | src/flash/nor/lpc2900.lo src/flash/nor/lpcspifi.lo \ | 247 | src/flash/nor/lpc288x.lo src/flash/nor/lpc2900.lo \ |
248 | src/flash/nor/mdr.lo src/flash/nor/mrvlqspi.lo \ | 248 | src/flash/nor/lpcspifi.lo src/flash/nor/mdr.lo \ |
249 | src/flash/nor/msp432.lo src/flash/nor/niietcm4.lo \ | 249 | src/flash/nor/mrvlqspi.lo src/flash/nor/msp432.lo \ |
250 | src/flash/nor/non_cfi.lo src/flash/nor/nrf51.lo \ | 250 | src/flash/nor/niietcm4.lo src/flash/nor/non_cfi.lo \ |
251 | src/flash/nor/numicro.lo src/flash/nor/ocl.lo \ | 251 | src/flash/nor/nrf51.lo src/flash/nor/numicro.lo \ |
252 | src/flash/nor/pic32mx.lo src/flash/nor/psoc4.lo \ | 252 | src/flash/nor/ocl.lo src/flash/nor/pic32mx.lo \ |
253 | src/flash/nor/sim3x.lo src/flash/nor/spi.lo \ | 253 | src/flash/nor/psoc4.lo src/flash/nor/sim3x.lo \ |
254 | src/flash/nor/stmsmi.lo src/flash/nor/stellaris.lo \ | 254 | src/flash/nor/spi.lo src/flash/nor/stmsmi.lo \ |
255 | src/flash/nor/stm32f1x.lo src/flash/nor/stm32f2x.lo \ | 255 | src/flash/nor/stellaris.lo src/flash/nor/stm32f1x.lo \ |
256 | src/flash/nor/stm32lx.lo src/flash/nor/stm32l4x.lo \ | 256 | src/flash/nor/stm32f2x.lo src/flash/nor/stm32lx.lo \ |
257 | src/flash/nor/str7x.lo src/flash/nor/str9x.lo \ | 257 | src/flash/nor/stm32l4x.lo src/flash/nor/str7x.lo \ |
258 | src/flash/nor/str9xpec.lo src/flash/nor/tms470.lo \ | 258 | src/flash/nor/str9x.lo src/flash/nor/str9xpec.lo \ |
259 | src/flash/nor/virtual.lo src/flash/nor/xmc1xxx.lo \ | 259 | src/flash/nor/tms470.lo src/flash/nor/virtual.lo \ |
260 | src/flash/nor/xmc4xxx.lo | 260 | src/flash/nor/xmc1xxx.lo src/flash/nor/xmc4xxx.lo |
261 | am_src_flash_nor_libocdflashnor_la_OBJECTS = src/flash/nor/core.lo \ | 261 | am_src_flash_nor_libocdflashnor_la_OBJECTS = src/flash/nor/core.lo \ |
262 | src/flash/nor/tcl.lo $(am__objects_3) src/flash/nor/drivers.lo \ | 262 | src/flash/nor/tcl.lo $(am__objects_3) src/flash/nor/drivers.lo \ |
263 | $(am__objects_2) | 263 | $(am__objects_2) |
@@ -1479,6 +1479,7 @@ NOR_DRIVERS = \ | |||
1479 | src/flash/nor/at91sam7.c \ | 1479 | src/flash/nor/at91sam7.c \ |
1480 | src/flash/nor/atsamv.c \ | 1480 | src/flash/nor/atsamv.c \ |
1481 | src/flash/nor/avrf.c \ | 1481 | src/flash/nor/avrf.c \ |
1482 | src/flash/nor/cc3220sf.c \ | ||
1482 | src/flash/nor/cfi.c \ | 1483 | src/flash/nor/cfi.c \ |
1483 | src/flash/nor/dsp5680xx_flash.c \ | 1484 | src/flash/nor/dsp5680xx_flash.c \ |
1484 | src/flash/nor/efm32.c \ | 1485 | src/flash/nor/efm32.c \ |
@@ -1521,6 +1522,7 @@ NOR_DRIVERS = \ | |||
1521 | 1522 | ||
1522 | NORHEADERS = \ | 1523 | NORHEADERS = \ |
1523 | src/flash/nor/core.h \ | 1524 | src/flash/nor/core.h \ |
1525 | src/flash/nor/cc3220sf.h \ | ||
1524 | src/flash/nor/cfi.h \ | 1526 | src/flash/nor/cfi.h \ |
1525 | src/flash/nor/driver.h \ | 1527 | src/flash/nor/driver.h \ |
1526 | src/flash/nor/imp.h \ | 1528 | src/flash/nor/imp.h \ |
@@ -1741,6 +1743,8 @@ src/flash/nor/atsamv.lo: src/flash/nor/$(am__dirstamp) \ | |||
1741 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) | 1743 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) |
1742 | src/flash/nor/avrf.lo: src/flash/nor/$(am__dirstamp) \ | 1744 | src/flash/nor/avrf.lo: src/flash/nor/$(am__dirstamp) \ |
1743 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) | 1745 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) |
1746 | src/flash/nor/cc3220sf.lo: src/flash/nor/$(am__dirstamp) \ | ||
1747 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) | ||
1744 | src/flash/nor/cfi.lo: src/flash/nor/$(am__dirstamp) \ | 1748 | src/flash/nor/cfi.lo: src/flash/nor/$(am__dirstamp) \ |
1745 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) | 1749 | src/flash/nor/$(DEPDIR)/$(am__dirstamp) |
1746 | src/flash/nor/dsp5680xx_flash.lo: src/flash/nor/$(am__dirstamp) \ | 1750 | src/flash/nor/dsp5680xx_flash.lo: src/flash/nor/$(am__dirstamp) \ |
@@ -2560,6 +2564,7 @@ distclean-compile: | |||
2560 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/at91samd.Plo@am__quote@ | 2564 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/at91samd.Plo@am__quote@ |
2561 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/atsamv.Plo@am__quote@ | 2565 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/atsamv.Plo@am__quote@ |
2562 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/avrf.Plo@am__quote@ | 2566 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/avrf.Plo@am__quote@ |
2567 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/cc3220sf.Plo@am__quote@ | ||
2563 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/cfi.Plo@am__quote@ | 2568 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/cfi.Plo@am__quote@ |
2564 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/core.Plo@am__quote@ | 2569 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/core.Plo@am__quote@ |
2565 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/drivers.Plo@am__quote@ | 2570 | @AMDEP_TRUE@@am__include@ @am__quote@src/flash/nor/$(DEPDIR)/drivers.Plo@am__quote@ |
diff --git a/openocd/src/flash/nor/Makefile.am b/openocd/src/flash/nor/Makefile.am index 2b6753c..4b40326 100644 --- a/openocd/src/flash/nor/Makefile.am +++ b/openocd/src/flash/nor/Makefile.am | |||
@@ -17,6 +17,7 @@ NOR_DRIVERS = \ | |||
17 | %D%/at91sam7.c \ | 17 | %D%/at91sam7.c \ |
18 | %D%/atsamv.c \ | 18 | %D%/atsamv.c \ |
19 | %D%/avrf.c \ | 19 | %D%/avrf.c \ |
20 | %D%/cc3220sf.c \ | ||
20 | %D%/cfi.c \ | 21 | %D%/cfi.c \ |
21 | %D%/dsp5680xx_flash.c \ | 22 | %D%/dsp5680xx_flash.c \ |
22 | %D%/efm32.c \ | 23 | %D%/efm32.c \ |
@@ -59,6 +60,7 @@ NOR_DRIVERS = \ | |||
59 | 60 | ||
60 | NORHEADERS = \ | 61 | NORHEADERS = \ |
61 | %D%/core.h \ | 62 | %D%/core.h \ |
63 | %D%/cc3220sf.h \ | ||
62 | %D%/cfi.h \ | 64 | %D%/cfi.h \ |
63 | %D%/driver.h \ | 65 | %D%/driver.h \ |
64 | %D%/imp.h \ | 66 | %D%/imp.h \ |
diff --git a/openocd/src/flash/nor/cc3220sf.c b/openocd/src/flash/nor/cc3220sf.c new file mode 100644 index 0000000..6841c58 --- /dev/null +++ b/openocd/src/flash/nor/cc3220sf.c | |||
@@ -0,0 +1,435 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2017 by Texas Instruments, Inc. * | ||
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, * | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
12 | * GNU General Public License for more details. * | ||
13 | * * | ||
14 | * You should have received a copy of the GNU General Public License * | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | #include "config.h" | ||
20 | #endif | ||
21 | |||
22 | #include "imp.h" | ||
23 | #include "cc3220sf.h" | ||
24 | #include <helper/time_support.h> | ||
25 | #include <target/algorithm.h> | ||
26 | #include <target/armv7m.h> | ||
27 | |||
28 | #define FLASH_TIMEOUT 5000 | ||
29 | |||
30 | struct cc3220sf_bank { | ||
31 | bool probed; | ||
32 | struct working_area *working_area; | ||
33 | struct armv7m_algorithm armv7m_info; | ||
34 | }; | ||
35 | |||
36 | static int cc3220sf_mass_erase(struct flash_bank *bank) | ||
37 | { | ||
38 | struct target *target = bank->target; | ||
39 | bool done; | ||
40 | long long start_ms; | ||
41 | long long elapsed_ms; | ||
42 | uint32_t value; | ||
43 | |||
44 | int retval = ERROR_OK; | ||
45 | |||
46 | if (TARGET_HALTED != target->state) { | ||
47 | LOG_ERROR("Target not halted"); | ||
48 | return ERROR_TARGET_NOT_HALTED; | ||
49 | } | ||
50 | |||
51 | /* Set starting address to erase to zero */ | ||
52 | value = 0; | ||
53 | retval = target_write_buffer(target, FMA_REGISTER_ADDR, | ||
54 | sizeof(value), (uint8_t *)&value); | ||
55 | if (ERROR_OK != retval) | ||
56 | return retval; | ||
57 | |||
58 | /* Write the MERASE bit of the FMC register */ | ||
59 | value = FMC_DEFAULT_VALUE | FMC_MERASE_BIT; | ||
60 | retval = target_write_buffer(target, FMC_REGISTER_ADDR, | ||
61 | sizeof(value), (uint8_t *)&value); | ||
62 | if (ERROR_OK != retval) | ||
63 | return retval; | ||
64 | |||
65 | /* Poll the MERASE bit until the mass erase is complete */ | ||
66 | done = false; | ||
67 | start_ms = timeval_ms(); | ||
68 | while (!done) { | ||
69 | retval = target_read_buffer(target, FMC_REGISTER_ADDR, | ||
70 | sizeof(value), (uint8_t *)&value); | ||
71 | if (ERROR_OK != retval) | ||
72 | return retval; | ||
73 | |||
74 | if ((value & FMC_MERASE_BIT) == 0) { | ||
75 | /* Bit clears when mass erase is finished */ | ||
76 | done = true; | ||
77 | } else { | ||
78 | elapsed_ms = timeval_ms() - start_ms; | ||
79 | if (elapsed_ms > 500) | ||
80 | keep_alive(); | ||
81 | if (elapsed_ms > FLASH_TIMEOUT) | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | if (!done) { | ||
87 | /* Mass erase timed out waiting for confirmation */ | ||
88 | return ERROR_FAIL; | ||
89 | } | ||
90 | |||
91 | /* Mark all sectors erased */ | ||
92 | if (0 != bank->sectors) { | ||
93 | for (int i = 0; i < bank->num_sectors; i++) | ||
94 | bank->sectors[i].is_erased = 1; | ||
95 | } | ||
96 | |||
97 | return retval; | ||
98 | } | ||
99 | |||
100 | FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command) | ||
101 | { | ||
102 | struct cc3220sf_bank *cc3220sf_bank; | ||
103 | |||
104 | if (CMD_ARGC < 6) | ||
105 | return ERROR_COMMAND_SYNTAX_ERROR; | ||
106 | |||
107 | cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank)); | ||
108 | if (0 == cc3220sf_bank) | ||
109 | return ERROR_FAIL; | ||
110 | |||
111 | /* Initialize private flash information */ | ||
112 | cc3220sf_bank->probed = false; | ||
113 | cc3220sf_bank->working_area = 0; | ||
114 | |||
115 | /* Finish initialization of flash bank */ | ||
116 | bank->driver_priv = cc3220sf_bank; | ||
117 | bank->next = 0; | ||
118 | |||
119 | return ERROR_OK; | ||
120 | } | ||
121 | |||
122 | static int cc3220sf_erase(struct flash_bank *bank, int first, int last) | ||
123 | { | ||
124 | struct target *target = bank->target; | ||
125 | bool done; | ||
126 | long long start_ms; | ||
127 | long long elapsed_ms; | ||
128 | uint32_t address; | ||
129 | uint32_t value; | ||
130 | |||
131 | int retval = ERROR_OK; | ||
132 | |||
133 | if (TARGET_HALTED != target->state) { | ||
134 | LOG_ERROR("Target not halted"); | ||
135 | return ERROR_TARGET_NOT_HALTED; | ||
136 | } | ||
137 | |||
138 | /* Do a mass erase if user requested all sectors of flash */ | ||
139 | if ((first == 0) && (last == (bank->num_sectors - 1))) { | ||
140 | /* Request mass erase of flash */ | ||
141 | return cc3220sf_mass_erase(bank); | ||
142 | } | ||
143 | |||
144 | /* Erase requested sectors one by one */ | ||
145 | for (int i = first; i <= last; i++) { | ||
146 | |||
147 | /* Determine address of sector to erase */ | ||
148 | address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE; | ||
149 | |||
150 | /* Set starting address to erase */ | ||
151 | retval = target_write_buffer(target, FMA_REGISTER_ADDR, | ||
152 | sizeof(address), (uint8_t *)&address); | ||
153 | if (ERROR_OK != retval) | ||
154 | return retval; | ||
155 | |||
156 | /* Write the ERASE bit of the FMC register */ | ||
157 | value = FMC_DEFAULT_VALUE | FMC_ERASE_BIT; | ||
158 | retval = target_write_buffer(target, FMC_REGISTER_ADDR, | ||
159 | sizeof(value), (uint8_t *)&value); | ||
160 | if (ERROR_OK != retval) | ||
161 | return retval; | ||
162 | |||
163 | /* Poll the ERASE bit until the erase is complete */ | ||
164 | done = false; | ||
165 | start_ms = timeval_ms(); | ||
166 | while (!done) { | ||
167 | retval = target_read_buffer(target, FMC_REGISTER_ADDR, | ||
168 | sizeof(value), (uint8_t *)&value); | ||
169 | if (ERROR_OK != retval) | ||
170 | return retval; | ||
171 | |||
172 | if ((value & FMC_ERASE_BIT) == 0) { | ||
173 | /* Bit clears when mass erase is finished */ | ||
174 | done = true; | ||
175 | } else { | ||
176 | elapsed_ms = timeval_ms() - start_ms; | ||
177 | if (elapsed_ms > 500) | ||
178 | keep_alive(); | ||
179 | if (elapsed_ms > FLASH_TIMEOUT) | ||
180 | break; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | if (!done) { | ||
185 | /* Sector erase timed out waiting for confirmation */ | ||
186 | return ERROR_FAIL; | ||
187 | } | ||
188 | |||
189 | /* Mark the sector as erased */ | ||
190 | if (0 != bank->sectors) | ||
191 | bank->sectors[i].is_erased = 1; | ||
192 | } | ||
193 | |||
194 | return retval; | ||
195 | } | ||
196 | |||
197 | static int cc3220sf_protect(struct flash_bank *bank, int set, int first, | ||
198 | int last) | ||
199 | { | ||
200 | return ERROR_OK; | ||
201 | } | ||
202 | |||
203 | static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer, | ||
204 | uint32_t offset, uint32_t count) | ||
205 | { | ||
206 | struct target *target = bank->target; | ||
207 | struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; | ||
208 | struct reg_param reg_params[3]; | ||
209 | uint32_t address; | ||
210 | uint32_t remaining; | ||
211 | uint32_t words; | ||
212 | uint32_t end_address = offset + count - 1; | ||
213 | uint32_t sector; | ||
214 | uint32_t result; | ||
215 | |||
216 | int retval = ERROR_OK; | ||
217 | |||
218 | if (TARGET_HALTED != target->state) { | ||
219 | LOG_ERROR("Target not halted"); | ||
220 | return ERROR_TARGET_NOT_HALTED; | ||
221 | } | ||
222 | |||
223 | /* Check for working area to use for flash helper algorithm */ | ||
224 | if (0 != cc3220sf_bank->working_area) | ||
225 | target_free_working_area(target, cc3220sf_bank->working_area); | ||
226 | retval = target_alloc_working_area(target, ALGO_WORKING_SIZE, | ||
227 | &cc3220sf_bank->working_area); | ||
228 | if (ERROR_OK != retval) | ||
229 | return retval; | ||
230 | |||
231 | /* Confirm the defined working address is the area we need to use */ | ||
232 | if (ALGO_BASE_ADDR != cc3220sf_bank->working_area->address) | ||
233 | return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; | ||
234 | |||
235 | /* Write flash helper algorithm into target memory */ | ||
236 | retval = target_write_buffer(target, ALGO_BASE_ADDR, | ||
237 | sizeof(cc3220sf_algo), cc3220sf_algo); | ||
238 | if (ERROR_OK != retval) | ||
239 | return retval; | ||
240 | |||
241 | /* Initialize the ARMv7m specific info to run the algorithm */ | ||
242 | cc3220sf_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; | ||
243 | cc3220sf_bank->armv7m_info.core_mode = ARM_MODE_THREAD; | ||
244 | |||
245 | /* Initialize register params for flash helper algorithm */ | ||
246 | init_reg_param(®_params[0], "r0", 32, PARAM_OUT); | ||
247 | init_reg_param(®_params[1], "r1", 32, PARAM_OUT); | ||
248 | init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); | ||
249 | |||
250 | /* Prepare to write to flash */ | ||
251 | address = FLASH_BASE_ADDR + offset; | ||
252 | remaining = count; | ||
253 | |||
254 | while (remaining > 0) { | ||
255 | /* Helper parameters are passed in registers R0-R2 */ | ||
256 | /* Set address to write to and start of data buffer */ | ||
257 | buf_set_u32(reg_params[0].value, 0, 32, ALGO_BUFFER_ADDR); | ||
258 | buf_set_u32(reg_params[1].value, 0, 32, address); | ||
259 | |||
260 | /* Download data to write into memory buffer */ | ||
261 | if (remaining >= ALGO_BUFFER_SIZE) { | ||
262 | /* Fill up buffer with data to flash */ | ||
263 | retval = target_write_buffer(target, ALGO_BUFFER_ADDR, | ||
264 | ALGO_BUFFER_SIZE, buffer); | ||
265 | if (ERROR_OK != retval) | ||
266 | break; | ||
267 | |||
268 | /* Count to write is in 32-bit words */ | ||
269 | words = ALGO_BUFFER_SIZE / 4; | ||
270 | |||
271 | /* Bump variables to next data */ | ||
272 | address += ALGO_BUFFER_SIZE; | ||
273 | buffer += ALGO_BUFFER_SIZE; | ||
274 | remaining -= ALGO_BUFFER_SIZE; | ||
275 | } else { | ||
276 | /* Fill buffer with what's left of the data */ | ||
277 | retval = target_write_buffer(target, ALGO_BUFFER_ADDR, | ||
278 | remaining, buffer); | ||
279 | if (ERROR_OK != retval) | ||
280 | break; | ||
281 | |||
282 | /* Calculate the final word count to write */ | ||
283 | words = remaining / 4; | ||
284 | if (0 != (remaining % 4)) | ||
285 | words++; | ||
286 | |||
287 | /* All done after this last buffer */ | ||
288 | remaining = 0; | ||
289 | } | ||
290 | |||
291 | /* Set number of words to write */ | ||
292 | buf_set_u32(reg_params[2].value, 0, 32, words); | ||
293 | |||
294 | /* Execute the flash helper algorithm */ | ||
295 | retval = target_run_algorithm(target, 0, 0, 3, reg_params, | ||
296 | ALGO_BASE_ADDR, 0, FLASH_TIMEOUT, | ||
297 | &cc3220sf_bank->armv7m_info); | ||
298 | if (ERROR_OK != retval) { | ||
299 | LOG_ERROR("cc3220sf: Flash algorithm failed to run"); | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | /* Check that all words were written to flash */ | ||
304 | result = buf_get_u32(reg_params[2].value, 0, 32); | ||
305 | if (0 != result) { | ||
306 | retval = ERROR_FAIL; | ||
307 | LOG_ERROR("cc3220sf: Flash operation failed"); | ||
308 | break; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | /* Free resources */ | ||
313 | destroy_reg_param(®_params[0]); | ||
314 | destroy_reg_param(®_params[1]); | ||
315 | destroy_reg_param(®_params[2]); | ||
316 | |||
317 | target_free_working_area(target, cc3220sf_bank->working_area); | ||
318 | cc3220sf_bank->working_area = 0; | ||
319 | |||
320 | if (ERROR_OK == retval) { | ||
321 | /* Mark flashed sectors as "not erased" */ | ||
322 | while (offset <= end_address) { | ||
323 | sector = offset / FLASH_SECTOR_SIZE; | ||
324 | bank->sectors[sector].is_erased = 0; | ||
325 | offset += FLASH_SECTOR_SIZE; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return retval; | ||
330 | } | ||
331 | |||
332 | static int cc3220sf_probe(struct flash_bank *bank) | ||
333 | { | ||
334 | struct target *target = bank->target; | ||
335 | struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; | ||
336 | |||
337 | uint32_t base; | ||
338 | uint32_t size; | ||
339 | int num_sectors; | ||
340 | int bank_id; | ||
341 | |||
342 | bank_id = bank->bank_number; | ||
343 | |||
344 | if (TARGET_HALTED != target->state) { | ||
345 | LOG_ERROR("Target not halted"); | ||
346 | return ERROR_TARGET_NOT_HALTED; | ||
347 | } | ||
348 | |||
349 | if (0 == bank_id) { | ||
350 | base = FLASH_BASE_ADDR; | ||
351 | size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE; | ||
352 | num_sectors = FLASH_NUM_SECTORS; | ||
353 | } else { | ||
354 | /* Invalid bank number somehow */ | ||
355 | return ERROR_FAIL; | ||
356 | } | ||
357 | |||
358 | if (0 != bank->sectors) { | ||
359 | free(bank->sectors); | ||
360 | bank->sectors = 0; | ||
361 | } | ||
362 | |||
363 | bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); | ||
364 | if (0 == bank->sectors) | ||
365 | return ERROR_FAIL; | ||
366 | |||
367 | bank->base = base; | ||
368 | bank->size = size; | ||
369 | bank->num_sectors = num_sectors; | ||
370 | |||
371 | for (int i = 0; i < num_sectors; i++) { | ||
372 | bank->sectors[i].offset = i * FLASH_SECTOR_SIZE; | ||
373 | bank->sectors[i].size = FLASH_SECTOR_SIZE; | ||
374 | bank->sectors[i].is_erased = -1; | ||
375 | bank->sectors[i].is_protected = 0; | ||
376 | } | ||
377 | |||
378 | /* We've successfully determined the stats on this flash bank */ | ||
379 | cc3220sf_bank->probed = true; | ||
380 | |||
381 | /* If we fall through to here, then all went well */ | ||
382 | |||
383 | return ERROR_OK; | ||
384 | } | ||
385 | |||
386 | static int cc3220sf_auto_probe(struct flash_bank *bank) | ||
387 | { | ||
388 | struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; | ||
389 | |||
390 | int retval = ERROR_OK; | ||
391 | |||
392 | if (0 != bank->bank_number) { | ||
393 | /* Invalid bank number somehow */ | ||
394 | return ERROR_FAIL; | ||
395 | } | ||
396 | |||
397 | if (!cc3220sf_bank->probed) | ||
398 | retval = cc3220sf_probe(bank); | ||
399 | |||
400 | return retval; | ||
401 | } | ||
402 | |||
403 | static int cc3220sf_protect_check(struct flash_bank *bank) | ||
404 | { | ||
405 | return ERROR_OK; | ||
406 | } | ||
407 | |||
408 | static int cc3220sf_info(struct flash_bank *bank, char *buf, int buf_size) | ||
409 | { | ||
410 | int printed = 0; | ||
411 | |||
412 | printed = snprintf(buf, buf_size, "CC3220SF with 1MB internal flash\n"); | ||
413 | |||
414 | buf += printed; | ||
415 | buf_size -= printed; | ||
416 | |||
417 | if (0 > buf_size) | ||
418 | return ERROR_BUF_TOO_SMALL; | ||
419 | |||
420 | return ERROR_OK; | ||
421 | } | ||
422 | |||
423 | struct flash_driver cc3220sf_flash = { | ||
424 | .name = "cc3220sf", | ||
425 | .flash_bank_command = cc3220sf_flash_bank_command, | ||
426 | .erase = cc3220sf_erase, | ||
427 | .protect = cc3220sf_protect, | ||
428 | .write = cc3220sf_write, | ||
429 | .read = default_flash_read, | ||
430 | .probe = cc3220sf_probe, | ||
431 | .auto_probe = cc3220sf_auto_probe, | ||
432 | .erase_check = default_flash_blank_check, | ||
433 | .protect_check = cc3220sf_protect_check, | ||
434 | .info = cc3220sf_info, | ||
435 | }; | ||
diff --git a/openocd/src/flash/nor/cc3220sf.h b/openocd/src/flash/nor/cc3220sf.h new file mode 100644 index 0000000..40bbad7 --- /dev/null +++ b/openocd/src/flash/nor/cc3220sf.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /*************************************************************************** | ||
2 | * Copyright (C) 2017 by Texas Instruments, Inc. * | ||
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, * | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
12 | * GNU General Public License for more details. * | ||
13 | * * | ||
14 | * You should have received a copy of the GNU General Public License * | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * | ||
16 | ***************************************************************************/ | ||
17 | |||
18 | #ifndef OPENOCD_FLASH_NOR_CC3220SF_H | ||
19 | #define OPENOCD_FLASH_NOR_CC3220SF_H | ||
20 | |||
21 | /* CC3220SF device types */ | ||
22 | #define CC3220_NO_TYPE 0 /* Device type not determined yet */ | ||
23 | #define CC3220_OTHER 1 /* CC3220 variant without flash */ | ||
24 | #define CC3220SF 2 /* CC3220SF variant with flash */ | ||
25 | |||
26 | /* Flash parameters */ | ||
27 | #define FLASH_BASE_ADDR 0x01000000 | ||
28 | #define FLASH_SECTOR_SIZE 2048 | ||
29 | #define FLASH_NUM_SECTORS 512 | ||
30 | |||
31 | /* CC2200SF flash registers */ | ||
32 | #define FMA_REGISTER_ADDR 0x400FD000 | ||
33 | #define FMC_REGISTER_ADDR 0x400FD008 | ||
34 | #define FMC_DEFAULT_VALUE 0xA4420000 | ||
35 | #define FMC_ERASE_BIT 0x00000002 | ||
36 | #define FMC_MERASE_BIT 0x00000004 | ||
37 | |||
38 | /* Flash helper algorithm addresses and values */ | ||
39 | #define ALGO_BASE_ADDR 0x20000000 | ||
40 | #define ALGO_BUFFER_ADDR 0x20000400 | ||
41 | #define ALGO_BUFFER_SIZE 0x1000 | ||
42 | #define ALGO_WORKING_SIZE 0x1400 | ||
43 | |||
44 | /* Flash helper algorithm for CC3220SF (assembled by hand) */ | ||
45 | const uint8_t cc3220sf_algo[] = { | ||
46 | /* ; flash programming key */ | ||
47 | 0xdf, 0xf8, 0x7c, 0xa0, /* 1: ldr r10, =0xa4420001 */ | ||
48 | /* ; base of FWB */ | ||
49 | 0xdf, 0xf8, 0x7c, 0xb0, /* ldr r11, =0x400fd100 */ | ||
50 | /* ; base of flash regs */ | ||
51 | 0xdf, 0xf8, 0x7c, 0xc0, /* ldr r12, =0x400fd000 */ | ||
52 | /* ; is the dest address 32-bit aligned? */ | ||
53 | 0x01, 0xf0, 0x7f, 0x03, /* and r3, r1, #0x7f */ | ||
54 | 0x00, 0x2b, /* cmp r3, #0 */ | ||
55 | /* ; if not aligned do one word at a time */ | ||
56 | 0x1e, 0xd1, /* bne %6 */ | ||
57 | |||
58 | /* ; program using the write buffers */ | ||
59 | /* ; start the buffer word counter at 0 */ | ||
60 | 0x4f, 0xf0, 0x00, 0x04, /* ldr r4, =0 */ | ||
61 | /* ; store the dest addr in FMA */ | ||
62 | 0xcc, 0xf8, 0x00, 0x10, /* str r1, [r12] */ | ||
63 | /* ; get the word to write to FWB */ | ||
64 | 0x03, 0x68, /* 2: ldr r3, [r0] */ | ||
65 | /* ; store the word in the FWB */ | ||
66 | 0xcb, 0xf8, 0x00, 0x30, /* str r3, [r11] */ | ||
67 | /* ; increment the FWB pointer */ | ||
68 | 0x0b, 0xf1, 0x04, 0x0b, /* add r11, r11, #4 */ | ||
69 | /* ; increment the source pointer */ | ||
70 | 0x00, 0xf1, 0x04, 0x00, /* add r0, r0, #4 */ | ||
71 | /* ; decrement the total word counter */ | ||
72 | 0xa2, 0xf1, 0x01, 0x02, /* sub r2, r2, #1 */ | ||
73 | /* ; increment the buffer word counter */ | ||
74 | 0x04, 0xf1, 0x01, 0x04, /* add r4, r4, #1 */ | ||
75 | /* ; increment the dest pointer */ | ||
76 | 0x01, 0xf1, 0x04, 0x01, /* add r1, r1, #4 */ | ||
77 | /* ; is the total word counter now 0? */ | ||
78 | 0x00, 0x2a, /* cmp r2, #0 */ | ||
79 | /* ; go to end if total word counter is 0 */ | ||
80 | 0x01, 0xd0, /* beq %3 */ | ||
81 | /* ; is the buffer word counter now 32? */ | ||
82 | 0x20, 0x2c, /* cmp r4, #32 */ | ||
83 | /* ; go to continue to fill buffer */ | ||
84 | 0xee, 0xd1, /* bne %2 */ | ||
85 | /* ; store the key and write bit to FMC2 */ | ||
86 | 0xcc, 0xf8, 0x20, 0xa0, /* 3: str r10, [r12, #0x20] */ | ||
87 | /* ; read FMC2 */ | ||
88 | 0xdc, 0xf8, 0x20, 0x30, /* 4: ldr r3, [r12, #0x20] */ | ||
89 | /* ; see if the write bit is cleared */ | ||
90 | 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #1 */ | ||
91 | /* ; go to read FMC2 if bit not cleared */ | ||
92 | 0xfa, 0xd1, /* bne %4 */ | ||
93 | /* ; is the total word counter now 0? */ | ||
94 | 0x00, 0x2a, /* cmp r2, #0 */ | ||
95 | /* ; go if there is more to program */ | ||
96 | 0xd7, 0xd1, /* bne %1 */ | ||
97 | 0x13, 0xe0, /* b %5 */ | ||
98 | |||
99 | /* ; program 1 word at a time */ | ||
100 | /* ; store the dest addr in FMA */ | ||
101 | 0xcc, 0xf8, 0x00, 0x10, /* 6: str r1, [r12] */ | ||
102 | /* ; get the word to write to FMD */ | ||
103 | 0x03, 0x68, /* ldr r3, [r0] */ | ||
104 | /* ; store the word in FMD */ | ||
105 | 0xcc, 0xf8, 0x04, 0x30, /* str r3, [r12, #0x4] */ | ||
106 | /* ; store the key and write bit to FMC */ | ||
107 | 0xcc, 0xf8, 0x08, 0xa0, /* str r10, [r12, #0x8] */ | ||
108 | /* ; read FMC */ | ||
109 | 0xdc, 0xf8, 0x08, 0x30, /* 7: ldr r3, [r12, #0x8] */ | ||
110 | /* ; see if the write bit is cleared */ | ||
111 | 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #1 */ | ||
112 | /* ; go to read FMC if bit not cleared */ | ||
113 | 0xfa, 0xd1, /* bne %7 */ | ||
114 | /* ; decrement the total word counter */ | ||
115 | 0xa2, 0xf1, 0x01, 0x02, /* sub r2, r2, #1 */ | ||
116 | /* ; increment the source pointer */ | ||
117 | 0x00, 0xf1, 0x04, 0x00, /* add r0, r0, #4 */ | ||
118 | /* ; increment the dest pointer */ | ||
119 | 0x01, 0xf1, 0x04, 0x01, /* add r1, r1, #4 */ | ||
120 | /* ; is the total word counter now 0 */ | ||
121 | 0x00, 0x2a, /* cmp r2, #0 */ | ||
122 | /* ; go if there is more to program */ | ||
123 | 0xc2, 0xd1, /* bne %1 */ | ||
124 | /* ; end */ | ||
125 | 0x00, 0xbe, /* 5: bkpt #0 */ | ||
126 | 0x01, 0xbe, /* bkpt #1 */ | ||
127 | 0xfc, 0xe7, /* b %5 */ | ||
128 | |||
129 | /* ; flash register address constants */ | ||
130 | 0x01, 0x00, 0x42, 0xa4, /* .word 0xa4420001 */ | ||
131 | 0x00, 0xd1, 0x0f, 0x40, /* .word 0x400fd100 */ | ||
132 | 0x00, 0xd0, 0x0f, 0x40 /* .word 0x400fd000 */ | ||
133 | }; | ||
134 | |||
135 | #endif /* OPENOCD_FLASH_NOR_CC3220SF_H */ | ||
diff --git a/openocd/src/flash/nor/drivers.c b/openocd/src/flash/nor/drivers.c index 99b212f..a8d6167 100644 --- a/openocd/src/flash/nor/drivers.c +++ b/openocd/src/flash/nor/drivers.c | |||
@@ -30,6 +30,7 @@ extern struct flash_driver at91sam7_flash; | |||
30 | extern struct flash_driver at91samd_flash; | 30 | extern struct flash_driver at91samd_flash; |
31 | extern struct flash_driver atsamv_flash; | 31 | extern struct flash_driver atsamv_flash; |
32 | extern struct flash_driver avr_flash; | 32 | extern struct flash_driver avr_flash; |
33 | extern struct flash_driver cc3220sf_flash; | ||
33 | extern struct flash_driver cfi_flash; | 34 | extern struct flash_driver cfi_flash; |
34 | extern struct flash_driver dsp5680xx_flash; | 35 | extern struct flash_driver dsp5680xx_flash; |
35 | extern struct flash_driver efm32_flash; | 36 | extern struct flash_driver efm32_flash; |
@@ -83,6 +84,7 @@ static struct flash_driver *flash_drivers[] = { | |||
83 | &at91samd_flash, | 84 | &at91samd_flash, |
84 | &atsamv_flash, | 85 | &atsamv_flash, |
85 | &avr_flash, | 86 | &avr_flash, |
87 | &cc3220sf_flash, | ||
86 | &cfi_flash, | 88 | &cfi_flash, |
87 | &dsp5680xx_flash, | 89 | &dsp5680xx_flash, |
88 | &efm32_flash, | 90 | &efm32_flash, |
diff --git a/openocd/tcl/board/ti_cc3220sf_launchpad.cfg b/openocd/tcl/board/ti_cc3220sf_launchpad.cfg new file mode 100644 index 0000000..205f3cd --- /dev/null +++ b/openocd/tcl/board/ti_cc3220sf_launchpad.cfg | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # TI CC3220SF-LaunchXL Evaluation Kit | ||
3 | # | ||
4 | source [find interface/xds110.cfg] | ||
5 | transport select swd | ||
6 | source [find target/ti_cc3220sf.cfg] | ||
7 | adapter_khz 2500 | ||
diff --git a/openocd/tcl/board/ti_cc32xx_launchpad.cfg b/openocd/tcl/board/ti_cc32xx_launchpad.cfg new file mode 100644 index 0000000..edd58ea --- /dev/null +++ b/openocd/tcl/board/ti_cc32xx_launchpad.cfg | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # TI CC32xx-LaunchXL Evaluation Kit | ||
3 | # | ||
4 | source [find interface/xds110.cfg] | ||
5 | transport select swd | ||
6 | source [find target/ti_cc32xx.cfg] | ||
7 | adapter_khz 2500 | ||
diff --git a/openocd/tcl/target/ti_cc32xx.cfg b/openocd/tcl/target/ti_cc32xx.cfg new file mode 100644 index 0000000..bc2316b --- /dev/null +++ b/openocd/tcl/target/ti_cc32xx.cfg | |||
@@ -0,0 +1,71 @@ | |||
1 | # | ||
2 | # Texas Instruments CC32xx - ARM Cortex-M4 | ||
3 | # | ||
4 | # http://www.ti.com/product/CC3200 | ||
5 | # http://www.ti.com/product/CC3220 | ||
6 | # | ||
7 | |||
8 | source [find target/swj-dp.tcl] | ||
9 | source [find target/icepick.cfg] | ||
10 | |||
11 | if { [info exists CHIPNAME] } { | ||
12 | set _CHIPNAME $CHIPNAME | ||
13 | } else { | ||
14 | set _CHIPNAME cc32xx | ||
15 | } | ||
16 | |||
17 | # | ||
18 | # Main DAP | ||
19 | # | ||
20 | if { [info exists DAP_TAPID] } { | ||
21 | set _DAP_TAPID $DAP_TAPID | ||
22 | } else { | ||
23 | if {[using_jtag]} { | ||
24 | set _DAP_TAPID 0x4BA00477 | ||
25 | } else { | ||
26 | set _DAP_TAPID 0x2BA01477 | ||
27 | } | ||
28 | } | ||
29 | |||
30 | if {[using_jtag]} { | ||
31 | jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable | ||
32 | jtag configure $_CHIPNAME.dap -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" | ||
33 | } else { | ||
34 | swj_newdap $_CHIPNAME dap -expected-id $_DAP_TAPID | ||
35 | } | ||
36 | |||
37 | # | ||
38 | # ICEpick-C (JTAG route controller) | ||
39 | # | ||
40 | if { [info exists JRC_TAPID] } { | ||
41 | set _JRC_TAPID $JRC_TAPID | ||
42 | } else { | ||
43 | set _JRC_TAPID 0x0B97C02F | ||
44 | } | ||
45 | |||
46 | if {[using_jtag]} { | ||
47 | jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version | ||
48 | jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" | ||
49 | } | ||
50 | |||
51 | set _TARGETNAME $_CHIPNAME.cpu | ||
52 | target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.dap | ||
53 | |||
54 | if { [info exists WORKAREASIZE] } { | ||
55 | set _WORKAREASIZE $WORKAREASIZE | ||
56 | } else { | ||
57 | set _WORKAREASIZE 0x2000 | ||
58 | } | ||
59 | |||
60 | $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 | ||
61 | |||
62 | if { ![using_hla] } { | ||
63 | cortex_m reset_config sysresetreq | ||
64 | } | ||
65 | |||
66 | gdb_memory_map enable | ||
67 | gdb_flash_program enable | ||
68 | |||
69 | $_TARGETNAME configure -event gdb-attach { | ||
70 | halt | ||
71 | } | ||