]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Bootloader/main.c
d74d209fe8c252acc8ad0cf2e0868ddd328da750
[kiibohd-controller.git] / Bootloader / main.c
1 /* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
2  * Modifications by Jacob Alexander 2014-2015 <haata@kiibohd.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 // ----- Includes -----
19
20 // Local Includes
21 #include "mchck.h"
22 #include "dfu.desc.h"
23
24
25
26 // ----- Variables -----
27
28 /**
29  * Unfortunately we can't DMA directly to FlexRAM, so we'll have to stage here.
30  */
31 static char staging[ FLASH_SECTOR_SIZE ];
32
33
34
35 // ----- Functions -----
36
37 static enum dfu_status setup_write( size_t off, size_t len, void **buf )
38 {
39         GPIOA_PCOR |= (1<<5);
40         static int last = 0;
41
42         if ( len > sizeof(staging) )
43                 return (DFU_STATUS_errADDRESS);
44
45         // We only allow the last write to be less than one sector size.
46         if ( off == 0 )
47                 last = 0;
48         if ( last && len != 0 )
49                 return (DFU_STATUS_errADDRESS);
50         if ( len != FLASH_SECTOR_SIZE )
51         {
52                 last = 1;
53                 memset( staging, 0xff, sizeof(staging) );
54         }
55
56         *buf = staging;
57         return (DFU_STATUS_OK);
58 }
59
60 static enum dfu_status finish_write( void *buf, size_t off, size_t len )
61 {
62         void *target;
63         if ( len == 0 )
64                 return (DFU_STATUS_OK);
65
66         target = flash_get_staging_area(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE);
67         if ( !target )
68                 return (DFU_STATUS_errADDRESS);
69         memcpy( target, buf, len );
70
71         // Depending on the error return a different status
72         switch ( flash_program_sector(off + (uintptr_t)&_app_rom, FLASH_SECTOR_SIZE) )
73         {
74         /*
75         case FTFL_FSTAT_RDCOLERR: // Flash Read Collision Error
76         case FTFL_FSTAT_ACCERR:   // Flash Access Error
77         case FTFL_FSTAT_FPVIOL:   // Flash Protection Violation Error
78                 return (DFU_STATUS_errADDRESS);
79         case FTFL_FSTAT_MGSTAT0:  // Memory Controller Command Completion Error
80                 return (DFU_STATUS_errADDRESS);
81         */
82
83         case 0:
84         default: // No error
85                 return (DFU_STATUS_OK);
86         }
87 }
88
89
90 static struct dfu_ctx dfu_ctx;
91
92 void init_usb_bootloader( int config )
93 {
94         dfu_init(setup_write, finish_write, &dfu_ctx);
95 }
96
97 void main()
98 {
99 #if defined(_mk20dx128vlf5_) // Kiibohd-dfu / Infinity
100         // XXX McHCK uses B16 instead of A19
101
102         // Enabling LED to indicate we are in the bootloader
103         GPIOA_PDDR |= (1<<19);
104         // Setup pin - A19 - See Lib/pin_map.mchck for more details on pins
105         PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
106         GPIOA_PSOR |= (1<<19);
107
108 #elif defined(_mk20dx256vlh7_) // Kiibohd-dfu
109         // Enabling LED to indicate we are in the bootloader
110         GPIOA_PDDR |= (1<<5);
111         // Setup pin - A5 - See Lib/pin_map.mchck for more details on pins
112         PORTA_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
113         GPIOA_PSOR |= (1<<5);
114 #else
115 #error "Incompatible chip for bootloader"
116 #endif
117
118         //for (uint8_t c = 0; c < 20; c++)
119         /*
120         while( 1 )
121         {
122                 GPIOA_PTOR |= (1<<5);
123                 for (uint32_t d = 0; d < 7200000; d++ );
124         }
125         */
126
127         // XXX REMOVEME
128         /*
129         GPIOB_PDDR |= (1<<16);
130         PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
131         GPIOB_PSOR |= (1<<16);
132         */
133         // RST
134         GPIOC_PDDR |= (1<<8);
135         PORTC_PCR8 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
136         GPIOC_PSOR |= (1<<8);
137         /*
138         // CS1B
139         GPIOC_PDDR |= (1<<4);
140         PORTC_PCR4 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
141         GPIOC_PCOR |= (1<<4);
142         */
143         // Backlight
144         GPIOC_PDDR |= (1<<1);
145         PORTC_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
146         GPIOC_PCOR |= (1<<1);
147         GPIOC_PDDR |= (1<<2);
148         PORTC_PCR2 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
149         GPIOC_PCOR |= (1<<2);
150         GPIOC_PDDR |= (1<<3);
151         PORTC_PCR3 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
152         GPIOC_PCOR |= (1<<3);
153
154
155
156         flash_prepare_flashing();
157
158         uint32_t *position = &_app_rom;
159         usb_init( &dfu_device );
160         for (;;)
161         {
162                 usb_poll();
163
164                 /*
165                 for ( ; position < &_app_rom + 0x201; position++ )
166                 //for ( ; position < &_app_rom + 0x800; position++ )
167                 {
168                         if ( *position != 0xFFFFFFFF )
169                         {
170                         while( 1 )
171                         {
172                                 GPIOA_PTOR |= (1<<5);
173                                 for (uint32_t d = 0; d < 7200000; d++ );
174                         }
175                         }
176                 }
177                 */
178
179         }
180 }
181