コード例 #1
0
ファイル: spi.py プロジェクト: rvolgers/Glasgow
    async def interact(self, device, args, avr_iface):
        await avr_iface.programming_enable()

        signature = await avr_iface.read_signature()
        device = devices_by_signature[signature]
        self.logger.info("device signature: %s (%s)",
            "{:02x} {:02x} {:02x}".format(*signature),
            "unknown" if device is None else device.name)

        if args.operation is not None and device is None:
            raise GlasgowAppletError("cannot operate on unknown device")

        if args.operation == "read":
            if args.fuses:
                fuses = await avr_iface.read_fuse_range(range(device.fuses_size))
                if device.fuses_size > 2:
                    self.logger.info("fuses: low %s high %s extra %s",
                                     "{:08b}".format(fuses[0]),
                                     "{:08b}".format(fuses[1]),
                                     "{:08b}".format(fuses[2]))
                elif device.fuses_size > 1:
                    self.logger.info("fuses: low %s high %s",
                                     "{:08b}".format(fuses[0]),
                                     "{:08b}".format(fuses[1]))
                else:
                    self.logger.info("fuse: %s", "{:08b}".format(fuses[0]))

            if args.lock_bits:
                lock_bits = await avr_iface.read_lock_bits()
                self.logger.info("lock bits: %s", "{:08b}".format(lock_bits))

            if args.calibration:
                calibration = \
                    await avr_iface.read_calibration_range(range(device.calibration_size))
                self.logger.info("calibration bytes: %s",
                                 " ".join(["%02x" % b for b in calibration]))

            if args.program:
                self._check_format(args.program, "program memory")
                self.logger.info("reading program memory (%d bytes)", device.program_size)
                output_data(args.program,
                    await avr_iface.read_program_memory_range(range(device.program_size)))

            if args.eeprom:
                self._check_format(args.eeprom, "EEPROM")
                self.logger.info("reading EEPROM (%d bytes)", device.eeprom_size)
                output_data(args.eeprom,
                    await avr_iface.read_eeprom_range(range(device.eeprom_size)))

        if args.operation == "write-fuses":
            if args.high and device.fuses_size < 2:
                raise GlasgowAppletError("device does not have high fuse")

            if args.low:
                self.logger.info("writing low fuse")
                await avr_iface.write_fuse(0, args.low)
                written = await avr_iface.read_fuse(0)
                if written != args.low:
                    raise GlasgowAppletError("verification of low fuse failed: %s" %
                                             "{:08b} != {:08b}".format(written, args.low))

            if args.high:
                self.logger.info("writing high fuse")
                await avr_iface.write_fuse(1, args.high)
                written = await avr_iface.read_fuse(1)
                if written != args.high:
                    raise GlasgowAppletError("verification of high fuse failed: %s" %
                                             "{:08b} != {:08b}".format(written, args.high))

        if args.operation == "write-lock":
            self.logger.info("writing lock bits")
            await avr_iface.write_lock_bits(args.bits)
            written = await avr_iface.read_lock_bits()
            if written != args.bits:
                raise GlasgowAppletError("verification of lock bits failed: %s" %
                                         "{:08b} != {:08b}".format(written, args.bits))

        if args.operation == "write-program":
            self.logger.info("erasing chip")
            await avr_iface.chip_erase()

            self._check_format(args.file, "program memory")
            data = input_data(args.file)
            self.logger.info("writing program memory (%d bytes)",
                             sum([len(chunk) for address, chunk in data]))
            for address, chunk in data:
                chunk = bytes(chunk)
                await avr_iface.write_program_memory_range(address, chunk, device.program_page)
                written = await avr_iface.read_program_memory_range(range(address, len(chunk)))
                if written != chunk:
                    raise GlasgowAppletError("verification failed at address %#06x: %s != %s" %
                                             (address, written.hex(), chunk.hex()))

        if args.operation == "write-eeprom":
            self._check_format(args.file, "EEPROM")
            data = input_data(args.file)
            self.logger.info("writing EEPROM (%d bytes)",
                             sum([len(chunk) for address, chunk in data]))
            for address, chunk in data:
                chunk = bytes(chunk)
                await avr_iface.write_eeprom_range(address, chunk, device.eeprom_page)
                written = await avr_iface.read_eeprom_range(range(address, len(chunk)))
                if written != chunk:
                    raise GlasgowAppletError("verification failed at address %#06x: %s != %s" %
                                             (address, written.hex(), chunk.hex()))

        await avr_iface.programming_disable()
コード例 #2
0
    async def interact(self, device, args, nrf24lx1_iface):
        page_size = 512
        if args.device == "LE1":
            memory_map  = _nrf24le1_map
            buffer_size = 512
        elif args.device == "LU1p32k":
            memory_map  = _nrf24lu1p_32k_map
            buffer_size = 256
        elif args.device == "LU1p16k":
            memory_map  = _nrf24lu1p_16k_map
            buffer_size = 256
        else:
            assert False

        try:
            await nrf24lx1_iface.reset_program()

            async def check_info_page(address):
                old_status = await nrf24lx1_iface.read_status()
                try:
                    await nrf24lx1_iface.write_status(FSR_BIT_INFEN)
                    fuse, = await nrf24lx1_iface.read(address, 1)
                    return fuse != 0xff
                finally:
                    await nrf24lx1_iface.write_status(old_status)

            async def check_read_protected():
                if await check_info_page(0x23):
                    raise ProgramNRF24Lx1Error("MCU is read protected; run `erase --info-page`")

            if args.operation == "read":
                await check_read_protected()

                chunks = []
                for memory_area in memory_map:
                    self.logger.info("reading %s memory", memory_area.name)
                    if memory_area.spi_addr & 0x10000:
                        await nrf24lx1_iface.write_status(FSR_BIT_INFEN)
                    else:
                        await nrf24lx1_iface.write_status(0)
                    area_data = await nrf24lx1_iface.read(memory_area.spi_addr & 0xffff,
                                                          memory_area.size)
                    chunks.append((memory_area.mem_addr, area_data))
                output_data(args.file, chunks, fmt="ihex")

            if args.operation == "program":
                await check_read_protected()

                area_index   = 0
                memory_area  = memory_map[area_index]
                erased_pages = set()
                for chunk_mem_addr, chunk_data in sorted(input_data(args.file, fmt="ihex"),
                                                         key=lambda c: c[0]):
                    if len(chunk_data) == 0:
                        continue
                    if chunk_mem_addr < memory_area.mem_addr:
                        raise ProgramNRF24Lx1Error("data outside of memory map at {:#06x}"
                                                 .format(chunk_mem_addr))
                    while chunk_mem_addr >= memory_area.mem_addr + memory_area.size:
                        area_index += 1
                        if area_index >= len(memory_area):
                            raise ProgramNRF24Lx1Error("data outside of memory map at {:#06x}"
                                                     .format(chunk_mem_addr))
                        memory_area = memory_map[area_index]
                    if chunk_mem_addr + len(chunk_data) > memory_area.mem_addr + memory_area.size:
                        raise ProgramNRF24Lx1Error("data outside of memory map at {:#06x}"
                                                 .format(memory_area.mem_addr + memory_area.size))
                    if memory_area.spi_addr & 0x10000 and not args.info_page:
                        self.logger.warn("data provided for info page, but info page programming "
                                         "is not enabled")
                        continue

                    chunk_spi_addr = (chunk_mem_addr
                                      - memory_area.mem_addr
                                      + memory_area.spi_addr) & 0xffff
                    if memory_area.spi_addr & 0x10000:
                        level = logging.WARN
                        await nrf24lx1_iface.write_status(FSR_BIT_INFEN)
                    else:
                        level = logging.INFO
                        await nrf24lx1_iface.write_status(0)

                    overwrite_pages = set(range(
                        (chunk_spi_addr // page_size),
                        (chunk_spi_addr + len(chunk_data) + page_size - 1) // page_size))
                    need_erase_pages = overwrite_pages - erased_pages
                    if need_erase_pages:
                        for page in need_erase_pages:
                            page_addr = (memory_area.spi_addr & 0x10000) | (page * page_size)
                            self.logger.log(level, "erasing %s memory at %#06x+%#06x",
                                            memory_area.name, page_addr, page_size)
                            await nrf24lx1_iface.write_enable()
                            await nrf24lx1_iface.erase_page(page)
                            await nrf24lx1_iface.wait_status()
                        erased_pages.update(need_erase_pages)

                    self.logger.log(level, "programming %s memory at %#06x+%#06x",
                                    memory_area.name, chunk_mem_addr, len(chunk_data))
                    while len(chunk_data) > 0:
                        await nrf24lx1_iface.write_enable()
                        await nrf24lx1_iface.program(chunk_spi_addr, chunk_data[:buffer_size])
                        await nrf24lx1_iface.wait_status()
                        chunk_data  = chunk_data[buffer_size:]
                        chunk_spi_addr += buffer_size

            if args.operation == "erase":
                if args.info_page:
                    await nrf24lx1_iface.write_status(FSR_BIT_INFEN)
                    info_page = await nrf24lx1_iface.read(0x0000, 0x0100)
                    self.logger.warn("backing up info page to %s", args.info_page)
                    if os.path.isfile(args.info_page):
                        raise ProgramNRF24Lx1Error("info page backup file already exists")
                    with open(args.info_page, "wb") as f:
                        output_data(f, [(0x10000, info_page)])
                    self.logger.warn("erasing code and data memory, and info page")
                else:
                    await check_read_protected()
                    await nrf24lx1_iface.write_status(0)
                    self.logger.info("erasing code and data memory")
                try:
                    await nrf24lx1_iface.write_enable()
                    await nrf24lx1_iface.erase_all()
                    await nrf24lx1_iface.wait_status()
                    if args.info_page:
                        self.logger.info("restoring info page DSYS area")
                        await nrf24lx1_iface.write_enable()
                        await nrf24lx1_iface.program(0, info_page[:32]) # DSYS only
                        await nrf24lx1_iface.wait_status()
                except:
                    if args.info_page:
                        self.logger.error("IMPORTANT: programming failed; restore DSYS manually "
                                          "using `program --info-page %s`",
                                          args.info_page)
                    raise

            if args.operation == "protect-read":
                if await check_info_page(0x23):
                    raise ProgramNRF24Lx1Error("memory read protection is already enabled")

                self.logger.warn("protecting code and data memory from reads")
                await nrf24lx1_iface.write_enable()
                await nrf24lx1_iface.disable_read()
                await nrf24lx1_iface.wait_status()

            if args.operation == "enable-debug":
                if await check_info_page(0x24):
                    raise ProgramNRF24Lx1Error("hardware debugging features already enabled")

                self.logger.info("enabling hardware debugging features")
                await nrf24lx1_iface.write_enable()
                await nrf24lx1_iface.enable_debug()
                await nrf24lx1_iface.wait_status()

        finally:
            await nrf24lx1_iface.reset_application()