summaryrefslogtreecommitdiffhomepage
path: root/digital/ucoolib/ucoolib/dev/avrisp/avrisp.hh
blob: 5046459b69dab7384c03956113ec6d1f675c39f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#ifndef ucoolib_dev_avrisp_avrisp_hh
#define ucoolib_dev_avrisp_avrisp_hh
// ucoolib - Microcontroller object oriented library. {{{
//
// Copyright (C) 2013 Nicolas Schodet
//
// APBTeam:
//        Web: http://apbteam.org/
//      Email: team AT apbteam DOT org
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// }}}
#include "ucoolib/common.hh"

namespace ucoo {

/// Results returned by ISP functions.
enum AvrIspResult
{
    /// Operation success.
    AVRISP_OK,
    /// Operation failed.
    AVRISP_FAILED,
    /// Operation failed on a timeout.
    AVRISP_TIMEOUT,
};

/// ISP Programming mode.
enum AvrIspMode
{
    /// Use page programming.
    AVRISP_MODE_PAGE = 1,
    /// Use simple delay for word programming.
    AVRISP_MODE_WORD_DELAY = 2,
    /// Use value polling if possible for word programming, fall back to delay
    /// if not possible.
    AVRISP_MODE_WORD_VALUE = 4,
    /// Use RDY/BSY polling for word programming.
    AVRISP_MODE_WORD_RDY_BSY = 8,
    /// Use simple delay for page programming.
    AVRISP_MODE_PAGE_DELAY = 16,
    /// Use value polling if possible for page programming, fall back to delay
    /// if not possible.
    AVRISP_MODE_PAGE_VALUE = 32,
    /// Use RDY/BSY polling for page programming.
    AVRISP_MODE_PAGE_RDY_BSY = 64,
    /// Write page at end of transfer.  Used for big pages which must be
    /// transfered in several packets.
    AVRISP_MODE_PAGE_WRITE = 128,
};

/// Interface to hardware connection.
class AvrIspIntf
{
  public:
    /// Send and receive one byte through SPI interface.
    virtual uint8_t send_and_recv (uint8_t tx) = 0;
    /// Enable programming:
    /// - set RESET and SCK to low,
    /// - power on, or if not possible, do a positive RESET pulse,
    /// - enable SPI, mode 0.
    virtual void enable (uint8_t sck_duration_us) = 0;
    /// Disable programming:
    /// - disable SPI,
    /// - release RESET,
    /// - power off if desired.
    virtual void disable () = 0;
    /// Do a pulse on SCK.  This is used to try to resynchronise.
    virtual void sck_pulse () = 0;
};

/// AVR serial programming.
class AvrIsp
{
  public:
    /// Constructor.
    AvrIsp (AvrIspIntf &intf);
    /// Enable SPI port and enter programing mode.
    /// - sck_duration_us: SCK period.
    /// - timeout_ms: command time-out, unused.
    /// - stab_delay_ms: stabilisation delay once device is reseted and SPI
    ///   initialised.
    /// - cmd_exe_delay_ms: delay for the command execution.
    /// - synch_loops: number of synchronisation loops (there is no start of
    ///   frame in SPI).
    /// - byte_delay_ms: delay between each byte.
    /// - poll_value: value to read to consider the sequence is correct.
    /// - poll_index: transfer index at which the poll_value must be read.
    /// - cmd: command bytes to be transfered.
    /// - returns: AVRISP_OK or AVRISP_FAILED if no synchronisation.
    AvrIspResult enter_progmode (uint8_t sck_duration_us,
                                 uint8_t timeout_ms, uint8_t stab_delay_ms,
                                 uint8_t cmd_exe_delay_ms,
                                 uint8_t synch_loops, uint8_t byte_delay_ms,
                                 uint8_t poll_value, uint8_t poll_index,
                                 const uint8_t cmd[4]);
    /// Leave programming mode and disable SPI port.
    /// - pre_delay_ms: delay before disabling.
    /// - post_delay_ms: delay after disabling.
    void leave_progmode (uint8_t pre_delay_ms, uint8_t post_delay_ms);
    /// Load programing address.
    /// - addr: address to load, bit 31 means the device has more than 64k
    ///   words and extended addressing should be used.
    void load_address (uint32_t addr);
    /// Chip full erase.
    /// - erase_delay_ms: delay to ensure the erase is finished.
    /// - poll_method: use delay (0) or RDY/BSY polling (1).
    /// - cmd: chip erase command.
    /// - returns: AVRISP_OK or AVRISP_TIMEOUT if using polling and it
    ///   timed-out.
    AvrIspResult chip_erase (uint8_t erase_delay_ms, uint8_t poll_method,
                             const uint8_t cmd[4]);
    /// Start a program command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult program_begin (uint16_t num_bytes, uint8_t mode,
                                uint8_t delay_ms, uint8_t cmd_write_mem,
                                uint8_t cmd_write_page, uint8_t cmd_read_mem,
                                const uint8_t poll[2], uint8_t flash);
    /// Start a flash memory program command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult program_flash_begin (uint16_t num_bytes, uint8_t mode,
                                      uint8_t delay_ms, uint8_t cmd_write_mem,
                                      uint8_t cmd_write_page,
                                      uint8_t cmd_read_mem,
                                      const uint8_t poll[2]);
    /// Start a EEPROM memory program command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult program_eeprom_begin (uint16_t num_bytes,
                                       uint8_t mode,
                                       uint8_t delay_ms,
                                       uint8_t cmd_write_mem,
                                       uint8_t cmd_write_page,
                                       uint8_t cmd_read_mem,
                                       const uint8_t poll[2]);
    /// Provide data for memory programming.  Data should be given by even
    /// sized packs or loading of word addressed data will fail.
    /// - returns: AVRISP_OK, AVRISP_FAILED for bad parameters or
    ///   AVRISP_TIMEOUT if using polling and it timed-out.
    AvrIspResult program_continue (const uint8_t *data, uint16_t size);
    /// End program command.
    /// - returns: AVRISP_OK, AVRISP_FAILED if too early or AVRISP_TIMEOUT if
    ///   using polling and it timed-out.
    AvrIspResult program_end ();
    /// Start a read command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult read_begin (uint16_t num_bytes, uint8_t cmd_read_mem,
                             uint8_t flash);
    /// Start a flash memory read command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult read_flash_begin (uint16_t num_bytes, uint8_t cmd_read_mem);
    /// Start a EEPROM memory read command.
    /// - num_bytes: total number of bytes to program.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    /// See class for other parameters meaning.
    AvrIspResult read_eeprom_begin (uint16_t num_bytes, uint8_t cmd_read_mem);
    /// Get data from read memory.  Data should be read by even sized packs or
    /// loading of word addressed data will fail.
    /// - returns: AVRISP_OK or AVRISP_FAILED for bad parameters.
    AvrIspResult read_continue (uint8_t *data, uint16_t size);
    /// End read command.
    /// - returns: AVRISP_OK or AVRISP_FAILED if too early.
    AvrIspResult read_end ();
    /// Program miscellaneous memory (fuse, lock).
    /// - cmd: program command.
    void program_misc (const uint8_t cmd[4]);
    /// Read miscellaneous memory (fuse, lock, signature, osccal).
    /// - ret_addr: transfer index at which the return value must be read.
    /// - cmd: read command.
    uint8_t read_misc (uint8_t ret_addr, const uint8_t cmd[4]);
    /// Generic SPI access.
    /// - num_tx: number of bytes to transmit.
    /// - num_rx: number of bytes to receive.
    /// - rx_start: start reception after this number of transmitted bytes.
    /// - dout: buffer to read sent bytes.
    /// - din: buffer to write received bytes.
    /// Limitation: no support for doing this in several chunks as memory
    /// programing and reading.
    void multi (uint8_t num_tx, uint8_t num_rx, uint8_t rx_start,
                const uint8_t *dout, uint8_t *din);
  private:
    /// Transmit a 16 bit data.
    void spi_tx_16 (uint16_t data);
    /// Transmit a 32 bit data and return last byte received.  This is used for
    /// RDY/BSY polling.
    uint8_t spi_tx_32 (uint32_t data);
  private:
    /// Hardware interface.
    AvrIspIntf &intf_;
    /// Current address.
    uint16_t addr_;
    /// Current extended address.
    uint8_t ext_addr_;
    /// Extended address loaded in device.
    uint8_t last_ext_addr_;
    /// Whether the device needs extended addressing.
    uint8_t larger_than_64k_;
    /// Programming start address (used for page program command).
    uint16_t start_addr_;
    /// Number of bytes left to process.
    uint16_t bytes_left_;
    /// Programming mode.
    uint8_t mode_;
    /// Programming delay if no other poll method.
    uint8_t delay_ms_;
    /// Write Program Memory or Load Page.
    uint8_t cmd_write_mem_;
    /// Write Page.
    uint8_t cmd_write_page_;
    /// Read Program Memory.
    uint8_t cmd_read_mem_;
    /// Value read until memory is programmed for value polling.
    uint8_t poll_[2];
    /// Whether the page can be polled (if almost one byte is not poll[0]).
    /// This is non zero if true, with LSB = 1 for high byte.
    uint8_t pollable_;
    /// Address to use for polling.
    uint16_t poll_addr_;
    /// Whether this is a flash memory.
    uint8_t flash_;
};

} // namespace ucoo

#endif // ucoolib_dev_avrisp_avrisp_hh