summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2015-11-17 13:25:28 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2015-11-17 13:35:09 +0100
commitf47f04b65fc7603ec5926dd5f941d6690a0daf91 (patch)
treedfb19cbe3eb22552df68f3d96aff62a6947bf489 /utils
parent5b7c9d40e749e96bd382e332ab9e25b6a18435b2 (diff)
downloadrockbox-f47f04b65fc7603ec5926dd5f941d6690a0daf91.tar.gz
rockbox-f47f04b65fc7603ec5926dd5f941d6690a0daf91.tar.bz2
rockbox-f47f04b65fc7603ec5926dd5f941d6690a0daf91.zip
hwstub: Add ajt213x lua interface for DSP block
With this you can upload and run code on DSP core in atj213x. The files can be produced using as2181. You can download this assembler from https://github.com/wodz/as2181 You should use extended mode (-x switch) since DSP core in atj is non standard and uses 24bit operands. PX register has different meaning as well and is used as MSB when loading other registers with immediates (immediate field is 16bit in instruction so to set register to 24bit value you need to store MSB in PX prior to this). MAC MR is 56bit accordingly. HIP interface seems to be mapped at standard addresses (except that regular 218x doesn't have HIP). Have a fun! Change-Id: I9a80ca0dd3718ba8435ae8579bfffa66e067e022
Diffstat (limited to 'utils')
-rw-r--r--utils/hwstub/tools/lua/atj.lua1
-rw-r--r--utils/hwstub/tools/lua/atj/dsp.lua158
2 files changed, 159 insertions, 0 deletions
diff --git a/utils/hwstub/tools/lua/atj.lua b/utils/hwstub/tools/lua/atj.lua
index 1f59a141fc..a1ad0c7505 100644
--- a/utils/hwstub/tools/lua/atj.lua
+++ b/utils/hwstub/tools/lua/atj.lua
@@ -7,3 +7,4 @@ ATJ = {}
hwstub.soc:select("atj213x")
require "atj/gpio"
require "atj/lcm"
+require "atj/dsp"
diff --git a/utils/hwstub/tools/lua/atj/dsp.lua b/utils/hwstub/tools/lua/atj/dsp.lua
new file mode 100644
index 0000000000..93c80e36ef
--- /dev/null
+++ b/utils/hwstub/tools/lua/atj/dsp.lua
@@ -0,0 +1,158 @@
+ATJ.dsp = {}
+
+-- Ungate DSP clock
+function ATJ.dsp.init()
+ HW.CMU.DEVCLKEN.write(bit32.bor(HW.CMU.DEVCLKEN.read(), 0x10010))
+end
+
+-- Connect memory to DSP bus
+-- Start DSP core
+function ATJ.dsp.start()
+ HW.SRAMOC.CTL.write(0) -- connect memory to DSP bus
+ HW.DSP.CTL.write(0x187) -- reset DSP
+ hwstub.mdelay(100)
+ HW.DSP.CTL.write(0x18f) -- run DSP from PM@0 clocked from HOSC
+end
+
+-- Stop DSP core
+-- Connect memory to MIPS bus
+function ATJ.dsp.stop()
+ HW.DSP.CTL.write(0x107)
+ HW.DSP.CTL.write(0x0f)
+ HW.SRAMOC.CTL.write(0xf0) -- connect memory to MIPS bus
+end
+
+function ATJ.dsp.setclock(mhz)
+ local dpck = math.floor(mhz/6)
+ if dpck < 2 then dpck = 2 end
+
+ HW.DSP.CTL.write(0x0f) -- stop DSP clock
+ HW.CMU.DSPPLL.DPCK.write(dpck) -- setup pll
+ HW.CMU.DSPPLL.DPEN.write(1) -- enable pll
+ hwstub.mdelay(10) -- wait for PLL to settle
+ HW.DSP.CTL.write(0x10f) -- run DSP again clocked from DSP PLL
+end
+
+-- Start the execution of DSP program and wait
+-- specified number of miliseconds before stoping DSP
+-- Then you can inspect DSP memories from MIPS side
+function ATJ.dsp.run(msec)
+ DSP.stop()
+ DSP.start()
+ hwstub.mdelay(msec)
+ DSP.stop()
+end
+
+-- Clear DSP program memory
+function ATJ.dsp.clearPM()
+ DSP.stop()
+ for i=0,16*1024-1,4 do DEV.write32(0xb4040000+i, 0) end
+end
+
+-- Clear DSP data memory
+function ATJ.dsp.clearDM()
+ DSP.stop()
+ for i=0,16*1024-1,4 do DEV.write32(0xb4050000+i, 0) end
+end
+
+-- write single 24bit value to DSP memory
+-- 0xb4040000 is start address of PM
+-- 0xb4050000 is start address of DM
+function ATJ.dsp.write(addr,val)
+ DEV.write8(addr+0, bit32.band(val, 0xff))
+ DEV.write8(addr+1, bit32.band(bit32.rshift(val, 8), 0xff))
+ DEV.write8(addr+2, bit32.band(bit32.rshift(val, 16), 0xff))
+end
+
+-- This function takes array of opcodes/values and writes it DSP memory
+function ATJ.dsp.prog(opcodes, base, type)
+ if base > 0x3fff then
+ print(string.format("Invalid address 0x%x", base))
+ return
+ end
+
+ if type == 'p' then
+ -- DSP program memory
+ base = base + 0xb4040000
+ elseif type == 'd' then
+ -- DSP data memory
+ base = base + 0xb4050000
+ else
+ print(string.format("Invalid memory type: %c", type))
+ return
+ end
+
+ local offset=0
+ DSP.stop()
+ for i,opcode in ipairs(opcodes) do
+ DSP.write(base+4*offset, opcode)
+ offset=offset+1
+ end
+end
+
+-- This function reads the file produced by as2181 and
+-- uploads it to the DSP memory
+function ATJ.dsp.progfile(path)
+ local opcodes={}
+ local addr=nil
+ local type=nil
+
+ local fh=io.open(path)
+ if fh == nil then
+ print(string.format("Unable to open %s", path))
+ return
+ end
+
+ while true do
+ line = fh:read()
+ if line == nil then
+ break
+ end
+
+ -- Search for header describing target memory
+ if string.find(line, '@PA') ~= nil then
+ type = 'p'
+ elseif string.find(line, '@PD' ~= nil) then
+ type = 'd'
+ end
+
+ if type ~= nil then
+ -- Next line after the header is the address
+ addr = fh:read()
+ if addr ~= nil then
+ addr = tonumber(addr, 16)
+ else
+ break;
+ end
+
+ while true do
+ line = fh:read()
+ if line == nil then
+ break
+ end
+
+ -- Check ending clause
+ -- We don't check embedded checksum
+ if string.find(line, '#123') then
+ break
+ end
+
+ -- Read operand and store in array
+ opcodes[#opcodes+1] = tonumber(line,16)
+ end
+
+ if (type == 'p') then
+ print(string.format("Writing %d opcodes PM @ 0x%0x", #opcodes, addr))
+ elseif (type == 'd') then
+ print(string.format("Writing %d values DM @ x0%0x", #opcodes, addr))
+ end
+
+ -- Write to DSP memory
+ DSP.prog(opcodes, addr, type)
+ opcodes={}
+ addr = nil
+ type = nil
+ end
+ end
+ fh:close()
+end