1 /*
2  * Copyright (c) 2017 Linaro Limited.
3  * Copyright (c) 2018 Nordic Semiconductor.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #include <stdlib.h>
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/flash.h>
13 #include <zephyr/shell/shell.h>
14 
15 #define PR_SHELL(sh, fmt, ...)				\
16 	shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__)
17 #define PR_ERROR(sh, fmt, ...)				\
18 	shell_fprintf(sh, SHELL_ERROR, fmt, ##__VA_ARGS__)
19 
20 /* Assumption: our devices have less than 64MB of memory */
21 #define RESERVED_MEM_MAP (CONFIG_SRAM_BASE_ADDRESS + 0x4000000)
22 #define FLASH_MEM         CONFIG_FLASH_BASE_ADDRESS
23 #define RAM_MEM           CONFIG_SRAM_BASE_ADDRESS
24 
25 /* MPU test command help texts */
26 #define READ_CMD_HELP  "Read from a reserved address in the memory map"
27 #define WRITE_CMD_HELP "Write in to boot FLASH/ROM"
28 #define RUN_CMD_HELP   "Run code located in RAM"
29 #define MTEST_CMD_HELP "Memory Test writes or reads a memory location.\n"    \
30 			"Command accepts 1 (Read) or 2 (Write) parameters."
31 
32 #if defined(CONFIG_SOC_FLASH_MCUX) || defined(CONFIG_SOC_FLASH_LPC) || \
33 	defined(CONFIG_SOC_FLASH_STM32)
34 static const struct device *const flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
35 #endif
36 
cmd_read(const struct shell * sh,size_t argc,char * argv[])37 static int cmd_read(const struct shell *sh, size_t argc, char *argv[])
38 {
39 	ARG_UNUSED(argc);
40 	ARG_UNUSED(argv);
41 
42 	uint32_t *p_mem = (uint32_t *) RESERVED_MEM_MAP;
43 
44 	/* Reads from an address that is reserved in the memory map */
45 	PR_SHELL(sh, "The value is: %d\n", *p_mem);
46 
47 	return 0;
48 }
49 
50 #if defined(CONFIG_SOC_FLASH_MCUX) || defined(CONFIG_SOC_FLASH_LPC)
cmd_write_mcux(const struct shell * sh,size_t argc,char * argv[])51 static int cmd_write_mcux(const struct shell *sh, size_t argc, char *argv[])
52 {
53 	ARG_UNUSED(argc);
54 	ARG_UNUSED(argv);
55 
56 	uint32_t value[2];
57 	uint32_t offset;
58 
59 	/* 128K reserved to the application */
60 	offset = FLASH_MEM + 0x20000;
61 	value[0] = 0xBADC0DE;
62 	value[1] = 0xBADC0DE;
63 
64 	PR_SHELL(sh, "write address: 0x%x\n", offset);
65 
66 	if (flash_write(flash_dev, offset, value,
67 				sizeof(value)) != 0) {
68 		PR_ERROR(sh, "Flash write failed!\n");
69 		return 1;
70 	}
71 
72 	return 0;
73 
74 }
75 #elif defined(CONFIG_SOC_FLASH_STM32)
cmd_write_stm32(const struct shell * sh,size_t argc,char * argv[])76 static int cmd_write_stm32(const struct shell *sh, size_t argc, char *argv[])
77 {
78 	ARG_UNUSED(argc);
79 	ARG_UNUSED(argv);
80 
81 	/* 16K reserved to the application */
82 	uint32_t offset = FLASH_MEM + 0x4000;
83 	uint32_t value = 0xBADC0DE;
84 
85 	PR_SHELL(sh, "write address: 0x%x\n", offset);
86 
87 	if (flash_write(flash_dev, offset, &value, sizeof(value)) != 0) {
88 		PR_ERROR(sh, "Flash write failed!\n");
89 		return 1;
90 	}
91 
92 	return 0;
93 }
94 #else
cmd_write(const struct shell * sh,size_t argc,char * argv[])95 static int cmd_write(const struct shell *sh, size_t argc, char *argv[])
96 {
97 	ARG_UNUSED(argc);
98 	ARG_UNUSED(argv);
99 
100 	/* 16K reserved to the application */
101 	uint32_t *p_mem = (uint32_t *) (FLASH_MEM + 0x4000);
102 
103 	PR_SHELL(sh, "write address: 0x%x\n", FLASH_MEM + 0x4000);
104 
105 	/* Write in to boot FLASH/ROM */
106 	*p_mem = 0xBADC0DE;
107 
108 	return 0;
109 }
110 #endif /* SOC_FLASH_MCUX || SOC_FLASH_LPC */
111 
cmd_run(const struct shell * sh,size_t argc,char * argv[])112 static int cmd_run(const struct shell *sh, size_t argc, char *argv[])
113 {
114 	ARG_UNUSED(argc);
115 	ARG_UNUSED(argv);
116 
117 	void (*func_ptr)(void) = (void (*)(void)) RAM_MEM;
118 
119 	/* Run code located in RAM */
120 	func_ptr();
121 
122 	return 0;
123 }
124 
cmd_mtest(const struct shell * sh,size_t argc,char * argv[])125 static int cmd_mtest(const struct shell *sh, size_t argc, char *argv[])
126 {
127 	uint32_t *mem;
128 	uint32_t val;
129 
130 	val = (uint32_t)strtol(argv[1], NULL, 16);
131 	mem = (uint32_t *) val;
132 
133 	if (argc == 2) {
134 		PR_SHELL(sh, "The value is: 0x%x\n", *mem);
135 	} else {
136 		*mem = (uint32_t) strtol(argv[2], NULL, 16);
137 	}
138 
139 	return 0;
140 }
141 
main(void)142 int main(void)
143 {
144 #if defined(CONFIG_SOC_FLASH_MCUX) || defined(CONFIG_SOC_FLASH_LPC) || \
145 	defined(CONFIG_SOC_FLASH_STM32)
146 	if (!device_is_ready(flash_dev)) {
147 		printk("Flash device not ready\n");
148 		return 0;
149 	}
150 #endif
151 	return 0;
152 }
153 
154 SHELL_STATIC_SUBCMD_SET_CREATE(sub_mpu,
155 	SHELL_CMD_ARG(mtest, NULL, MTEST_CMD_HELP, cmd_mtest, 2, 1),
156 	SHELL_CMD(read, NULL, READ_CMD_HELP, cmd_read),
157 	SHELL_CMD(run, NULL, RUN_CMD_HELP, cmd_run),
158 #if defined(CONFIG_SOC_FLASH_MCUX) || defined(CONFIG_SOC_FLASH_LPC)
159 	SHELL_CMD(write, NULL, WRITE_CMD_HELP, cmd_write_mcux),
160 #elif defined(CONFIG_SOC_FLASH_STM32)
161 	SHELL_CMD(write, NULL, WRITE_CMD_HELP, cmd_write_stm32),
162 #else
163 	SHELL_CMD(write, NULL, WRITE_CMD_HELP, cmd_write),
164 #endif /* SOC_FLASH_MCUX*/
165 	SHELL_SUBCMD_SET_END /* Array terminated. */
166 );
167 SHELL_CMD_REGISTER(mpu, &sub_mpu, "MPU related commands.", NULL);
168