mdebug

cortex m series debugger
git clone http://frotz.net/git/mdebug.git
Log | Files | Refs | README | LICENSE

efr32bg2x.c (4309B)


      1 // agents/efr32bg2x.c
      2 //
      3 // Copyright 2022 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 <agent/flash.h>
     22 #include <fw/io.h>
     23 
     24 #define CMU_CLKEN1_SET 0x40009068
     25 #define CMU_CLKEN1_MSC     (1U<<17)
     26 
     27 #define MSC_WRITECTRL      0x4003000C
     28 #define MSC_WRITECTRL_SET  0x4003100C
     29 #define MSC_WRITECTRL_CLR  0x4003200C
     30 #define MSC_WRITECMD       0x40030010
     31 #define MSC_WRITECMD_SET   0x40031010
     32 #define MSC_WRITECMD_CLR   0x40032010
     33 #define MSC_ADDRB          0x40030014
     34 #define MSC_WDATA          0x40030018
     35 #define MSC_STATUS         0x4003001C
     36 
     37 #define MSC_WRITECTRL_WREN 1
     38 
     39 #define MSC_WRITECMD_WRITEND   (1U<<2)
     40 #define MSC_WRITECMD_ERASEPAGE (1U<<1)
     41 
     42 #define MSC_STATUS_WREADY         (1U<<27)
     43 #define MSC_STATUS_PWRON          (1U<<24)
     44 #define MSC_STATUS_REGLOCK        (1U<<16)
     45 #define MSC_STATUS_TIMEOUT        (1U<<6)
     46 #define MSC_STATUS_PENDING        (1U<<5)
     47 #define MSC_STATUS_ERASEABORTYED  (1U<<4)
     48 #define MSC_STATUS_WDATAREADY     (1U<<3)
     49 #define MSC_STATUS_INVADDR        (1U<<2)
     50 #define MSC_STATUS_LOCKED         (1U<<1)
     51 #define MSC_STATUS_BUSY           (1U<<0)
     52 
     53 static unsigned FLASH_PAGE_SIZE = 8192;
     54 static unsigned FLASH_SIZE = 352 * 1024;
     55 
     56 int flash_agent_setup(flash_agent *agent) {
     57 	// TODO - validate part ID
     58 	if (0) {
     59 		// unknown part
     60 		return ERR_INVALID;
     61 	}
     62 
     63 	// TODO: read from userdata
     64 	agent->flash_size = FLASH_SIZE;
     65 
     66 	return ERR_NONE;
     67 }
     68 
     69 int flash_agent_erase(u32 flash_addr, u32 length) {
     70 	unsigned v;
     71 	int status = ERR_NONE;
     72 	if (flash_addr > FLASH_SIZE) {
     73 		return ERR_INVALID;
     74 	}
     75 	if (flash_addr & (FLASH_PAGE_SIZE - 1)) {
     76 		return ERR_ALIGNMENT;
     77 	}
     78 
     79 	writel(CMU_CLKEN1_MSC, CMU_CLKEN1_SET);
     80 	writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_SET);
     81 	while (length > 0) {
     82 		writel(flash_addr, MSC_ADDRB);
     83 		v = readl(MSC_STATUS);
     84 		if (v & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED)) {
     85 			status = ERR_INVALID;
     86 			break;
     87 		}
     88 		if (!(v & MSC_STATUS_WREADY)) {
     89 			status = ERR_FAIL;
     90 			break;
     91 		}
     92 		if (length > FLASH_PAGE_SIZE) {
     93 			length -= FLASH_PAGE_SIZE;
     94 		} else {
     95 			length = 0;
     96 		}
     97 		writel(MSC_WRITECMD_ERASEPAGE, MSC_WRITECMD_SET);
     98 		while (readl(MSC_STATUS) & MSC_STATUS_BUSY) ;
     99 		for (unsigned n = 0; n < FLASH_PAGE_SIZE; n += 4) {
    100 			if (readl(flash_addr + n) != 0xFFFFFFFF) {
    101 				status = ERR_FAIL;
    102 				goto done;
    103 			}
    104 		}
    105 		flash_addr += FLASH_PAGE_SIZE;
    106 	}
    107 done:
    108 	writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_CLR);
    109 	return status;
    110 }
    111 
    112 int flash_agent_write(u32 flash_addr, const void *_data, u32 length) {
    113 	int status = ERR_NONE;
    114 	const unsigned *data = _data;
    115 	unsigned v;
    116 	if (flash_addr > FLASH_SIZE) {
    117 		return ERR_INVALID;
    118 	}
    119 	if ((flash_addr & 3) || (length & 3)) {
    120 		return ERR_ALIGNMENT;
    121 	}
    122 	writel(CMU_CLKEN1_MSC, CMU_CLKEN1_SET);
    123 	writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_SET);
    124 	while (length > 0) {
    125 		writel(flash_addr, MSC_ADDRB);
    126 		v = readl(MSC_STATUS);
    127 		if (v & (MSC_STATUS_INVADDR | MSC_STATUS_LOCKED)) {
    128 			status = ERR_INVALID;
    129 			break;
    130 		}
    131 		if (!(v & MSC_STATUS_WREADY)) {
    132 			status = ERR_FAIL;
    133 			break;
    134 		}
    135 		writel(*data, MSC_WDATA);
    136 		while (readl(MSC_STATUS) & MSC_STATUS_BUSY) ;
    137 		if (readl(flash_addr) != *data) {
    138 			status = ERR_FAIL;
    139 			goto done;
    140 		}
    141 		data++;
    142 		length -= 4;
    143 		flash_addr += 4;
    144 	}
    145 done:
    146 	writel(MSC_WRITECTRL_WREN, MSC_WRITECTRL_CLR);
    147 	return status;
    148 }
    149 
    150 int flash_agent_ioctl(u32 op, void *ptr, u32 arg0, u32 arg1) {
    151 	return ERR_INVALID;
    152 }
    153 
    154 const flash_agent __attribute((section(".vectors"))) FlashAgent = {
    155 	.magic =	AGENT_MAGIC,
    156 	.version =	AGENT_VERSION,
    157 	.flags =	0,
    158 	.load_addr =	LOADADDR,
    159 	.data_addr =	LOADADDR + 0x400,
    160 	.data_size =	0x4000,
    161 	.flash_addr =	FLASH_BASE,
    162 	.flash_size =	0,
    163 	.setup =	flash_agent_setup,
    164 	.erase =	flash_agent_erase,
    165 	.write =	flash_agent_write,
    166 	.ioctl =	flash_agent_ioctl,
    167 };