summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2021-03-29 10:04:04 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2021-04-01 00:52:57 -0400
commit89acde6af2c9d8ff4a647e7abd737b18333cad80 (patch)
tree92c9ec13b6292c1cbc2abf6b0692fff49e95cd02
parent058a9ec9453fed05872d10c72913bbc7034d32d8 (diff)
downloadrockbox-89acde6af2c9d8ff4a647e7abd737b18333cad80.tar.gz
rockbox-89acde6af2c9d8ff4a647e7abd737b18333cad80.zip
H10 PP Crash -- Fixed
This appears to finally fix the issue turns out the status register we were writing was only for the CPU COP cache flush wiped out the CPU cache -- Added some defines to cut down on the magic numbers Added some comments explaining such Set the address to full 20 bit address 0x1FFFFF which is then left shifted 11 internally -- somewhere around 4GB? Link explains the cache status bits https://daniel.haxx.se/sansa/memory_controller.txt Change-Id: I57b7187c2f71a5b54ce145bf3a21ed492a8993cb
-rw-r--r--firmware/export/pp5020.h6
-rw-r--r--firmware/target/arm/pp/system-pp502x.c81
2 files changed, 60 insertions, 27 deletions
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 073d33e494..0d2ffc4d94 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -584,8 +584,10 @@
584#define CACHE_DATA_BASE (*(volatile unsigned long*)(0xf0000000)) 584#define CACHE_DATA_BASE (*(volatile unsigned long*)(0xf0000000))
585/* 0xf0002000-0xf0003fff */ 585/* 0xf0002000-0xf0003fff */
586#define CACHE_DATA_MIRROR_BASE (*(volatile unsigned long*)(0xf0002000)) 586#define CACHE_DATA_MIRROR_BASE (*(volatile unsigned long*)(0xf0002000))
587/* 0xf0004000-0xf0007fff */ 587/* 0xf0004000-0xf0005fff */
588#define CACHE_STATUS_BASE (*(volatile unsigned long*)(0xf0004000)) 588#define CACHE_STATUS_BASE_CPU (*(volatile unsigned long*)(0xf0004000))
589/* 0xf0006000-0xf0007fff */
590#define CACHE_STATUS_BASE_COP (*(volatile unsigned long*)(0xf0006000))
589#define CACHE_FLUSH_BASE (*(volatile unsigned long*)(0xf0008000)) 591#define CACHE_FLUSH_BASE (*(volatile unsigned long*)(0xf0008000))
590#define CACHE_INVALID_BASE (*(volatile unsigned long*)(0xf000c000)) 592#define CACHE_INVALID_BASE (*(volatile unsigned long*)(0xf000c000))
591#define MMAP_PHYS_READ_MASK 0x0100 593#define MMAP_PHYS_READ_MASK 0x0100
diff --git a/firmware/target/arm/pp/system-pp502x.c b/firmware/target/arm/pp/system-pp502x.c
index ad0577c38f..686e2ac3bd 100644
--- a/firmware/target/arm/pp/system-pp502x.c
+++ b/firmware/target/arm/pp/system-pp502x.c
@@ -29,6 +29,21 @@
29#include "button-target.h" 29#include "button-target.h"
30#include "usb_drv.h" 30#include "usb_drv.h"
31 31
32/* Bit 0 - 20: Cached Address */
33#define CACHE_ADDRESS_MASK ((1<<21)-1)
34/* Bit 22: Cache line dirty */
35#define CACHE_LINE_DIRTY (1<<22)
36/* Bit 23: Cache line valid */
37#define CACHE_LINE_VALID (1<<23)
38/* Cache Size - 8K*/
39#define CACHE_SIZE 0x2000
40
41/*Initial memory address used to prime cache
42 * could be targeted to a more 'important' address
43 * Note: Don't start at 0x0, as the compiler thinks it's a
44 * null pointer dereference and will helpfully blow up the code. */
45#define CACHED_INIT_ADDR CACHEALIGN_UP(0x2000)
46
32#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE) 47#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
33extern void TIMER1(void); 48extern void TIMER1(void);
34extern void TIMER2(void); 49extern void TIMER2(void);
@@ -44,7 +59,7 @@ unsigned char probed_ramsize;
44 59
45void __attribute__((interrupt("IRQ"))) irq_handler(void) 60void __attribute__((interrupt("IRQ"))) irq_handler(void)
46{ 61{
47 if(CURRENT_CORE == CPU) 62 if(IF_COP_CORE(CPU) == CPU)
48 { 63 {
49 if (CPU_INT_STAT & TIMER1_MASK) { 64 if (CPU_INT_STAT & TIMER1_MASK) {
50 TIMER1(); 65 TIMER1();
@@ -218,6 +233,39 @@ void ICODE_ATTR commit_dcache(void)
218 } 233 }
219} 234}
220 235
236static void ICODE_ATTR cache_invalidate_special(void)
237{
238 /* Cache lines which are not marked as valid can cause memory
239 * corruption when there are many writes to and code fetches from
240 * cached memory. This workaround points all cache status to the
241 * maximum line address and marked valid but not dirty. Since that area
242 * is never accessed, the cache lines don't affect anything, and
243 * they're effectively discarded. Interrupts must be disabled here
244 * because any change they make to cached memory could be discarded.
245 * A status word is 32 bits and is mirrored four times for each cache line
246 bit 0-20 line_address >> 11
247 bit 21 unused?
248 bit 22 line_dirty
249 bit 23 line_valid
250 bit 24-31 unused?
251 */
252 register volatile unsigned long *p;
253 if (IF_COP_CORE(CPU) == CPU)
254 {
255 for (p = &CACHE_STATUS_BASE_CPU;
256 p < (&CACHE_STATUS_BASE_CPU) + CACHE_SIZE;
257 p += CACHEALIGN_BITS) /* sizeof(p) * CACHEALIGN_BITS */
258 *p = CACHE_LINE_VALID | CACHE_ADDRESS_MASK;
259 }
260 else
261 {
262 for (p = &CACHE_STATUS_BASE_COP;
263 p < (&CACHE_STATUS_BASE_COP) + CACHE_SIZE;
264 p += CACHEALIGN_BITS)
265 *p = CACHE_LINE_VALID | CACHE_ADDRESS_MASK;
266 }
267}
268
221void ICODE_ATTR commit_discard_idcache(void) 269void ICODE_ATTR commit_discard_idcache(void)
222{ 270{
223 if (CACHE_CTL & CACHE_CTL_ENABLE) 271 if (CACHE_CTL & CACHE_CTL_ENABLE)
@@ -225,21 +273,7 @@ void ICODE_ATTR commit_discard_idcache(void)
225 register int istat = disable_interrupt_save(IRQ_FIQ_STATUS); 273 register int istat = disable_interrupt_save(IRQ_FIQ_STATUS);
226 274
227 commit_dcache(); 275 commit_dcache();
228 276 cache_invalidate_special();
229 /* Cache lines which are not marked as valid can cause memory
230 * corruption when there are many writes to and code fetches from
231 * cached memory. This workaround points all cache status words past
232 * end of RAM and marks them as valid, but not dirty. Since that area
233 * is never accessed, the cache lines don't affect anything, and
234 * they're effectively discarded. Interrupts must be disabled here
235 * because any change they make to cached memory could be discarded.
236 */
237
238 register volatile unsigned long *p;
239 for (p = &CACHE_STATUS_BASE;
240 p < (&CACHE_STATUS_BASE) + 512*16/sizeof(*p);
241 p += 16/sizeof(*p))
242 *p = ((MEMORYSIZE*0x100000) >> 11) | 0x800000;
243 277
244 restore_interrupt(istat); 278 restore_interrupt(istat);
245 } 279 }
@@ -258,7 +292,7 @@ static void init_cache(void)
258 292
259#ifndef BOOTLOADER 293#ifndef BOOTLOADER
260 /* what's this do? */ 294 /* what's this do? */
261 CACHE_PRIORITY |= CURRENT_CORE == CPU ? 0x10 : 0x20; 295 CACHE_PRIORITY |= IF_COP_CORE(CPU) == CPU ? 0x10 : 0x20;
262#endif 296#endif
263 297
264 /* Cache if (addr & mask) >> 16 == (mask & match) >> 16: 298 /* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
@@ -278,11 +312,8 @@ static void init_cache(void)
278 * can run from cached RAM, rewriting of cache status words may not 312 * can run from cached RAM, rewriting of cache status words may not
279 * be safe and the cache is filled instead by reading. */ 313 * be safe and the cache is filled instead by reading. */
280 314
281 /* Note: Don't start at 0x0, as the compiler thinks it's a 315 register volatile char *p = (volatile char *)CACHED_INIT_ADDR;
282 null pointer dereference and will helpfully blow up the code. */ 316 for (;p < (volatile char *)CACHED_INIT_ADDR + CACHE_SIZE; p += CACHEALIGN_SIZE)
283
284 register volatile char *p;
285 for (p = (volatile char *)0x1000; p < (volatile char *)0x3000; p += 0x10)
286 (void)*p; 317 (void)*p;
287} 318}
288#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */ 319#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */
@@ -293,7 +324,7 @@ static void init_cache(void)
293void scale_suspend_core(bool suspend) ICODE_ATTR; 324void scale_suspend_core(bool suspend) ICODE_ATTR;
294void scale_suspend_core(bool suspend) 325void scale_suspend_core(bool suspend)
295{ 326{
296 unsigned int core = CURRENT_CORE; 327 unsigned int core = IF_COP_CORE(CPU);
297 IF_COP( unsigned int othercore = 1 - core; ) 328 IF_COP( unsigned int othercore = 1 - core; )
298 static int oldstatus IBSS_ATTR; 329 static int oldstatus IBSS_ATTR;
299 330
@@ -442,7 +473,7 @@ static void pp_set_cpu_frequency(long frequency)
442#ifndef BOOTLOADER 473#ifndef BOOTLOADER
443void system_init(void) 474void system_init(void)
444{ 475{
445 if (CURRENT_CORE == CPU) 476 if (IF_COP_CORE(CPU) == CPU)
446 { 477 {
447#if defined (IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(IPOD_COLOR) 478#if defined (IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(IPOD_COLOR)
448 /* set minimum startup configuration */ 479 /* set minimum startup configuration */
@@ -628,7 +659,7 @@ void system_exception_wait(void)
628 COP_INT_DIS = -1; 659 COP_INT_DIS = -1;
629 660
630 /* Halt */ 661 /* Halt */
631 PROC_CTL(CURRENT_CORE) = 0x40000000; 662 PROC_CTL(IF_COP_CORE(CPU)) = 0x40000000;
632 while (1); 663 while (1);
633} 664}
634 665