blob: 633313376a38338254d1a43c5f11b8f4b8b4a887 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <inttypes.h>
#include "os/mynewt.h"
#include <console/console.h>
#include <hal/hal_bsp.h>
#include <hal/hal_flash.h>
#include <hal/hal_flash_int.h>
#include <shell/shell.h>
#include <stdio.h>
#include <string.h>
#define SPIFLASH_STRESS_TEST_TASK_COUNT 3
struct runtest_task {
struct os_task task;
char name[sizeof "taskX"];
OS_TASK_STACK_DEFINE_NOSTATIC(stack, MYNEWT_VAL(SPIFLASH_STRESS_TEST_STACK_SIZE));
};
static struct runtest_task runtest_tasks[SPIFLASH_STRESS_TEST_TASK_COUNT];
static int runtest_next_task_idx;
struct task_cfg {
uint8_t flash_area_id;
uint32_t flash_area_offset;
uint32_t flash_area_size;
int increment;
int pin;
} task_args[] = {
{ MYNEWT_VAL(SPIFLASH_STRESS_TEST_FLASH_AREA_ID), 0x00000, 0x01000, 1, 11 },
{ MYNEWT_VAL(SPIFLASH_STRESS_TEST_FLASH_AREA_ID), 0x02000, 0x06000, 7, 12 },
{ MYNEWT_VAL(SPIFLASH_STRESS_TEST_FLASH_AREA_ID), 0x08000, 0x08000, 13, 13 },
};
struct os_task *
runtest_init_task(os_task_func_t task_func, uint8_t prio)
{
struct os_task *task = NULL;
#if 1
os_stack_t *stack;
char *name;
int rc;
if (runtest_next_task_idx >= SPIFLASH_STRESS_TEST_TASK_COUNT) {
assert("No more test tasks");
return NULL;
}
task = &runtest_tasks[runtest_next_task_idx].task;
stack = runtest_tasks[runtest_next_task_idx].stack;
name = runtest_tasks[runtest_next_task_idx].name;
strcpy(name, "task");
name[4] = '0' + runtest_next_task_idx;
name[5] = '\0';
rc = os_task_init(task, name, task_func, &task_args[runtest_next_task_idx],
prio, OS_WAIT_FOREVER, stack,
MYNEWT_VAL(SPIFLASH_STRESS_TEST_STACK_SIZE));
assert(rc == 0);
#endif
runtest_next_task_idx++;
return task;
}
const uint8_t pattern[] = "1234567890 We choose to go to the moon in this decade and do the other things, not because they are easy, but because they are hard.";
struct os_sem sem;
void flash_test_task1(void *arg)
{
const struct flash_area *fa;
struct task_cfg *cfg = arg;
int i;
int increment;
uint8_t pat_buf[sizeof(pattern)];
g_current_task->t_pad = cfg->pin;
if (flash_area_open(cfg->flash_area_id, &fa))
return;
while (1) {
os_sem_pend(&sem, OS_TIMEOUT_NEVER);
console_printf("Task %d starts\n", os_sched_get_current_task()->t_taskid);
flash_area_erase(fa, cfg->flash_area_offset, cfg->flash_area_size);
increment = cfg->increment;
int chunk = 0;
for (i = 0 ; i < cfg->flash_area_size; ) {
chunk += increment;
if (chunk < 0 || chunk > sizeof(pattern)) {
increment = -increment;
chunk += increment;
}
if (i + chunk > cfg->flash_area_size)
chunk = cfg->flash_area_size - i;
flash_area_write(fa, cfg->flash_area_offset + i, pattern, chunk);
i += chunk;
os_time_delay(1);
}
increment = cfg->increment;
chunk = 0;
for (i = 0 ; i < cfg->flash_area_size; ) {
chunk += increment;
if (chunk < 0 || chunk > sizeof(pattern)) {
increment = -increment;
chunk += increment;
}
memset(pat_buf, 0xDA, chunk);
if (i + chunk > cfg->flash_area_size)
chunk = cfg->flash_area_size - i;
flash_area_read(fa, cfg->flash_area_offset + i, pat_buf, chunk);
if (memcmp(pattern, pat_buf, chunk) != 0) {
console_printf("Flast write/read failed\n");
}
os_time_delay(1);
i += chunk;
}
console_printf("Task %d finished and waits for next start\n",
os_sched_get_current_task()->t_taskid);
}
}
static int spiflash_stress_test_cli_cmd(int argc, char **argv);
static struct shell_cmd spiflash_stress_cmd_struct = {
.sc_cmd = "flashstress",
.sc_cmd_func = spiflash_stress_test_cli_cmd
};
static int
spiflash_stress_test_cli_cmd(int argc, char **argv)
{
if (argc > 1 && (!strcmp(argv[1], "?") || !strcmp(argv[1], "help"))) {
console_printf("Commands Available\n");
console_printf("start\n");
return 0;
}
os_sem_release(&sem);
os_sem_release(&sem);
os_sem_release(&sem);
return 0;
}
/*
* Initialize the package. Only called from sysinit().
*/
void
spiflash_stress_test_init(void)
{
os_sem_init(&sem, 0);
runtest_init_task(flash_test_task1, MYNEWT_VAL(OS_MAIN_TASK_PRIO) + 1);
runtest_init_task(flash_test_task1, MYNEWT_VAL(OS_MAIN_TASK_PRIO) + 2);
runtest_init_task(flash_test_task1, MYNEWT_VAL(OS_MAIN_TASK_PRIO) + 3);
shell_cmd_register(&spiflash_stress_cmd_struct);
}