aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c')
-rw-r--r--lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c612
1 files changed, 612 insertions, 0 deletions
diff --git a/lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c b/lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c
new file mode 100644
index 000000000..0755e1bfe
--- /dev/null
+++ b/lib/chibios-contrib/demos/STM32/RT-STM32F429-DISCOVERY-DMA2D/main.c
@@ -0,0 +1,612 @@
1/*
2 Copyright (C) 2013-2015 Andrea Zoppi
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "ch.h"
18#include "hal.h"
19
20#include "chprintf.h"
21#include "shell.h"
22#if (HAL_USE_SERIAL_USB == TRUE)
23#include "usbcfg.h"
24#endif
25
26#include "ili9341.h"
27#include "hal_stm32_ltdc.h"
28#include "hal_stm32_dma2d.h"
29
30#include "res/wolf3d_vgagraph_chunk87.h"
31
32/*===========================================================================*/
33/* SDRAM related. */
34/*===========================================================================*/
35
36// TODO: Move constants below elsewhere, and normalize their name
37
38/* SDRAM bank base address.*/
39#define SDRAM_BANK_ADDR ((uint32_t)0xD0000000)
40
41/*
42 * FMC SDRAM Mode definition register defines
43 */
44#define FMC_SDCMR_MRD_BURST_LENGTH_1 ((uint16_t)0x0000)
45#define FMC_SDCMR_MRD_BURST_LENGTH_2 ((uint16_t)0x0001)
46#define FMC_SDCMR_MRD_BURST_LENGTH_4 ((uint16_t)0x0002)
47#define FMC_SDCMR_MRD_BURST_LENGTH_8 ((uint16_t)0x0004)
48#define FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
49#define FMC_SDCMR_MRD_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
50#define FMC_SDCMR_MRD_CAS_LATENCY_2 ((uint16_t)0x0020)
51#define FMC_SDCMR_MRD_CAS_LATENCY_3 ((uint16_t)0x0030)
52#define FMC_SDCMR_MRD_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
53#define FMC_SDCMR_MRD_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
54#define FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
55
56/*
57 * FMC_ReadPipe_Delay
58 */
59#define FMC_ReadPipe_Delay_0 ((uint32_t)0x00000000)
60#define FMC_ReadPipe_Delay_1 ((uint32_t)0x00002000)
61#define FMC_ReadPipe_Delay_2 ((uint32_t)0x00004000)
62#define FMC_ReadPipe_Delay_Mask ((uint32_t)0x00006000)
63
64/*
65 * FMC_Read_Burst
66 */
67#define FMC_Read_Burst_Disable ((uint32_t)0x00000000)
68#define FMC_Read_Burst_Enable ((uint32_t)0x00001000)
69#define FMC_Read_Burst_Mask ((uint32_t)0x00001000)
70
71/*
72 * FMC_SDClock_Period
73 */
74#define FMC_SDClock_Disable ((uint32_t)0x00000000)
75#define FMC_SDClock_Period_2 ((uint32_t)0x00000800)
76#define FMC_SDClock_Period_3 ((uint32_t)0x00000C00)
77#define FMC_SDClock_Period_Mask ((uint32_t)0x00000C00)
78
79/*
80 * FMC_ColumnBits_Number
81 */
82#define FMC_ColumnBits_Number_8b ((uint32_t)0x00000000)
83#define FMC_ColumnBits_Number_9b ((uint32_t)0x00000001)
84#define FMC_ColumnBits_Number_10b ((uint32_t)0x00000002)
85#define FMC_ColumnBits_Number_11b ((uint32_t)0x00000003)
86
87/*
88 * FMC_RowBits_Number
89 */
90#define FMC_RowBits_Number_11b ((uint32_t)0x00000000)
91#define FMC_RowBits_Number_12b ((uint32_t)0x00000004)
92#define FMC_RowBits_Number_13b ((uint32_t)0x00000008)
93
94/*
95 * FMC_SDMemory_Data_Width
96 */
97#define FMC_SDMemory_Width_8b ((uint32_t)0x00000000)
98#define FMC_SDMemory_Width_16b ((uint32_t)0x00000010)
99#define FMC_SDMemory_Width_32b ((uint32_t)0x00000020)
100
101/*
102 * FMC_InternalBank_Number
103 */
104#define FMC_InternalBank_Number_2 ((uint32_t)0x00000000)
105#define FMC_InternalBank_Number_4 ((uint32_t)0x00000040)
106
107/*
108 * FMC_CAS_Latency
109 */
110#define FMC_CAS_Latency_1 ((uint32_t)0x00000080)
111#define FMC_CAS_Latency_2 ((uint32_t)0x00000100)
112#define FMC_CAS_Latency_3 ((uint32_t)0x00000180)
113
114/*
115 * FMC_Write_Protection
116 */
117#define FMC_Write_Protection_Disable ((uint32_t)0x00000000)
118#define FMC_Write_Protection_Enable ((uint32_t)0x00000200)
119
120/*
121 * SDRAM driver configuration structure.
122 */
123static const SDRAMConfig sdram_cfg = {
124 .sdcr = (uint32_t)(FMC_ColumnBits_Number_8b |
125 FMC_RowBits_Number_12b |
126 FMC_SDMemory_Width_16b |
127 FMC_InternalBank_Number_4 |
128 FMC_CAS_Latency_3 |
129 FMC_Write_Protection_Disable |
130 FMC_SDClock_Period_2 |
131 FMC_Read_Burst_Disable |
132 FMC_ReadPipe_Delay_1),
133
134 .sdtr = (uint32_t)((2 - 1) | // FMC_LoadToActiveDelay = 2 (TMRD: 2 Clock cycles)
135 (7 << 4) | // FMC_ExitSelfRefreshDelay = 7 (TXSR: min=70ns (7x11.11ns))
136 (4 << 8) | // FMC_SelfRefreshTime = 4 (TRAS: min=42ns (4x11.11ns) max=120k (ns))
137 (7 << 12) | // FMC_RowCycleDelay = 7 (TRC: min=70 (7x11.11ns))
138 (2 << 16) | // FMC_WriteRecoveryTime = 2 (TWR: min=1+ 7ns (1+1x11.11ns))
139 (2 << 20) | // FMC_RPDelay = 2 (TRP: 20ns => 2x11.11ns)
140 (2 << 24)), // FMC_RCDDelay = 2 (TRCD: 20ns => 2x11.11ns)
141
142 .sdcmr = (uint32_t)(((4 - 1) << 5) |
143 ((FMC_SDCMR_MRD_BURST_LENGTH_2 |
144 FMC_SDCMR_MRD_BURST_TYPE_SEQUENTIAL |
145 FMC_SDCMR_MRD_CAS_LATENCY_3 |
146 FMC_SDCMR_MRD_OPERATING_MODE_STANDARD |
147 FMC_SDCMR_MRD_WRITEBURST_MODE_SINGLE) << 9)),
148
149 /* if (STM32_SYSCLK == 180000000) ->
150 64ms / 4096 = 15.625us
151 15.625us * 90MHz = 1406 - 20 = 1386 */
152 //.sdrtr = (1386 << 1),
153 .sdrtr = (uint32_t)(683 << 1),
154};
155
156/* SDRAM size, in bytes.*/
157#define IS42S16400J_SIZE (8 * 1024 * 1024)
158
159/*
160 * Erases the whole SDRAM bank.
161 */
162static void sdram_bulk_erase(void) {
163
164 volatile uint8_t *p = (volatile uint8_t *)SDRAM_BANK_ADDR;
165 volatile uint8_t *end = p + IS42S16400J_SIZE;
166 while (p < end)
167 *p++ = 0;
168}
169
170/*
171 * Red LED blinker thread, times are in milliseconds.
172 */
173static THD_WORKING_AREA(waThread1, 128);
174static THD_FUNCTION(Thread1, arg) {
175
176 (void)arg;
177 chRegSetThreadName("blinker1");
178 while (true) {
179 palClearPad(GPIOG, GPIOG_LED4_RED);
180 chThdSleepMilliseconds(500);
181 palSetPad(GPIOG, GPIOG_LED4_RED);
182 chThdSleepMilliseconds(500);
183 }
184}
185
186/*
187 * Green LED blinker thread, times are in milliseconds.
188 */
189static THD_WORKING_AREA(waThread2, 128);
190static THD_FUNCTION(Thread2, arg) {
191
192 (void)arg;
193 chRegSetThreadName("blinker2");
194 while (true) {
195 palClearPad(GPIOG, GPIOG_LED3_GREEN);
196 chThdSleepMilliseconds(250);
197 palSetPad(GPIOG, GPIOG_LED3_GREEN);
198 chThdSleepMilliseconds(250);
199 }
200}
201
202/*===========================================================================*/
203/* LTDC related. */
204/*===========================================================================*/
205
206static uint8_t frame_buffer[240 * 320 * 3] __attribute__((section(".ram7")));
207
208static uint8_t view_buffer[240 * 320];
209
210extern const ltdc_color_t wolf3d_palette[256];
211
212static const ltdc_window_t ltdc_fullscreen_wincfg = {
213 0,
214 240 - 1,
215 0,
216 320 - 1,
217};
218
219static const ltdc_frame_t ltdc_view_frmcfg1 = {
220 view_buffer,
221 240,
222 320,
223 240 * sizeof(uint8_t),
224 LTDC_FMT_L8,
225};
226
227static const ltdc_laycfg_t ltdc_view_laycfg1 = {
228 &ltdc_view_frmcfg1,
229 &ltdc_fullscreen_wincfg,
230 LTDC_COLOR_FUCHSIA,
231 0xFF,
232 0x980088,
233 wolf3d_palette,
234 256,
235 LTDC_BLEND_FIX1_FIX2,
236 (LTDC_LEF_ENABLE | LTDC_LEF_PALETTE),
237};
238
239static const ltdc_frame_t ltdc_screen_frmcfg1 = {
240 frame_buffer,
241 240,
242 320,
243 240 * 3,
244 LTDC_FMT_RGB888,
245};
246
247static const ltdc_laycfg_t ltdc_screen_laycfg1 = {
248 &ltdc_screen_frmcfg1,
249 &ltdc_fullscreen_wincfg,
250 LTDC_COLOR_FUCHSIA,
251 0xFF,
252 0x980088,
253 NULL,
254 0,
255 LTDC_BLEND_FIX1_FIX2,
256 LTDC_LEF_ENABLE,
257};
258
259static const LTDCConfig ltdc_cfg = {
260 /* Display specifications.*/
261 240, /**< Screen pixel width.*/
262 320, /**< Screen pixel height.*/
263 10, /**< Horizontal sync pixel width.*/
264 2, /**< Vertical sync pixel height.*/
265 20, /**< Horizontal back porch pixel width.*/
266 2, /**< Vertical back porch pixel height.*/
267 10, /**< Horizontal front porch pixel width.*/
268 4, /**< Vertical front porch pixel height.*/
269 0, /**< Driver configuration flags.*/
270
271 /* ISR callbacks.*/
272 NULL, /**< Line Interrupt ISR, or @p NULL.*/
273 NULL, /**< Register Reload ISR, or @p NULL.*/
274 NULL, /**< FIFO Underrun ISR, or @p NULL.*/
275 NULL, /**< Transfer Error ISR, or @p NULL.*/
276
277 /* Color and layer settings.*/
278 LTDC_COLOR_TEAL,
279 &ltdc_view_laycfg1,
280 NULL,
281};
282
283extern LTDCDriver LTDCD1;
284
285const SPIConfig spi_cfg5 = {
286 false,
287 NULL,
288 GPIOC,
289 GPIOC_SPI5_LCD_CS,
290 (((1 << 3) & SPI_CR1_BR) | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR),
291 0
292};
293
294extern SPIDriver SPID5;
295
296const ILI9341Config ili9341_cfg = {
297 &SPID5,
298 GPIOD,
299 GPIOD_LCD_WRX
300};
301
302static void initialize_lcd(void) {
303
304 static const uint8_t pgamma[15] = {
305 0x0F, 0x29, 0x24, 0x0C, 0x0E, 0x09, 0x4E, 0x78,
306 0x3C, 0x09, 0x13, 0x05, 0x17, 0x11, 0x00
307 };
308 static const uint8_t ngamma[15] = {
309 0x00, 0x16, 0x1B, 0x04, 0x11, 0x07, 0x31, 0x33,
310 0x42, 0x05, 0x0C, 0x0A, 0x28, 0x2F, 0x0F
311 };
312
313 ILI9341Driver *const lcdp = &ILI9341D1;
314
315 /* XOR-checkerboard texture.*/
316 unsigned x, y;
317 for (y = 0; y < 320; ++y)
318 for (x = 0; x < 240; ++x)
319 view_buffer[y * 240 + x] = (uint8_t)(x ^ y);
320
321 ili9341AcquireBus(lcdp);
322 ili9341Select(lcdp);
323
324 ili9341WriteCommand(lcdp, ILI9341_SET_FRAME_CTL_NORMAL);
325 ili9341WriteByte(lcdp, 0x00);
326 ili9341WriteByte(lcdp, 0x1B);
327
328 ili9341WriteCommand(lcdp, ILI9341_SET_FUNCTION_CTL);
329 ili9341WriteByte(lcdp, 0x0A);
330 ili9341WriteByte(lcdp, 0xA2);
331
332 ili9341WriteCommand(lcdp, ILI9341_SET_POWER_CTL_1);
333 ili9341WriteByte(lcdp, 0x10);
334
335 ili9341WriteCommand(lcdp, ILI9341_SET_POWER_CTL_2);
336 ili9341WriteByte(lcdp, 0x10);
337
338 ili9341WriteCommand(lcdp, ILI9341_SET_VCOM_CTL_1);
339 ili9341WriteByte(lcdp, 0x45);
340 ili9341WriteByte(lcdp, 0x15);
341
342 ili9341WriteCommand(lcdp, ILI9341_SET_VCOM_CTL_2);
343 ili9341WriteByte(lcdp, 0x90);
344
345 ili9341WriteCommand(lcdp, ILI9341_SET_MEM_ACS_CTL);
346 ili9341WriteByte(lcdp, 0xC8);
347
348 ili9341WriteCommand(lcdp, ILI9341_SET_RGB_IF_SIG_CTL);
349 ili9341WriteByte(lcdp, 0xC2);
350
351 ili9341WriteCommand(lcdp, ILI9341_SET_FUNCTION_CTL);
352 ili9341WriteByte(lcdp, 0x0A);
353 ili9341WriteByte(lcdp, 0xA7);
354 ili9341WriteByte(lcdp, 0x27);
355 ili9341WriteByte(lcdp, 0x04);
356
357 ili9341WriteCommand(lcdp, ILI9341_SET_COL_ADDR);
358 ili9341WriteByte(lcdp, 0x00);
359 ili9341WriteByte(lcdp, 0x00);
360 ili9341WriteByte(lcdp, 0x00);
361 ili9341WriteByte(lcdp, 0xEF);
362
363 ili9341WriteCommand(lcdp, ILI9341_SET_PAGE_ADDR);
364 ili9341WriteByte(lcdp, 0x00);
365 ili9341WriteByte(lcdp, 0x00);
366 ili9341WriteByte(lcdp, 0x01);
367 ili9341WriteByte(lcdp, 0x3F);
368
369 ili9341WriteCommand(lcdp, ILI9341_SET_IF_CTL);
370 ili9341WriteByte(lcdp, 0x01);
371 ili9341WriteByte(lcdp, 0x00);
372 ili9341WriteByte(lcdp, 0x06);
373
374 ili9341WriteCommand(lcdp, ILI9341_SET_GAMMA);
375 ili9341WriteByte(lcdp, 0x01);
376
377 ili9341WriteCommand(lcdp, ILI9341_SET_PGAMMA);
378 ili9341WriteChunk(lcdp, pgamma, 15);
379
380 ili9341WriteCommand(lcdp, ILI9341_SET_NGAMMA);
381 ili9341WriteChunk(lcdp, ngamma, 15);
382
383 ili9341WriteCommand(lcdp, ILI9341_CMD_SLEEP_OFF);
384 chThdSleepMilliseconds(10);
385
386 ili9341WriteCommand(lcdp, ILI9341_CMD_DISPLAY_ON);
387 ili9341WriteCommand(lcdp, ILI9341_SET_MEM);
388 chThdSleepMilliseconds(10);
389
390 ili9341Unselect(lcdp);
391 ili9341ReleaseBus(lcdp);
392}
393
394static const DMA2DConfig dma2d_cfg = {
395 /* ISR callbacks.*/
396 NULL, /**< Configuration error, or @p NULL.*/
397 NULL, /**< Palette transfer done, or @p NULL.*/
398 NULL, /**< Palette access error, or @p NULL.*/
399 NULL, /**< Transfer watermark, or @p NULL.*/
400 NULL, /**< Transfer complete, or @p NULL.*/
401 NULL /**< Transfer error, or @p NULL.*/
402};
403
404static const dma2d_palcfg_t dma2d_palcfg = {
405 wolf3d_palette,
406 256,
407 DMA2D_FMT_ARGB8888
408};
409
410static const dma2d_laycfg_t dma2d_bg_laycfg = {
411 view_buffer,
412 0,
413 DMA2D_FMT_L8,
414 DMA2D_COLOR_RED,
415 0xFF,
416 &dma2d_palcfg
417};
418
419static const dma2d_laycfg_t dma2d_fg_laycfg = {
420 (void *)wolf3d_vgagraph_chunk87,
421 0,
422 DMA2D_FMT_L8,
423 DMA2D_COLOR_LIME,
424 0xFF,
425 &dma2d_palcfg
426};
427
428static const dma2d_laycfg_t dma2d_frame_laycfg = {
429 frame_buffer,
430 0,
431 DMA2D_FMT_RGB888,
432 DMA2D_COLOR_BLUE,
433 0xFF,
434 NULL
435};
436
437static void dma2d_test(void) {
438
439 DMA2DDriver *const dma2dp = &DMA2DD1;
440 LTDCDriver *const ltdcp = &LTDCD1;
441
442 chThdSleepSeconds(1);
443
444 ltdcBgSetConfig(ltdcp, &ltdc_screen_laycfg1);
445 ltdcReload(ltdcp, TRUE);
446
447 dma2dAcquireBus(dma2dp);
448
449 /* Target the frame buffer by default.*/
450 dma2dBgSetConfig(dma2dp, &dma2d_frame_laycfg);
451 dma2dFgSetConfig(dma2dp, &dma2d_frame_laycfg);
452 dma2dOutSetConfig(dma2dp, &dma2d_frame_laycfg);
453
454 /* Copy the background.*/
455 dma2dFgSetConfig(dma2dp, &dma2d_bg_laycfg);
456 dma2dJobSetMode(dma2dp, DMA2D_JOB_CONVERT);
457 dma2dJobSetSize(dma2dp, 240, 320);
458 dma2dJobExecute(dma2dp);
459
460 /* Draw the splashscren picture at (8, 0).*/
461 dma2dFgSetConfig(dma2dp, &dma2d_fg_laycfg);
462 dma2dOutSetAddress(dma2dp, dma2dComputeAddress(
463 frame_buffer, ltdc_screen_frmcfg1.pitch, DMA2D_FMT_RGB888, 8, 0
464 ));
465 dma2dOutSetWrapOffset(dma2dp, ltdc_screen_frmcfg1.width - 200);
466 dma2dJobSetMode(dma2dp, DMA2D_JOB_CONVERT);
467 dma2dJobSetSize(dma2dp, 200, 320);
468 dma2dJobExecute(dma2dp);
469
470 dma2dReleaseBus(dma2dp);
471}
472
473/*===========================================================================*/
474/* Command line related. */
475/*===========================================================================*/
476
477
478#define SHELL_WA_SIZE THD_WORKING_AREA_SIZE(2048)
479#define TEST_WA_SIZE THD_WORKING_AREA_SIZE(256)
480
481static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[]) {
482 (void)argv;
483 if (argc > 0) {
484 chprintf(chp, "Usage: reset\r\n");
485 return;
486 }
487
488 chprintf(chp, "Will reset in 200ms\r\n");
489 chThdSleepMilliseconds(200);
490 NVIC_SystemReset();
491}
492
493static const ShellCommand commands[] = {
494 {"reset", cmd_reset},
495 {NULL, NULL}
496};
497
498static const ShellConfig shell_cfg1 = {
499#if (HAL_USE_SERIAL_USB == TRUE)
500 (BaseSequentialStream *)&SDU2,
501#else
502 (BaseSequentialStream *)&SD1,
503#endif
504 commands
505};
506
507/*===========================================================================*/
508/* Initialization and main thread. */
509/*===========================================================================*/
510
511/*
512 * Application entry point.
513 */
514int main(void) {
515 thread_t *shelltp = NULL;
516
517 /*
518 * System initializations.
519 * - HAL initialization, this also initializes the configured device drivers
520 * and performs the board-specific initializations.
521 * - Kernel initialization, the main() function becomes a thread and the
522 * RTOS is active.
523 */
524 halInit();
525 chSysInit();
526
527 /*
528 * Shell manager initialization.
529 */
530 shellInit();
531
532#if (HAL_USE_SERIAL_USB == TRUE)
533 /*
534 * Initializes a serial-over-USB CDC driver.
535 */
536 sduObjectInit(&SDU2);
537 sduStart(&SDU2, &serusbcfg);
538
539 /*
540 * Activates the USB driver and then the USB bus pull-up on D+.
541 * Note, a delay is inserted in order to not have to disconnect the cable
542 * after a reset.
543 */
544 usbDisconnectBus(serusbcfg.usbp);
545 chThdSleepMilliseconds(1000);
546 usbStart(serusbcfg.usbp, &usbcfg);
547 usbConnectBus(serusbcfg.usbp);
548#else
549 /*
550 * Initializes serial port.
551 */
552 sdStart(&SD1, NULL);
553#endif /* HAL_USE_SERIAL_USB */
554
555 /*
556 * Initialise FSMC for SDRAM.
557 */
558 sdramInit();
559 sdramStart(&SDRAMD1, &sdram_cfg);
560 sdram_bulk_erase();
561
562 /*
563 * Activates the LCD-related drivers.
564 */
565 spiStart(&SPID5, &spi_cfg5);
566 ili9341ObjectInit(&ILI9341D1);
567 ili9341Start(&ILI9341D1, &ili9341_cfg);
568 initialize_lcd();
569 ltdcInit();
570 ltdcStart(&LTDCD1, &ltdc_cfg);
571
572 /*
573 * Activates the DMA2D-related drivers.
574 */
575 dma2dInit();
576 dma2dStart(&DMA2DD1, &dma2d_cfg);
577 dma2d_test();
578
579 /*
580 * Creating the blinker threads.
581 */
582 chThdCreateStatic(waThread1, sizeof(waThread1),
583 NORMALPRIO + 10, Thread1, NULL);
584 chThdCreateStatic(waThread2, sizeof(waThread2),
585 NORMALPRIO + 10, Thread2, NULL);
586
587 /*
588 * Normal main() thread activity, in this demo it just performs
589 * a shell respawn upon its termination.
590 */
591 while (true) {
592 if (!shelltp) {
593#if (HAL_USE_SERIAL_USB == TRUE)
594 if (SDU2.config->usbp->state == USB_ACTIVE) {
595 /* Spawns a new shell.*/
596 shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, "shell", NORMALPRIO, shellThread, (void *) &shell_cfg1);
597 }
598#else
599 shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE, "shell", NORMALPRIO, shellThread, (void *) &shell_cfg1);
600#endif
601 }
602 else {
603 /* If the previous shell exited.*/
604 if (chThdTerminatedX(shelltp)) {
605 /* Recovers memory of the previous shell.*/
606 chThdRelease(shelltp);
607 shelltp = NULL;
608 }
609 }
610 chThdSleepMilliseconds(500);
611 }
612}