xdebug

next generation of mdebug (work in progress)
git clone http://frotz.net/git/xdebug.git
Log | Files | Refs | README

pico.c (3927B)


      1 // agents/pico.c
      2 //
      3 // Copyright 2020 Brian Swetland <swetland@frotz.net>
      4 //
      5 // Licensed under the Apache License, Version 2.0 (the "License");
      6 // you may not use this file except in compliance with the License.
      7 // You may obtain a copy of the License at
      8 //
      9 //     http://www.apache.org/licenses/LICENSE-2.0
     10 //
     11 // Unless required by applicable law or agreed to in writing, software
     12 // distributed under the License is distributed on an "AS IS" BASIS,
     13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 // See the License for the specific language governing permissions and
     15 // limitations under the License.
     16 
     17 #define LOADADDR	0x20000400
     18 
     19 #define FLASH_BASE	0x00000000
     20 
     21 #include <stdint.h>
     22 #include <agent/flash.h>
     23 #include <fw/io.h>
     24 
     25 static unsigned FLASH_BLOCK_SIZE = 256;
     26 static unsigned FLASH_PAGE_SIZE = 4096;
     27 static unsigned FLASH_SIZE = 4 * 1024 * 1024;
     28 
     29 #define FLASH_XIP_BASE 0x10000000
     30 
     31 #define CODE(c1, c2) (((c2) << 8) | (c1))
     32 
     33 #define ROM_LOOKUP_FN_PTR 0x18
     34 #define ROM_FN_TABLE_PTR 0x14
     35 
     36 // lookup fn for code using ROM lookup helper and ROM fn table
     37 void* lookup_fn(uint32_t code) {
     38 	void* (*lookup)(uint32_t table, uint32_t code) =
     39 		(void*) (uintptr_t) *((uint16_t*) ROM_LOOKUP_FN_PTR);
     40 
     41 	return lookup(*((uint16_t*)ROM_FN_TABLE_PTR), code);
     42 }
     43 
     44 static void (*_flash_connect)(void);
     45 static void (*_flash_exit_xip)(void);
     46 static void (*_flash_erase)(uint32_t addr, uint32_t len,
     47 		uint32_t block_size, uint32_t block_cmd);
     48 static void (*_flash_write)(uint32_t addr, const void* data, uint32_t len);
     49 static void (*_flash_flush_cache)(void);
     50 static void (*_flash_enter_xip)(void);
     51 
     52 // erase: addr and count must be 4096 aligned
     53 // write: addr and len must be 256 aligned 
     54 
     55 int flash_agent_setup(flash_agent *agent) {
     56 	// TODO - validate part ID
     57 	if (0) {
     58 		// unknown part
     59 		return ERR_INVALID;
     60 	}
     61 
     62 	_flash_connect = lookup_fn(CODE('I','F'));
     63 	_flash_exit_xip = lookup_fn(CODE('E','X'));
     64 	_flash_erase = lookup_fn(CODE('R','E'));
     65 	_flash_write = lookup_fn(CODE('R','P'));
     66 	_flash_flush_cache = lookup_fn(CODE('F','C'));
     67 	_flash_enter_xip = lookup_fn(CODE('C','X'));
     68 
     69 	// TODO: obtain from spi flash	
     70 	agent->flash_size = FLASH_SIZE;
     71 
     72 	return ERR_NONE;
     73 }
     74 
     75 int flash_agent_erase(uint32_t flash_addr, uint32_t length) {
     76 	if (flash_addr > FLASH_SIZE) {
     77 		return ERR_INVALID;
     78 	}
     79 	if (flash_addr & (FLASH_PAGE_SIZE - 1)) {
     80 		return ERR_ALIGNMENT;
     81 	}
     82 	if (length & (FLASH_PAGE_SIZE-1)) {
     83 		length = (length & (~(FLASH_PAGE_SIZE-1))) + FLASH_PAGE_SIZE;
     84 	}
     85 
     86 	_flash_connect();
     87 	_flash_exit_xip();
     88 	_flash_erase(flash_addr, length, 65536, 0xD8);
     89 	_flash_flush_cache();
     90 	_flash_enter_xip();
     91 
     92 	uint32_t* flash = (void*) (flash_addr + FLASH_XIP_BASE);
     93 	for (uint32_t n = 0; n < length; n+= 4) {
     94 		if (*flash++ != 0xFFFFFFFF) {
     95 			return ERR_FAIL;
     96 		}
     97 	}
     98 
     99 	return ERR_NONE;
    100 }
    101 
    102 int flash_agent_write(uint32_t flash_addr, const void *data, uint32_t length) {
    103 	if (flash_addr > FLASH_SIZE) {
    104 		return ERR_INVALID;
    105 	}
    106 	if (flash_addr & (FLASH_BLOCK_SIZE - 1)) {
    107 		return ERR_ALIGNMENT;
    108 	}
    109 	if (length & (FLASH_BLOCK_SIZE-1)) {
    110 		length = (length & (~(FLASH_BLOCK_SIZE-1))) + FLASH_BLOCK_SIZE;
    111 	}
    112 
    113 	_flash_connect();
    114 	_flash_exit_xip();
    115 	_flash_write(flash_addr, data, length);
    116 	_flash_flush_cache();
    117 	_flash_enter_xip();
    118 
    119 	uint32_t* flash = (void*) (flash_addr + FLASH_XIP_BASE);
    120 	const uint32_t* xdata = data;
    121 	for (uint32_t n = 0; n < length; n += 4) {
    122 		if (*flash++ != *xdata++) {
    123 			return ERR_FAIL;
    124 		}
    125 	}
    126 
    127 	return ERR_NONE;
    128 }
    129 
    130 int flash_agent_ioctl(uint32_t op, void *ptr, uint32_t arg0, uint32_t arg1) {
    131 	return ERR_INVALID;
    132 }
    133 
    134 const flash_agent __attribute((section(".vectors"))) FlashAgent = {
    135 	.magic =	AGENT_MAGIC,
    136 	.version =	AGENT_VERSION,
    137 	.flags =	0,
    138 	.load_addr =	LOADADDR,
    139 	.data_addr =	LOADADDR + 0x400,
    140 	.data_size =	0x4000,
    141 	.flash_addr =	FLASH_BASE,
    142 	.flash_size =	0,
    143 	.setup =	flash_agent_setup,
    144 	.erase =	flash_agent_erase,
    145 	.write =	flash_agent_write,
    146 	.ioctl =	flash_agent_ioctl,
    147 };