<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def memory_write(self, addr, data, zone=None, nbits=None):
 """Writes memory to a target system or specific memory zone. The optional ``zone`` specifies a memory zone to access to write to, e.g. ``IDATA``, ``DDATA``, or ``CODE``. The given number of bits, if provided, must be either ``8``, ``16``, or ``32``. Args: self (JLink):
 the ``JLink`` instance addr (int):
 start address to write to data (list):
 list of data units to write zone (str):
 optional memory zone name to access nbits (int):
 number of bits to use for each unit Returns: Number of units written. Raises: JLinkException: on write hardware failure. ValueError: if ``nbits`` is not ``None``, and not in ``8``, ``16`` or ``32``. """

        buf_size = len(data)
        buf = None
        access = 0

        if nbits is None:
            # Pack the given data into an array of 8-bit unsigned integers in
            # order to write it successfully
            packed_data = map(lambda d: reversed(binpacker.pack(d)), data)
            packed_data = list(itertools.chain(*packed_data))

            buf_size = len(packed_data)
            buf = (ctypes.c_uint8 * buf_size)(*packed_data)

            # Allow the access width to be chosen for us.
            access = 0
        elif nbits == 8:
            buf = (ctypes.c_uint8 * buf_size)(*data)
            access = 1
        elif nbits == 16:
            buf = (ctypes.c_uint16 * buf_size)(*data)
            access = 2
            buf_size = buf_size * access
        elif nbits == 32:
            buf = (ctypes.c_uint32 * buf_size)(*data)
            access = 4
            buf_size = buf_size * access
        else:
            raise ValueError('Given bit size is invalid: %s' % nbits)

        args = [addr, buf_size, buf, access]

        method = self._dll.JLINKARM_WriteMemEx
        if zone is not None:
            method = self._dll.JLINKARM_WriteMemZonedEx
            args.append(zone.encode())

        units_written = method(*args)
        if units_written < 0:
            raise errors.JLinkWriteException(units_written)

        return units_written