diff --git a/mcu/tools/memdumptablegen.py b/mcu/tools/memdumptablegen.py
new file mode 100755
index 0000000..43afed0
--- /dev/null
+++ b/mcu/tools/memdumptablegen.py
@@ -0,0 +1,251 @@
+import os, subprocess, re, sys, struct
+import binascii
+
+debug_log = True
+tool_chain_prefix = ''
+
+def log(stuff):
+  if not debug_log:
+    return
+  print(stuff)
+   
+print(sys.argv)
+
+if len(sys.argv) < 5:
+  print("Usage: %s [Output file] [Toolchain prefix] [C file] [ELF file] (gcc option file ~inc_def.tmp)"%(sys.argv[0]))
+  exit(0)
+
+elf_file = sys.argv[4]
+cmd_list = []
+if len(sys.argv) >= 6:
+  cmd_list = ['@'+sys.argv[5]]
+  
+tool_chain_prefix = sys.argv[2]
+step1o_fname = os.path.join(os.path.dirname(sys.argv[1]),'~mdmp_step1.o')
+step2o_fname = os.path.join(os.path.dirname(sys.argv[1]),'~mdmp_step2.o')
+if subprocess.call([tool_chain_prefix + 'gcc', '-G0', '-EL', '-c', '-o' + step1o_fname] + cmd_list + [sys.argv[3]]) != 0:
+  exit(1)
+
+if subprocess.call([tool_chain_prefix + 'ld', '-EL', '--entry=mdmp_profile_list', '--just-symbols=' + elf_file, '-o' + step2o_fname, step1o_fname]) != 0:
+  exit(2)
+
+def readSymbolTableV2(objFile, prefix = False):
+	global tool_chain_prefix
+
+	sec_tbl = []
+	r = re.compile(br'\[\s?(\d+)\](.*)')
+	proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-WS', objFile], stdout=subprocess.PIPE)
+	for line in proc.stdout:
+		m = r.search(line.rstrip())
+		if m is None:
+			continue
+			
+		s = m.group(2).split()
+		sec_tbl.append({'addr':int(s[2], 16), 'offset':int(s[3], 16), 'size':int(s[4], 16)})
+
+	symDict = {}
+	r = re.compile(br'\d+: (\w*)\s+(\d+).+ (\w+) ([^\s]+)$')
+
+	proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-Ws', objFile], stdout=subprocess.PIPE)
+	for line in proc.stdout:
+		m = r.search(line)
+		if m is None: continue
+		s = m.group(4)
+		if prefix is not False and not s.startswith(prefix): continue
+		
+		v = int(m.group(1), 16)
+		if m.group(3).isdigit():
+			t = sec_tbl[int(m.group(3))]
+			v = (v - t['addr']) + t['offset']
+		symDict.update({s:{'val':v, 'size':int(m.group(2))}})
+
+	return symDict
+
+def readFromFileV2(objFile, offset, size, isNullTerminated = False):
+	fd = open(objFile, 'rb')
+	fd.seek(offset)
+	d = fd.read(size)
+	if (isNullTerminated):
+		b = d.find(b'\x00')
+		if b is not False: d=d[:b]
+	return d
+	
+_sec_info = None
+def getDataSectionInfo():
+  global _sec_info
+  if _sec_info == None:
+    proc = subprocess.Popen([tool_chain_prefix + 'readelf', '-S', step2o_fname], stdout=subprocess.PIPE)
+    r = re.compile(br'\[\s?(\d+)\](.*)')
+    for line in proc.stdout:
+      m = r.search(line.rstrip())
+      if m is None:
+        continue
+      s = m.group(2).split()
+      if s[0] != b'.data':
+        continue
+      _sec_info = {'idx':m.group(1), 'addr':int(s[2], 16), 'offset':int(s[3], 16), 'size':int(s[4], 16)}
+  return _sec_info
+
+_sym_table = None
+def getSymbolTable():
+  global _sym_table
+  if _sym_table is None:
+    _sym_table = []
+    proc = subprocess.Popen([tool_chain_prefix + 'readelf', '--syms', '--wide', step2o_fname], stdout=subprocess.PIPE)
+    for line in proc.stdout:
+      s = line.split()
+      if len(s) != 8 or s[3] != b'OBJECT' or not s[6].isdigit():
+        continue
+      _sym_table.append({'symbol': s[7], 'addr':int(s[1], 16), 'size':int(s[2])})
+    log('==== Symbol Table ====')
+    log(_sym_table)
+    log('======================')
+  return _sym_table
+
+def getAddrOffsetSizeByAddr(address):
+  sec_info = getDataSectionInfo()  
+  if address < sec_info['addr'] or address >= sec_info['addr'] + sec_info['size']:
+    raise ValueError('Address not in range.')
+  offset = address-sec_info['addr']+sec_info['offset']
+  
+  sym_table = getSymbolTable()
+  for e in sym_table:
+    if e['addr'] == address:
+      return {'addr': address, 'offset': offset, 'size':e['size']}
+  raise IndexError('Address not found in symbol list.')      
+  return None  
+  
+def getAddrBySymbol(symbol):
+  sym_table = getSymbolTable()
+  for e in sym_table:
+    if e['symbol'] == symbol:
+      return e['addr']
+  raise IndexError('Symbol not found.')
+  return None
+  
+
+def getElementListByAddr(address, fd, fmt):
+  r = []
+  if address != 0:
+    aos = getAddrOffsetSizeByAddr(address)
+    # log(['getElementListByAddr',aos])
+    fd.seek(aos['offset'])
+    bytes_remain = aos['size']
+    size = struct.calcsize(fmt)
+    while bytes_remain > 0:
+      r.append(struct.unpack(fmt, fd.read(size)))
+      bytes_remain -= size
+  return r
+
+
+bin_obj = {}
+
+def genBinObj(addr, build_function, *args):
+  global bin_obj
+  if addr == 0: 
+    return
+  if addr in bin_obj:
+    log('Bin addr {:08X} already exists'.format(addr))
+    return
+  bin_obj[addr] = build_function(*args)
+  log('Bin addr {:08X} created'.format(addr))
+
+  
+def buildSelectiveTable(selective_tbl):
+  r = struct.pack('<I', len(selective_tbl))
+  for s in selective_tbl:
+    r = r + struct.pack('<IIBBxx', s[0], s[1], s[2], s[3])
+
+  return r
+
+
+def buildRegionTable(num_mem_type, num_option, region_tbl):
+  # Handle region table
+  option_size = (num_option+7)//8
+  mem = [bytearray(option_size) for y in range(num_mem_type)] 
+  for r in region_tbl:
+    mem_type = r[0]
+    for x in r[1:]:
+      if x == 0:
+        break
+      x=x-1
+      mem[mem_type][x//8] = mem[mem_type][x//8] ^ (1<<(x%8))
+      
+    # log(['Config:', r])
+    # log(['Mem:', mem])
+  
+  log(['num_mem_type:',num_mem_type])
+  log(['option_byte:', option_size])
+
+  r = struct.pack('<HH', num_mem_type, option_size)
+  for x in mem:
+    r = r + x
+    
+  return r
+
+
+# open object file  
+fd=open(step2o_fname, 'rb')
+
+# get information from object
+num_mem_type = getElementListByAddr(getAddrBySymbol(b'_mdmp_num_mem_type'), fd, '=I')[0][0]
+num_region_option = getElementListByAddr(getAddrBySymbol(b'_mdmp_num_region_option'), fd, '=I')[0][0]
+
+profile = []
+pid = 0
+for p in getElementListByAddr(getAddrBySymbol(b'mdmp_profile_list'), fd, '=III'):
+  log('Profile #{}: +0x{:X} -0x{:X}'.format(pid, p[0], p[1]))
+  genBinObj(p[0], buildRegionTable, num_mem_type, num_region_option, getElementListByAddr(p[0], fd, '=I'+'I'*num_region_option))
+  genBinObj(p[1], buildSelectiveTable, getElementListByAddr(p[1], fd, '=IIII'))
+  profile.append((p[0],p[1],p[2]))
+  pid = pid+1
+
+fd.close()
+
+# Write to binary file  
+fd_bin = open(sys.argv[1], 'wb+')
+
+profile_info_size = 8 + len(profile)*8
+fd_bin.seek(profile_info_size)
+
+bin_obj_offset = {0:0}
+for b in bin_obj:
+  bin_obj_offset[b] = fd_bin.tell()
+  fd_bin.write(bin_obj[b])
+
+# write eof pattern
+fd_bin.write(b'\x99\x17\x71\xCB')
+
+# Read build info
+try:
+	sym = readSymbolTableV2(elf_file, (b'RELEASE_VERNO_RW', b'BUILD_TIME_RW'))
+	build_verno = readFromFileV2(elf_file, sym[b'RELEASE_VERNO_RW$$Base']['val'], sym[b'RELEASE_VERNO_RW$$Length']['val'], isNullTerminated = True)
+	build_time = readFromFileV2(elf_file, sym[b'BUILD_TIME_RW$$Base']['val'], sym[b'BUILD_TIME_RW$$Length']['val'], isNullTerminated = True)
+	signature = bytearray(build_verno + b'_' + build_time)
+except Exception as err:
+	print("Cannot read build information!", err)
+
+signature_pos = fd_bin.tell()
+fd_bin.write(struct.pack('<H', len(signature)))
+fd_bin.write(signature)
+
+# from the end of binary
+fd_bin.write(struct.pack('<I', signature_pos))
+fd_bin.seek(0)
+
+profile_binary_magic = 0x1A424650
+fd_bin.write(struct.pack('<II', profile_binary_magic, len(profile)))
+for p in profile:
+  fd_bin.write(struct.pack('<HHI', bin_obj_offset[p[0]], bin_obj_offset[p[1]], p[2]))
+
+# add crc32 at file end
+fd_bin.seek(0)
+buf = fd_bin.read()
+crc32 = binascii.crc32(buf, profile_binary_magic) & 0xFFFFFFFF
+fd_bin.write(struct.pack('<I', crc32))
+output_size = fd_bin.tell()
+fd_bin.close()
+
+os.remove(step1o_fname)
+os.remove(step2o_fname)
+print ("Memory dump profile %s created. File size %d. CRC32 0x%08X"%(sys.argv[1], output_size, crc32))
