Writing to flash fails with traceback
DAP-Link interface , nRF51822 target
Windows 7 Pro x64

Read and write RAM works:
```
C:\\Temp>pyocd cmd -c R32 0x2000000
02000000:  00000000

C:\\Temp>pyocd cmd -c R32 0x20000000
20000000:  e00abe00

C:\\Temp>pyocd cmd -c W32 0x20000000 0xe00abe01

C:\\Temp>pyocd cmd -c R32 0x20000000
20000000:  e00abe01

C:\\Temp>pyocd cmd -c W32 0x20000000 0xe00abe00

C:\\Temp>pyocd cmd -c R32 0x20000000
20000000:  e00abe00
```

Reading flash works, writing flash fails:

```
C:\\Temp>pyocd cmd -c R32 0x10001000
10001000:  ffffffff

C:\\Temp>pyocd cmd -c W32 0x10001000 0xA5A55A5A
0000625:ERROR:__main__:uncaught exception: name 'flashPtr' is not defined
Traceback (most recent call last):
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\__main__.py", line 329, in run
    self._COMMANDS[self._args.cmd](self)
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\__main__.py", line 577, in do_commander
    PyOCDCommander(self._args, cmds).run()
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\tools\\pyocd.py", line 648, in run
    result = self.command_list[cmd](args)
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\tools\\pyocd.py", line 899, in handle_write32
    return self.do_write(args, 32)
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\tools\\pyocd.py", line 992, in do_write
    region.flash.program_phrase(addr, data)
  File "c:\\uac_ok\\python37\\lib\\site-packages\\pyocd\\flash\\flash.py", line 421, in program_phrase
    if flashPtr % min_len:
NameError: name 'flashPtr' is not defined
```

I am fairly sure the problem is on line 421 of flash,py  .

It should be:

`if address % min_len:`

This problem also occurs in console mode.



diff --git a/pyocd/flash/flash.py b/pyocd/flash/flash.py
index 15506384..eedcbf52 100644
--- a/pyocd/flash/flash.py
+++ b/pyocd/flash/flash.py
@@ -380,11 +380,8 @@ class Flash(object):
         assert buffer_number < len(self.page_buffers), "Invalid buffer number"
         assert self._active_operation == self.Operation.PROGRAM
 
-        # get info about this page
-        page_info = self.get_page_info(address)
-
         # update core register to execute the program_page subroutine
-        result = self._call_function(self.flash_algo['pc_program_page'], address, page_info.size, self.page_buffers[buffer_number])
+        result = self._call_function(self.flash_algo['pc_program_page'], address, self.region.page_size, self.page_buffers[buffer_number])
 
     def load_page_buffer(self, buffer_number, address, bytes):
         """!
@@ -415,10 +412,10 @@ class Flash(object):
         if self.min_program_length:
             min_len = self.min_program_length
         else:
-            min_len = self.get_page_info(address).size
+            min_len = self.region.page_size
 
         # Require write address and length to be aligned to min write size.
-        if flashPtr % min_len:
+        if address % min_len:
             raise FlashFailure("unaligned flash write address")
         if len(bytes) % min_len:
             raise FlashFailure("phrase length is unaligned or too small")
@@ -446,7 +443,7 @@ class Flash(object):
 
         info = SectorInfo()
         info.erase_weight = self.region.erase_sector_weight
-        info.size = self.region.blocksize
+        info.size = self.region.sector_size
         info.base_addr = addr - (addr % info.size)
         return info
 
diff --git a/pyocd/target/pack/cmsis_pack.py b/pyocd/target/pack/cmsis_pack.py
index 82e58d87..9eb41d97 100644
--- a/pyocd/target/pack/cmsis_pack.py
+++ b/pyocd/target/pack/cmsis_pack.py
@@ -16,7 +16,7 @@
 
 from __future__ import print_function
 from xml.etree.ElementTree import ElementTree
-from zipfile import ZipFile
+import zipfile
 from collections import namedtuple
 import logging
 import io
@@ -71,11 +71,18 @@ class CmsisPack(object):
         @param self
         @param file_or_path The .pack file to open. May be a string that is the path to the pack,
             or may be a ZipFile, or a file-like object that is already opened.
+        
+        @exception MalformedCmsisPackError The pack is not a zip file, or the .pdsc file is missing
+            from within the pack.
         """
-        if isinstance(file_or_path, ZipFile):
+        if isinstance(file_or_path, zipfile.ZipFile):
             self._pack_file = file_or_path
         else:
-            self._pack_file = ZipFile(file_or_path, 'r')
+            try:
+                self._pack_file = zipfile.ZipFile(file_or_path, 'r')
+            except zipfile.BadZipFile as err:
+                six.raise_from(MalformedCmsisPackError("Failed to open CMSIS-Pack '{}': {}".format(
+                    file_or_path, err)), err)
         
         # Find the .pdsc file.
         for name in self._pack_file.namelist():
@@ -83,7 +90,7 @@ class CmsisPack(object):
                 self._pdscName = name
                 break
         else:
-            raise MalformedCmsisPackError("CMSIS-Pack is missing a .pdsc file")
+            raise MalformedCmsisPackError("CMSIS-Pack '{}' is missing a .pdsc file".format(file_or_path))
         
         # Convert PDSC into an ElementTree.
         with self._pack_file.open(self._pdscName) as pdscFile:
['pyocd/target/pack/cmsis_pack.py', 'pyocd/flash/flash.py']