Contiki 2.5
rom.c
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#)$Id: rom.c,v 1.2 2006/12/01 15:06:42 bg- Exp $
30  */
31 
32 #include "contiki.h"
33 
34 #include "dev/rom.h"
35 
36 struct ictx {
37  int s;
38  unsigned short ie1, ie2, wdtctl;
39 };
40 
41 static void
42 mask_intr(struct ictx *c)
43 {
44  /* Disable all interrupts. */
45  c->s = splhigh();
46 
47 #define WDTRPW 0x6900 /* Watchdog key returned by read */
48 
49  /* Disable all NMI-Interrupt sources */
50  c->wdtctl = WDTCTL;
51  c->wdtctl ^= (WDTRPW ^ WDTPW);
52  WDTCTL = WDTPW | WDTHOLD;
53  c->ie1 = IE1;
54  IE1 = 0x00;
55  c->ie2 = IE2;
56  IE2 = 0x00;
57 
58  /* MSP430F1611 257 < f < 476 kHz, 2.4576MHz/(5+1) = 409.6 kHz. */
59  FCTL2 = FWKEY | FSSEL_SMCLK | (FN2 | FN1);
60  FCTL3 = FWKEY; /* Unlock flash. */
61 }
62 
63 static void
64 rest_intr(struct ictx *c)
65 {
66  FCTL1 = FWKEY; /* Disable erase or write. */
67  FCTL3 = FWKEY | LOCK; /* Lock flash. */
68  /* Restore interrupts. */
69  IE2 = c->ie2;
70  IE1 = c->ie1;
71  WDTCTL = c->wdtctl;
72  splx(c->s);
73 }
74 
75 /*
76  * This helper routine must reside in RAM!
77  */
78 static void
79 blkwrt(void *to, const void *from, const void *from_end)
80  // __attribute__ ((section(".data")))
81  ;
82 
83 int
84 rom_erase(long nbytes, off_t offset)
85 {
86  int nb = nbytes;
87  char *to = (char *)(uintptr_t)offset;
88  struct ictx c;
89 
90  if(nbytes % ROM_ERASE_UNIT_SIZE != 0) {
91  return -1;
92  }
93 
94  if(offset % ROM_ERASE_UNIT_SIZE != 0) {
95  return -1;
96  }
97 
98  while (nbytes > 0) {
99  mask_intr(&c);
100 
101  FCTL1 = FWKEY | ERASE; /* Segment erase. */
102  *to = 0; /* Erase segment containing to. */
103  nbytes -= ROM_ERASE_UNIT_SIZE;
104  to += ROM_ERASE_UNIT_SIZE;
105 
106  rest_intr(&c);
107  }
108 
109  return nb;
110 }
111 
112 int
113 rom_pwrite(const void *buf, int nbytes, off_t offset)
114 {
115  const char *from = buf;
116  int nb = nbytes;
117  char *to = (char *)(uintptr_t)offset;
118  struct ictx c;
119 
120  mask_intr(&c);
121 
122  while(nbytes > 0) {
123  int n = (nbytes > 64) ? 64 : nbytes;
124  FCTL1 = FWKEY | BLKWRT | WRT; /* Enable block write. */
125  blkwrt(to, from, from + n);
126  while(FCTL3 & BUSY);
127  to += 64;
128  from += 64;
129  nbytes -= n;
130  }
131 
132  rest_intr(&c);
133 
134  return nb;
135 }
136 
137 /*
138  * This helper routine must reside in RAM!
139  */
140 asm(".data");
141 asm(".p2align 1,0");
142 asm(".type blkwrt,@function");
143 asm(".section .data");
144 
145 static void
146 blkwrt(void *_to, const void *_from, const void *_from_end)
147 {
148  unsigned short *to = _to;
149  const unsigned short *from = _from;
150  const unsigned short *from_end = _from_end;
151  do {
152  *to++ = *from++;
153  while(!(FCTL3 & WAIT));
154  } while(from < from_end);
155  FCTL1 = FWKEY; /* Disable block write. */
156  /* Now ROM is available again! */
157 }