Support for the NVMCTRL Security Bit (PROT=1)

This commit is contained in:
Richard Meadows 2015-01-18 20:46:26 +00:00
parent e75ea64a01
commit 3726061773
3 changed files with 73 additions and 10 deletions

View File

@ -60,8 +60,6 @@ const struct command_s cortexm_cmd_list[] = {
#define SIGTRAP 5
#define SIGSEGV 11
static bool cortexm_attach(struct target_s *target);
static int cortexm_regs_read(struct target_s *target, void *data);
static int cortexm_regs_write(struct target_s *target, const void *data);
static int cortexm_pc_write(struct target_s *target, const uint32_t val);
@ -269,8 +267,7 @@ cortexm_probe(struct target_s *target)
return true;
}
static bool
cortexm_attach(struct target_s *target)
bool cortexm_attach(struct target_s *target)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;

View File

@ -123,6 +123,7 @@
#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0)
#define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0)
bool cortexm_attach(struct target_s *target);
void cortexm_detach(struct target_s *target);
void cortexm_halt_resume(struct target_s *target, bool step);

View File

@ -25,9 +25,6 @@
* http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf
* particularly Sections 12. DSU and 20. NVMCTRL
*/
/* TODO: Support for the NVMCTRL Security Bit. If this is set then the
* device will probably not even be detected.
*/
#include <stdio.h>
#include <stdlib.h>
@ -51,6 +48,7 @@ static bool samd20_cmd_unlock_flash(target *t);
static bool samd20_cmd_read_userrow(target *t);
static bool samd20_cmd_serial(target *t);
static bool samd20_cmd_mbist(target *t);
static bool samd20_cmd_ssb(target *t);
const struct command_s samd20_cmd_list[] = {
{"erase_mass", (cmd_handler)samd20_cmd_erase_all, "Erase entire flash memory"},
@ -59,6 +57,7 @@ const struct command_s samd20_cmd_list[] = {
{"user_row", (cmd_handler)samd20_cmd_read_userrow, "Prints user row from flash"},
{"serial", (cmd_handler)samd20_cmd_serial, "Prints serial number"},
{"mbist", (cmd_handler)samd20_cmd_mbist, "Runs the built-in memory test"},
{"set_security_bit", (cmd_handler)samd20_cmd_ssb, "Sets the Security Bit"},
{NULL, NULL, NULL}
};
@ -102,6 +101,8 @@ static const char samd20_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define SAMD20_CTRLA_CMD_LOCK 0x0040
#define SAMD20_CTRLA_CMD_UNLOCK 0x0041
#define SAMD20_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044
#define SAMD20_CTRLA_CMD_SSB 0x0045
#define SAMD20_CTRLA_CMD_INVALL 0x0046
/* Interrupt Flag Register (INTFLAG) */
#define SAMD20_NVMC_READY (1 << 0)
@ -137,6 +138,7 @@ static const char samd20_xml_memory_map[] = "<?xml version=\"1.0\"?>"
#define SAMD20_STATUSA_BERR (1 << 10)
#define SAMD20_STATUSA_CRSTEXT (1 << 9)
#define SAMD20_STATUSA_DONE (1 << 8)
#define SAMD20_STATUSB_PROT (1 << 16)
/* Device Identification Register (DID) */
#define SAMD20_DID_MASK 0xFFBF0000
@ -284,8 +286,32 @@ samd20_revB_halt_resume(struct target_s *target, bool step)
}
}
/**
* Overload the default cortexm attach for when the samd20 is protected.
*
* If the samd20 is protected then the default cortexm attach will
* fail as the S_HALT bit in the DHCSR will never go high. This
* function allows users to attach on a temporary basis so they can
* rescue the device.
*/
static bool
samd20_protected_attach(struct target_s *target)
{
/**
* TODO: Notify the user that we're not really attached and
* they should issue the 'monitor erase_mass' command to
* regain access to the chip.
*/
char variant_string[30];
/* Patch back in the normal cortexm attach for next time */
target->attach = cortexm_attach;
/* Allow attach this time */
return true;
}
char variant_string[40];
bool samd20_probe(struct target_s *target)
{
ADIv5_AP_t *ap = adiv5_target_ap(target);
@ -306,6 +332,7 @@ bool samd20_probe(struct target_s *target)
& SAMD20_DID_DEVSEL_MASK;
uint8_t revision = (did >> SAMD20_DID_REVISION_POS)
& SAMD20_DID_REVISION_MASK;
uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT);
/* Pin Variant */
char pin_variant;
@ -322,9 +349,17 @@ bool samd20_probe(struct target_s *target)
/* Revision */
char revision_variant = 'A' + revision;
/* Protected? */
int protected = (ctrlstat & SAMD20_STATUSB_PROT);
/* Part String */
sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)",
pin_variant, mem_variant, revision_variant);
if (protected) {
sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c) (PROT=1)",
pin_variant, mem_variant, revision_variant);
} else {
sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)",
pin_variant, mem_variant, revision_variant);
}
/* Setup Target */
target->driver = variant_string;
@ -339,6 +374,16 @@ bool samd20_probe(struct target_s *target)
target->detach = samd20_revB_detach;
target->halt_resume = samd20_revB_halt_resume;
}
if (protected) {
/**
* Overload the default cortexm attach
* for when the samd20 is protected.
* This function allows users to
* attach on a temporary basis so they
* can rescue the device.
*/
target->attach = samd20_protected_attach;
}
target->xml_mem_map = samd20_xml_memory_map;
target->flash_erase = samd20_flash_erase;
@ -669,3 +714,23 @@ static bool samd20_cmd_mbist(target *t)
return true;
}
/**
* Sets the security bit
*/
static bool samd20_cmd_ssb(target *t)
{
ADIv5_AP_t *ap = adiv5_target_ap(t);
/* Issue the ssb command */
adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_SSB);
/* Poll for NVM Ready */
while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0)
if(target_check_error(t))
return -1;
gdb_outf("Set the security bit! "
"You will need to issue 'monitor erase_mass' to clear this.\n");
return true;
}