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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
diff --git a/apps/main.c b/apps/main.c
index 677eeb5..91a63c9 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -162,6 +162,7 @@ static void app_main(void)
     root_menu();
 }

+static int init_dircache(bool preinit) INIT_ATTR;
 static int init_dircache(bool preinit)
 {
 #ifdef HAVE_DIRCACHE
@@ -237,6 +238,7 @@ static int init_dircache(bool preinit)
 }

 #ifdef HAVE_TAGCACHE
+static void init_tagcache(void) INIT_ATTR;
 static void init_tagcache(void)
 {
     bool clear = false;
@@ -366,6 +368,7 @@ static void init(void)

 #else

+static void init(void) INIT_ATTR;
 static void init(void)
 {
     int rc;
diff --git a/apps/playback.c b/apps/playback.c
index bebbfb1..c88387f 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -1991,6 +1991,7 @@ static void audio_thread(void)
 /* Initialize the audio system - called from init() in main.c.
  * Last function because of all the references to internal symbols
  */
+void audio_init(void) INIT_ATTR;
 void audio_init(void)
 {
     unsigned int audio_thread_id;
diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h
index 7277b46..129d1dd 100644
--- a/apps/recorder/radio.h
+++ b/apps/recorder/radio.h
@@ -27,7 +27,7 @@

 #if CONFIG_TUNER
 void radio_load_presets(char *filename);
-void radio_init(void);
+void radio_init(void) INIT_ATTR;
 int radio_screen(void);
 void radio_start(void);
 void radio_pause(void);
diff --git a/apps/tagcache.h b/apps/tagcache.h
index f238bc0..1488c3b 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -239,7 +239,7 @@ bool tagcache_is_ramcache(void);
 bool tagcache_fill_tags(struct mp3entry *id3, const char *filename);
 void tagcache_unload_ramcache(void);
 #endif
-void tagcache_init(void);
+void tagcache_init(void) INIT_ATTR;
 bool tagcache_is_initialized(void);
 bool tagcache_is_usable(void);
 void tagcache_start_scan(void);
diff --git a/apps/tree.h b/apps/tree.h
index 3b31d02..f3057e8 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -71,8 +71,8 @@ struct tree_context {
 };

 void tree_drawlists(void);
-void tree_mem_init(void);
-void tree_gui_init(void);
+void tree_mem_init(void) INIT_ATTR;
+void tree_gui_init(void) INIT_ATTR;
 void get_current_file(char* buffer, int buffer_len);
 void set_dirfilter(int l_dirfilter);
 void set_current_file(char *path);
diff --git a/firmware/buffer.c b/firmware/buffer.c
index 07d06cd..2bd312d 100644
--- a/firmware/buffer.c
+++ b/firmware/buffer.c
@@ -19,6 +19,7 @@
  *
  ****************************************************************************/
 #include <stdio.h>
+#include "config.h"
 #include "buffer.h"

 #ifdef SIMULATOR
@@ -31,6 +32,7 @@ extern unsigned char audiobuffer[];

 unsigned char *audiobuf;

+void buffer_init(void) INIT_ATTR;
 void buffer_init(void)
 {
     /* 32-bit aligned */
diff --git a/firmware/export/adc.h b/firmware/export/adc.h
index 275db45..4a0d384 100644
--- a/firmware/export/adc.h
+++ b/firmware/export/adc.h
@@ -25,7 +25,7 @@
 #include "adc-target.h"

 unsigned short adc_read(int channel);
-void adc_init(void);
+void adc_init(void) INIT_ATTR;

 #ifndef NEED_ADC_CLOSE
 #define adc_close()
diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h
index c440db4..3b33e1a 100644
--- a/firmware/export/backlight.h
+++ b/firmware/export/backlight.h
@@ -36,7 +36,7 @@ void backlight_off(void);
 void backlight_set_timeout(int value);

 #ifdef HAVE_BACKLIGHT
-void backlight_init(void);
+void backlight_init(void) INIT_ATTR;
 void backlight_close(void);

 int  backlight_get_current_timeout(void);
diff --git a/firmware/export/button.h b/firmware/export/button.h
index 3aac1af..097f50a 100644
--- a/firmware/export/button.h
+++ b/firmware/export/button.h
@@ -30,7 +30,7 @@

 extern struct event_queue button_queue;

-void button_init (void);
+void button_init (void) INIT_ATTR;
 void button_close(void);
 int button_queue_count(void);
 long button_get (bool block);
diff --git a/firmware/export/config.h b/firmware/export/config.h
index adc03d5..2f63b92 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -725,6 +725,11 @@ Lyre prototype 1 */
 #define IBSS_ATTR
 #define STATICIRAM static
 #endif
+#if defined(CPU_PP) && !defined(SIMULATOR)
+#define INIT_ATTR       __attribute__ ((section(".init")))
+#else
+#define INIT_ATTR
+#endif

 #if defined(SIMULATOR) && defined(__APPLE__)
 #define DATA_ATTR       __attribute__ ((section("__DATA, .data")))
diff --git a/firmware/export/font.h b/firmware/export/font.h
index 75b012d..14b6f01 100644
--- a/firmware/export/font.h
+++ b/firmware/export/font.h
@@ -109,7 +109,7 @@ struct font {
 };

 /* font routines*/
-void font_init(void);
+void font_init(void) INIT_ATTR;
 struct font* font_load(const char *path);
 struct font* font_get(int font);
 void font_reset(void);
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 89f3943..e70762c 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -175,8 +175,8 @@ extern void lcd_write_command(int byte);
 extern void lcd_write_command_e(int cmd, int data);
 extern void lcd_write_command_ex(int cmd, int data1, int data2);
 extern void lcd_write_data(const fb_data* p_bytes, int count);
-extern void lcd_init(void);
-extern void lcd_init_device(void);
+extern void lcd_init(void) INIT_ATTR;
+extern void lcd_init_device(void) INIT_ATTR;

 extern void lcd_backlight(bool on);
 extern int  lcd_default_contrast(void);
diff --git a/firmware/export/power.h b/firmware/export/power.h
index 5cd6996..1071587 100644
--- a/firmware/export/power.h
+++ b/firmware/export/power.h
@@ -83,7 +83,7 @@ bool charging_state(void);

 #ifndef SIMULATOR

-void power_init(void);
+void power_init(void) INIT_ATTR;

 bool ide_powered(void);
 #endif
diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h
index c49cd0e..23ef447 100644
--- a/firmware/export/powermgmt.h
+++ b/firmware/export/powermgmt.h
@@ -131,7 +131,7 @@ extern const unsigned short percent_to_volt_charge[11];
 #endif

 /* Start up power management thread */
-void powermgmt_init(void);
+void powermgmt_init(void) INIT_ATTR;

 #endif /* SIMULATOR */

diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h
index 0fcb06a..f472e14 100644
--- a/firmware/export/scroll_engine.h
+++ b/firmware/export/scroll_engine.h
@@ -28,7 +28,7 @@
 #include <lcd.h>
 #include "file.h"

-void scroll_init(void);
+void scroll_init(void) INIT_ATTR;
 void lcd_scroll_stop(const struct viewport* vp);
 void lcd_scroll_stop_line(const struct viewport* vp, int y);
 void lcd_scroll_fn(void);
diff --git a/firmware/export/tuner.h b/firmware/export/tuner.h
index b27e660..30f0925 100644
--- a/firmware/export/tuner.h
+++ b/firmware/export/tuner.h
@@ -139,7 +139,7 @@ enum

 /** **/

-void tuner_init(void);
+void tuner_init(void) INIT_ATTR;

 #endif /* #if CONFIG_TUNER */

diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index d432b39..b1e57ea 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -123,7 +123,7 @@ struct usb_transfer_completion_event_data
 };
 #endif /* HAVE_USBSTACK */

-void usb_init(void);
+void usb_init(void) INIT_ATTR;
 void usb_enable(bool on);
 void usb_attach(void);
 void usb_start_monitoring(void);
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index b5b1b72..de35b23 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -84,7 +84,7 @@ typedef struct {
     DIR_UNCACHED *regulardir;
 } DIR_CACHED;

-void dircache_init(void);
+void dircache_init(void) INIT_ATTR;
 int dircache_load(void);
 int dircache_save(void);
 int dircache_build(int last_size);
diff --git a/firmware/kernel.c b/firmware/kernel.c
index d076d6d..7c02024 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -103,6 +103,7 @@ static int remove_array_ptr(void **arr, void *ptr)
 /****************************************************************************
  * Standard kernel stuff
  ****************************************************************************/
+void kernel_init(void) INIT_ATTR;
 void kernel_init(void)
 {
     /* Init the threading API */
diff --git a/firmware/target/arm/crt0-pp.S b/firmware/target/arm/crt0-pp.S
index bd1fc03..3b19e69 100644
--- a/firmware/target/arm/crt0-pp.S
+++ b/firmware/target/arm/crt0-pp.S
@@ -213,6 +213,17 @@ cpu_init:
     strhi  r5, [r3], #4
     bhi    1b

+    /* copy init data to codec buffer */
+    ldr    r2, =_initstart
+    ldr    r3, =_initend
+    ldr    r4, =_initcopy
+
+1:
+    cmp     r3, r2
+    ldrhi   r5, [r4], #4
+    strhi   r5, [r2], #4
+    bhi 1b
+
     /* Zero out IBSS */
     ldr    r2, =_iedata
     ldr    r3, =_iend
diff --git a/firmware/target/arm/sandisk/app.lds b/firmware/target/arm/sandisk/app.lds
index 3010644..12ffc8f 100644
--- a/firmware/target/arm/sandisk/app.lds
+++ b/firmware/target/arm/sandisk/app.lds
@@ -37,8 +37,9 @@ STARTUP(target/arm/crt0-pp.o)

 MEMORY
 {
-    DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
-    IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+    DRAM : ORIGIN = DRAMORIG,     LENGTH = DRAMSIZE
+    IRAM : ORIGIN = IRAMORIG,     LENGTH = IRAMSIZE
+    INIT : ORIGIN = ENDAUDIOADDR, LENGTH = CODECSIZE
 }

 SECTIONS
@@ -126,6 +127,17 @@ SECTIONS

     _iramcopy = LOADADDR(.iram);

+
+    .init ENDAUDIOADDR : 
+    {
+        . = ALIGN(4);
+        _initstart = .;
+        *(.init)
+        _initend = .;
+    } AT> DRAM
+
+    _initcopy = LOADADDR(.init);
+
     .idle_stacks (NOLOAD) :
     {
        *(.idle_stacks)
@@ -175,6 +187,7 @@ SECTIONS
     .audiobuf (NOLOAD) :
     {
         _audiobuffer = .;
+        . = ALIGN(0x4);
         audiobuffer = .;
     } > DRAM

diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index 03f6a1b..96d1326 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -353,6 +353,7 @@ static void lcd_display_off(void)
 }
 #endif

+void lcd_init_device(void) INIT_ATTR;
 void lcd_init_device(void)
 {
 /* All this is magic worked out by MrH */
@@ -435,6 +436,7 @@ void lcd_init_device(void)
 #endif

     LCD_REG_6 |= 1; /* Start DMA */
+    _backlight_set_brightness(0);
 }

 #if defined(HAVE_LCD_ENABLE)
diff --git a/firmware/thread.c b/firmware/thread.c
index a63641e..33c7f27 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -724,7 +724,8 @@ static void __attribute__((naked))
  * initializations.
  *---------------------------------------------------------------------------
  */
-static void core_thread_init(unsigned int core)
+static void core_thread_init(unsigned int core) INIT_ATTR;
+static void core_thread_init(unsigned int core) 
 {
     if (core == CPU)
     {
@@ -3033,6 +3034,7 @@ unsigned int switch_core(unsigned int new_core)
  * are safe to perform.
  *---------------------------------------------------------------------------
  */
+void init_threads(void) INIT_ATTR;
 void init_threads(void)
 {
     const unsigned int core = CURRENT_CORE;