Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix flash tests #122

Merged
merged 11 commits into from
Feb 23, 2024
1 change: 0 additions & 1 deletion .github/workflows/ports_psoc6.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ jobs:
cp mpy-psoc6_${{ matrix.board }}_${{ needs.server-build.outputs.commit_sha }}/firmware.hex .
source tools/ci.sh && ci_psoc6_flash_multiple_devices ${{ matrix.board }} firmware.hex tools/psoc6/${{ runner.name }}-devs.yml
- name: Run psoc6 filesystem test
if: matrix.board == 'CY8CPROTO-062-4343W'
run: |
devs=($(python tools/psoc6/get-devs.py port -b ${{ matrix.board }} -y tools/psoc6/${{ runner.name }}-devs.yml))
cd tests
Expand Down
2 changes: 1 addition & 1 deletion ports/psoc6/freeze/vfs_lfs2.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
vfs = os.VfsLfs2(bdev, progsize=write_size, readsize=read_size)
os.mount(vfs, "/")

print("LFS2 filesystem mounted at /\n")
print("Internal LFS2 filesystem mounted at /\n")

del machine, os, psoc6, bdev, vfs, read_size, write_size
2 changes: 1 addition & 1 deletion ports/psoc6/freeze/vfs_lfs2_qspi_flash.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
vfs = os.VfsLfs2(bdev, progsize=read_size, readsize=write_size)
os.mount(vfs, "/flash")

print("LFS2 filesystem mounted at /flash\n")
print("External LFS2 filesystem mounted at /flash\n")

del machine, os, psoc6, bdev, vfs, read_size, write_size
75 changes: 55 additions & 20 deletions ports/psoc6/psoc6_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "py/runtime.h"
#include "extmod/vfs.h"
#include "modpsoc6.h"
#include "mplogger.h"
#include "mphalport.h"


Expand Down Expand Up @@ -83,10 +84,49 @@ STATIC psoc6_flash_obj_t psoc6_flash_obj = {
};

cyhal_flash_t cyhal_flash_obj;
cyhal_flash_info_t flash_info;

// Helper function to get internal flash configurations
void get_flash_info(void) {
mplogger_print("\nRetrieving internal flash info...\n");
cyhal_flash_get_info(&cyhal_flash_obj, &flash_info);
/* Wait for 100ms for the flash write to complete */
uint32_t timeout = 100;
/* Wait for the command to finish execution */
while ((true != cyhal_flash_is_operation_complete(&cyhal_flash_obj)) && (0 < timeout)) {
timeout--;
cyhal_system_delay_ms(1); /* delay one millisecond each iteration */
}
uint32_t total_flash_size = 0;
uint32_t page_size = 0;
if (0 != timeout) {
for (int index = 0; index < flash_info.block_count; index++)
{
const cyhal_flash_block_info_t *block_info = flash_info.blocks;
total_flash_size += block_info->size;
page_size = block_info->page_size;
}
}

mplogger_print("\nTotal flash size (MB): %ld\n", total_flash_size / (1024 * 1024));
mplogger_print("\nTotal no. of blocks: %d\n", flash_info.block_count);
mplogger_print("\nPage size (bytes): %ld\n", page_size);
}

STATIC mp_obj_t psoc6_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
cyhal_flash_init(&cyhal_flash_obj);
mplogger_print("\nFlash constructor invoked\n");
#if MICROPY_LOGGER_DEBUG
get_flash_info();
#endif

cy_rslt_t result = CY_RSLT_SUCCESS;

result = cyhal_flash_init(&cyhal_flash_obj);
if (CY_RSLT_SUCCESS != result) {
mplogger_print("psoc6_flash_make_new() failed while initializing flash with error code : %u\n", CY_RSLT_GET_CODE(result));
mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT("psoc6_flash_make_new() - QSPI flash init failed !\n"));
}

// Parse arguments
enum { ARG_start, ARG_len };

Expand Down Expand Up @@ -128,6 +168,8 @@ STATIC mp_obj_t psoc6_flash_make_new(const mp_obj_type_t *type, size_t n_args, s
}

STATIC mp_obj_t psoc6_flash_readblocks(size_t n_args, const mp_obj_t *args) {
mplogger_print("\nFlash readblocks called\n");

psoc6_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES;
mp_buffer_info_t bufinfo;
Expand All @@ -138,9 +180,9 @@ STATIC mp_obj_t psoc6_flash_readblocks(size_t n_args, const mp_obj_t *args) {
}

cy_rslt_t result = cyhal_flash_read(&cyhal_flash_obj, self->flash_base + offset, bufinfo.buf, bufinfo.len);

if (CY_RSLT_SUCCESS != result) {
mp_raise_ValueError(MP_ERROR_TEXT("cyhal_rtc_read failed !"));
mplogger_print("psoc6_flash_readblocks() failed while reading the flash with error code: %u\n", CY_RSLT_GET_CODE(result));
mp_raise_ValueError(MP_ERROR_TEXT("psoc6_flash_readblocks() - Flash Read failed !"));
}

// TODO: or simply do it like this ?
Expand All @@ -151,28 +193,25 @@ STATIC mp_obj_t psoc6_flash_readblocks(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(psoc6_flash_readblocks_obj, 3, 4, psoc6_flash_readblocks);

STATIC mp_obj_t psoc6_flash_writeblocks(size_t n_args, const mp_obj_t *args) {

mplogger_print("\nFlash writeblocks called\n");
psoc6_flash_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint32_t offset = mp_obj_get_int(args[1]) * BLOCK_SIZE_BYTES;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);

if (n_args == 3) {
// Flash erase/program must run in an atomic section.
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();

uint32_t numSectors = bufinfo.len / FLASH_SECTOR_SIZE;

for (uint32_t i = 0; i <= numSectors; ++i) {
cy_rslt_t result = cyhal_flash_erase(&cyhal_flash_obj, self->flash_base + offset + i * FLASH_SECTOR_SIZE);

if (CY_RSLT_SUCCESS != result) {
mp_raise_ValueError(MP_ERROR_TEXT("cyhal_rtc_read failed !"));
mplogger_print("\npsoc6_flash_writeblocks() failed while erasing the flash with error code: %u\n", CY_RSLT_GET_CODE(result));
mp_raise_ValueError(MP_ERROR_TEXT("psoc6_flash_writeblocks() - Flash Erase failed !"));
}
}

MICROPY_END_ATOMIC_SECTION(atomic_state);
// TODO: check return value
} else {
offset += mp_obj_get_int(args[3]);
}
Expand All @@ -181,23 +220,19 @@ STATIC mp_obj_t psoc6_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
// Flash erase/program must run in an atomic section.
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();

uint32_t numPages = bufinfo.len / FLASH_SECTOR_SIZE; // TODO: should be page size

for (uint32_t i = 0; i <= numPages; ++i) {
cy_rslt_t result = cyhal_flash_program(&cyhal_flash_obj, self->flash_base + offset + i * FLASH_SECTOR_SIZE, bufinfo.buf + i * FLASH_SECTOR_SIZE);

if (CY_RSLT_SUCCESS != result) {
mp_raise_ValueError(MP_ERROR_TEXT("cyhal_rtc_read failed !"));
}
cy_rslt_t result = cyhal_flash_write(&cyhal_flash_obj, self->flash_base + offset, bufinfo.buf);
if (CY_RSLT_SUCCESS != result) {
mplogger_print("psoc6_flash_writeblocks() failed while writing with error code: %u\n", CY_RSLT_GET_CODE(result));
mp_raise_ValueError(MP_ERROR_TEXT("psoc6_flash_writeblocks() - Flash Write failed!"));
}

MICROPY_END_ATOMIC_SECTION(atomic_state);
// TODO: check return value
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(psoc6_flash_writeblocks_obj, 3, 4, psoc6_flash_writeblocks);

STATIC mp_obj_t psoc6_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_in) {
mplogger_print("Flash ioctrl called\n");
psoc6_flash_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t cmd = mp_obj_get_int(cmd_in);

Expand All @@ -219,11 +254,11 @@ STATIC mp_obj_t psoc6_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t ar
cy_rslt_t result = cyhal_flash_erase(&cyhal_flash_obj, self->flash_base + offset);

if (CY_RSLT_SUCCESS != result) {
mp_raise_ValueError(MP_ERROR_TEXT("cyhal_rtc_read failed !"));
mplogger_print("psoc6_flash_ioctl() failed while erasing block with error code: %u\n", CY_RSLT_GET_CODE(result));
mp_raise_ValueError(MP_ERROR_TEXT("psoc6_flash_ioctl() - Flash erase failed !"));
}

MICROPY_END_ATOMIC_SECTION(atomic_state);
// TODO: check return value
return MP_OBJ_NEW_SMALL_INT(0);
}
default:
Expand Down
5 changes: 2 additions & 3 deletions ports/psoc6/psoc6_qspi_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ void get_ext_flash_info(void) {

STATIC mp_obj_t psoc6_qspi_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
mplogger_print("\nQSPI flash constructor invoked\n");
#if MICROPY_LOGGER_DEBUG
get_ext_flash_info();
#endif

cy_rslt_t result = CY_RSLT_SUCCESS;

Expand Down Expand Up @@ -155,7 +157,6 @@ STATIC mp_obj_t psoc6_qspi_flash_readblocks(size_t n_args, const mp_obj_t *args)
if (n_args == 4) {
offset += mp_obj_get_int(args[3]);
}
mplogger_print("Address in hex:%04X, Length:%u\n", self->flash_base + offset, bufinfo.len);

mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
cy_rslt_t result = cy_serial_flash_qspi_read(self->flash_base + offset, bufinfo.len, bufinfo.buf);
Expand All @@ -182,7 +183,6 @@ STATIC mp_obj_t psoc6_qspi_flash_writeblocks(size_t n_args, const mp_obj_t *args
uint32_t numSectors = bufinfo.len / EXT_FLASH_SECTOR_SIZE;

for (uint32_t i = 0; i <= numSectors; ++i) {
mplogger_print("Address in hex:%04X\n", self->flash_base + offset + i * EXT_FLASH_SECTOR_SIZE);
cy_rslt_t result = cy_serial_flash_qspi_erase(self->flash_base + offset + i * EXT_FLASH_SECTOR_SIZE, cy_serial_flash_qspi_get_erase_size(self->flash_base + offset + i * EXT_FLASH_SECTOR_SIZE));
// the cy_serial_flash_qspi_get_erase_size() function call is necessary to keep the erase at sector boundary, else it throws errors.

Expand Down Expand Up @@ -214,7 +214,6 @@ STATIC mp_obj_t psoc6_qspi_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj
mplogger_print("QSPI flash ioctrl called\n");
psoc6_qspi_flash_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t cmd = mp_obj_get_int(cmd_in);
mplogger_print("option:%u\n", cmd);

switch (cmd) {
case MP_BLOCKDEV_IOCTL_INIT:
Expand Down
4 changes: 0 additions & 4 deletions tests/psoc6/flash.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import os, psoc6

machine = os.uname().machine
if "CY8CPROTO-063-BLE" in machine:
# TODO: Not working for this board. Neither the timer timing is correct
print("SKIP")
raise SystemExit

# Try to mount the filesystem, and format the flash if it doesn't exist.
# create block device object based on whichever flash is active
Expand Down
41 changes: 10 additions & 31 deletions tests/psoc6/run_psoc6_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -259,49 +259,28 @@ if [ ${fs} -eq 1 ]; then
echo
echo " done."
echo

chmod 777 ./psoc6/test_scripts/fs.py

echo " attempting to save different test files in flash "
echo
echo " saving test_fs_small_file.txt to FS - (size : 10KB) "

command_output=$( ../tools/mpremote/mpremote.py connect ${device0} cp ./psoc6/test_inputs/test_fs_small_file.txt :/)
exp_output="cp ./psoc6/test_inputs/test_fs_small_file.txt :/"
if [ "$command_output" != "$exp_output" ]; then
echo "Error: Cannot save small file."
python3 ./psoc6/test_scripts/fs.py ${device0} 0
if [ $? -ne 0 ]; then
echo "FS test failed"
exit 1
fi

# On device file saving tests for medium and large size takes considerable amount of time. Hence only when needed, this should be triggered.
if [ ${afs} -eq 1 ]; then

echo " saving test_fs_medium_file.txt to FS - (size : 500KB) "
command_output=$(../tools/mpremote/mpremote.py connect ${device0} cp ./psoc6/test_inputs/test_fs_medium_file.txt :/)
exp_output="cp ./psoc6/test_inputs/test_fs_medium_file.txt :/"
if [ "$command_output" != "$exp_output" ]; then
echo "Error: Cannot save medium file."
exit 1
fi

echo " saving test_fs_large_file.txt to FS - (size : 1MB) "
command_output=$(../tools/mpremote/mpremote.py connect ${device0} cp ./psoc6/test_inputs/test_fs_large_file.txt :/)
exp_output="cp ./psoc6/test_inputs/test_fs_large_file.txt :/"
if [ "$command_output" != "$exp_output" ]; then
echo "Error: Cannot save large file."
exit 1
fi

python3 ./psoc6/test_scripts/fs.py ${device0} 1
if [ $? -ne 0 ]; then
echo "FS test failed"
exit 1
fi
fi

echo
echo " done."
echo

fi


if [ ${implemented} -eq 1 ]; then


echo " running implemented tests ..."
echo

Expand Down
82 changes: 82 additions & 0 deletions tests/psoc6/test_scripts/fs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import subprocess
import sys
import os

device = sys.argv[1]
test_type = sys.argv[2]

# local and remote(MPY device) paths
local_small_file_path = "./psoc6/test_inputs/test_fs_small_file.txt"
local_medium_file_path = "./psoc6/test_inputs/test_fs_medium_file.txt"
local_large_file_path = "./psoc6/test_inputs/test_fs_large_file.txt"
remote_directory_path = "/"

# out and exp file paths
basic_test_op_fp = "./psoc6/test_scripts/fs_basic.py.out"
adv_test_op_fp = "./psoc6/test_scripts/fs_adv.py.out"
exp_basic_op_fp = "./psoc6/test_scripts/fs_basic.py.exp"
exp_adv_op_fp = "./psoc6/test_scripts/fs_adv.py.exp"

# List of mpremote commands
mpr_connect = f"../tools/mpremote/mpremote.py connect {device}"
mpr_small_file_cp = f"{mpr_connect} cp {local_small_file_path} :{remote_directory_path}"
mpr_medium_file_cp = f"{mpr_connect} cp {local_medium_file_path} :{remote_directory_path}"
mpr_large_file_cp = f"{mpr_connect} cp {local_large_file_path} :{remote_directory_path}"
mpr_ls = f"{mpr_connect} fs ls /"
mpr_rm = f"{mpr_connect} fs rm "


def exec(cmd, op_file_path="null"):
if cmd == mpr_rm:
# Check if file is present already
output = subprocess.run(f"{mpr_ls} | grep {op_file_path}", shell=True, capture_output=True)
# If the file is present, remove it
if output.returncode == 0:
subprocess.run(f"{cmd} {op_file_path}", shell=True, capture_output=False)
else:
with open(op_file_path, "a") as file:
subprocess.check_call(cmd, shell=True, stdout=file)


def validate_test(op, exp_op):
with open(op, "r") as output_file:
output = [line.strip() for line in output_file]

with open(exp_op, "r") as exp_output_file:
exp_output = [line.strip() for line in exp_output_file]

if output != exp_output:
print("Operation failed!")
sys.exit(1)
else:
print("Operation successful!")


def fs_basic_test():
print("Running basic test")
print("Saving small file - 10KB")
exec(mpr_rm, "test_fs_small_file.txt")
exec(mpr_small_file_cp, basic_test_op_fp)
validate_test(basic_test_op_fp, exp_basic_op_fp)
os.remove(basic_test_op_fp)


def fs_adv_test():
print("Running advance test")
print("Saving small files - 10KB")
exec(mpr_rm, "test_fs_small_file.txt")
exec(mpr_small_file_cp, adv_test_op_fp)
print("Saving medium files - 500KB")
exec(mpr_rm, "test_fs_medium_file.txt")
exec(mpr_medium_file_cp, adv_test_op_fp)
print("Saving large files - 1MB")
exec(mpr_rm, "test_fs_large_file.txt")
exec(mpr_large_file_cp, adv_test_op_fp)
validate_test(adv_test_op_fp, exp_adv_op_fp)
os.remove(adv_test_op_fp)


if test_type == "0":
fs_basic_test()
if test_type == "1":
fs_adv_test()
3 changes: 3 additions & 0 deletions tests/psoc6/test_scripts/fs_adv.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cp ./psoc6/test_inputs/test_fs_small_file.txt :/
cp ./psoc6/test_inputs/test_fs_medium_file.txt :/
cp ./psoc6/test_inputs/test_fs_large_file.txt :/
1 change: 1 addition & 0 deletions tests/psoc6/test_scripts/fs_basic.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cp ./psoc6/test_inputs/test_fs_small_file.txt :/
Loading