Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: whitequark/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 33364f7442c5
Choose a base ref
...
head repository: whitequark/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a2df0aa8892c
Choose a head ref
  • 1 commit
  • 5 files changed
  • 1 contributor

Commits on Nov 18, 2018

  1. Copy the full SHA
    a2df0aa View commit details
1 change: 1 addition & 0 deletions software/glasgow/applet/__init__.py
Original file line number Diff line number Diff line change
@@ -158,6 +158,7 @@ def wrapper(self):
from .i2c.eeprom_24c import I2CEEPROM24CApplet
from .i2c.tps6598x import I2CTPS6598xApplet
from .jtag import JTAGApplet
from .jtag.arc import JTAGARCApplet
from .jtag.mips import JTAGMIPSApplet
from .jtag.pinout import JTAGPinoutApplet
from .jtag.svf import JTAGSVFApplet
139 changes: 139 additions & 0 deletions software/glasgow/applet/jtag/arc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Ref: Microchip MEC1618/MEC1618i Low Power 32-bit Microcontroller with Embedded Flash
# Document Number: DS00002339A

import logging
import argparse
import struct

from . import JTAGApplet
from .. import *
from ...pyrepl import *
from ...arch.jtag import *
from ...arch.arc.jtag import *
from ...database.arc import *


class JTAGARCInterface:
def __init__(self, interface, logger):
self.lower = interface
self._logger = logger
self._level = logging.DEBUG if self._logger.name == __name__ else logging.TRACE

def _log(self, message, *args):
self._logger.log(self._level, "ARC: " + message, *args)

async def identify(self):
await self.lower.write_ir(IR_IDCODE)
idcode_bits = await self.lower.read_dr(32)
idcode = DR_IDCODE.from_bitarray(idcode_bits)
self._log("read IDCODE mfg_id=%03x part_id=%04x",
idcode.mfg_id, idcode.part_id)
device = devices[idcode.mfg_id, idcode.part_id]
return idcode, device

async def _wait_txn(self):
await self.lower.write_ir(IR_STATUS)
status = DR_STATUS()
while not status.RD:
status_bits = await self.lower.read_dr(4)
status = DR_STATUS.from_bitarray(status_bits)
self._log("status %s", status.bits_repr())
if status.FL:
raise GlasgowAppletError("transaction failed")

async def read(self, address, space):
if space == "memory":
dr_txn_command = DR_TXN_COMMAND_READ_MEMORY
elif space == "core":
dr_txn_command = DR_TXN_COMMAND_READ_CORE
elif space == "aux":
dr_txn_command = DR_TXN_COMMAND_READ_AUX
else:
assert False

self._log("read space=%s address=%08x", space, address)
dr_address = DR_ADDRESS(Address=address)
await self.lower.write_ir(IR_ADDRESS)
await self.lower.write_dr(dr_address.to_bitarray())
await self.lower.write_ir(IR_TXN_COMMAND)
await self.lower.write_dr(dr_txn_command)
await self._wait_txn()
await self.lower.write_ir(IR_DATA)
dr_data_bits = await self.lower.read_dr(32)
dr_data = DR_DATA.from_bitarray(dr_data_bits)
self._log("read data=%08x", dr_data.Data)
return dr_data.Data

async def write(self, address, data, space):
if space == "memory":
dr_txn_command = DR_TXN_COMMAND_WRITE_MEMORY
elif space == "core":
dr_txn_command = DR_TXN_COMMAND_WRITE_CORE
elif space == "aux":
dr_txn_command = DR_TXN_COMMAND_WRITE_AUX
else:
assert False

self._log("write space=%s address=%08x data=%08x", space, address, data)
dr_address = DR_ADDRESS(Address=address)
await self.lower.write_ir(IR_ADDRESS)
await self.lower.write_dr(dr_address.to_bitarray())
await self.lower.write_ir(IR_DATA)
dr_data = DR_DATA(Data=data)
await self.lower.write_dr(dr_data.to_bitarray())
await self.lower.write_ir(IR_TXN_COMMAND)
await self.lower.write_dr(dr_txn_command)
await self._wait_txn()


class JTAGARCApplet(JTAGApplet, name="jtag-arc"):
preview = True
logger = logging.getLogger(__name__)
help = "debug ARC processors via JTAG"
description = """
Debug ARC processors via the JTAG interface.
The list of supported devices is:
{devices}
There is currently no debug server implemented. This applet only allows manipulating Memory,
Core and Aux spaces via a Python REPL.
""".format(
devices="\n".join(map(lambda x: " * {.name}\n".format(x), devices.values()))
)

@classmethod
def add_run_arguments(cls, parser, access):
super().add_run_arguments(parser, access)

parser.add_argument(
"--tap-index", metavar="INDEX", type=int, default=0,
help="select TAP #INDEX for communication (default: %(default)s)")

async def run(self, device, args):
jtag_iface = await super().run(device, args)
await jtag_iface.test_reset()

tap_iface = await jtag_iface.select_tap(args.tap_index)
if not tap_iface:
raise GlasgowAppletError("cannot select TAP #%d" % args.tap_index)

return JTAGARCInterface(tap_iface, self.logger)

@classmethod
def add_interact_arguments(cls, parser):
p_operation = parser.add_subparsers(dest="operation", metavar="OPERATION")

p_repl = p_operation.add_parser(
"repl", help="drop into Python shell; use `arc_iface` to communicate")

async def interact(self, device, args, arc_iface):
idcode, device = await arc_iface.identify()
if device is None:
raise GlasgowAppletError("cannot operate on unknown device IDCODE=%08x"
% idcode.to_int())
self.logger.info("IDCODE=%08x device=%s rev=%d",
idcode.to_int(), device.name, idcode.version)

if args.operation == "repl":
await AsyncInteractiveConsole(locals={"arc_iface":arc_iface}).interact()
Empty file.
53 changes: 53 additions & 0 deletions software/glasgow/arch/arc/jtag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Ref: Microchip MEC1618/MEC1618i Low Power 32-bit Microcontroller with Embedded Flash
# Document Number: DS00002339A

from bitarray import bitarray

from ...support.bits import *


__all__ = [
# IR
"IR_RESET_TEST", "IR_STATUS", "IR_TXN_COMMAND", "IR_ADDRESS", "IR_DATA", "IR_IDCODE",
# DR
"DR_STATUS",
"DR_TXN_COMMAND_WRITE_MEMORY", "DR_TXN_COMMAND_WRITE_CORE", "DR_TXN_COMMAND_WRITE_AUX",
"DR_TXN_COMMAND_READ_MEMORY", "DR_TXN_COMMAND_READ_CORE", "DR_TXN_COMMAND_READ_AUX",
"DR_ADDRESS",
"DR_DATA",
]


# IR values

IR_RESET_TEST = bitarray("0100", endian="little") # DR[32]
IR_STATUS = bitarray("0001", endian="little") # DR[4]
IR_TXN_COMMAND = bitarray("1001", endian="little") # DR[4]
IR_ADDRESS = bitarray("0101", endian="little") # DR[32]
IR_DATA = bitarray("1101", endian="little") # DR[32]
IR_IDCODE = bitarray("0011", endian="little") # DR[32]
IR_BYPASS = bitarray("1111", endian="little") # DR[1]

# DR values

DR_STATUS = Bitfield("DR_STATUS", 1, [
("ST", 1),
("FL", 1),
("RD", 1),
("PC_SEL", 1),
])

DR_TXN_COMMAND_WRITE_MEMORY = bitarray("0000", endian="little")
DR_TXN_COMMAND_WRITE_CORE = bitarray("1000", endian="little")
DR_TXN_COMMAND_WRITE_AUX = bitarray("0100", endian="little")
DR_TXN_COMMAND_READ_MEMORY = bitarray("0010", endian="little")
DR_TXN_COMMAND_READ_CORE = bitarray("1010", endian="little")
DR_TXN_COMMAND_READ_AUX = bitarray("0110", endian="little")

DR_ADDRESS = Bitfield("DR_ADDRESS", 4, [
("Address", 32),
])

DR_DATA = Bitfield("DR_DATA", 4, [
("Data", 32),
])
12 changes: 12 additions & 0 deletions software/glasgow/database/arc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from collections import defaultdict, namedtuple


__all__ = ["devices"]


ARCDevice = namedtuple("ARCDevice", ("name",))


devices = defaultdict(lambda: None, {
(0x258, 0x0002): ARCDevice(name="ARC6xx"),
})