blob: 64d27d27a9f34c8e1a2d318b9a558760c8e0f325 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* Licensed 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 <stdbool.h>
#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sw/device/lib/camera_hm01b0.h"
#include "sw/device/lib/dif/dif_cam_ctrl.h"
#include "sw/device/lib/dif/dif_isp_wrapper.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_uart.h"
#include "sw/device/lib/runtime/irq.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/runtime/print.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"
#include "sw/device/lib/testing/test_framework/test_util.h"
OTTF_DEFINE_TEST_CONFIG();
static dif_cam_ctrl_t cam_ctrl;
static dif_rv_plic_t plic;
static dif_isp_wrapper_t isp_wrapper;
static dif_uart_t smc_uart;
static volatile bool isp_frame_done_irq_seen = false;
void ottf_external_isr(void) {
dif_rv_plic_irq_id_t interrupt_id;
CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kTopMatchaPlicTargetIbex0Smc,
&interrupt_id));
top_matcha_plic_peripheral_smc_t peripheral_id =
top_matcha_plic_interrupt_for_peripheral_smc[interrupt_id];
CHECK(peripheral_id == kTopMatchaPlicPeripheralIspWrapper ||
peripheral_id == kTopMatchaPlicPeripheralCamI2c,
"ISR from something besides ISP_WRAPPER or CAM_I2C");
switch (peripheral_id) {
case kTopMatchaPlicPeripheralCamI2c: {
CHECK_DIF_OK(camera_hm01b0_irq_handler(interrupt_id));
break;
}
case kTopMatchaPlicPeripheralIspWrapper: {
uint32_t mi_mis, isp_mis;
CHECK_DIF_OK(dif_isp_wrapper_read_mi_mis(&isp_wrapper, &mi_mis));
CHECK_DIF_OK(dif_isp_wrapper_read_isp_mis(&isp_wrapper, &isp_mis));
CHECK_DIF_OK(dif_isp_wrapper_write_isp_icr(&isp_wrapper, isp_mis));
CHECK_DIF_OK(dif_isp_wrapper_write_mi_icr(&isp_wrapper, mi_mis));
CHECK_DIF_OK(dif_isp_wrapper_irq_acknowledge_all(&isp_wrapper));
if (isp_mis & (1 << 5)) {
isp_frame_done_irq_seen = true;
}
break;
}
default:
LOG_FATAL("Unexpected peripheral_id!");
}
CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kTopMatchaPlicTargetIbex0Smc,
interrupt_id));
}
void _ottf_main(void) {
CHECK_DIF_OK(dif_cam_ctrl_init(
mmio_region_from_addr(TOP_MATCHA_CAM_CTRL_BASE_ADDR), &cam_ctrl));
CHECK_DIF_OK(dif_isp_wrapper_init(
mmio_region_from_addr(TOP_MATCHA_ISP_WRAPPER_BASE_ADDR), &isp_wrapper));
CHECK_DIF_OK(dif_rv_plic_init(
mmio_region_from_addr(TOP_MATCHA_RV_PLIC_SMC_BASE_ADDR), &plic));
// Initialize the SMC UART to enable logging for non-DV simulation platforms.
if (kDeviceType != kDeviceSimDV) {
init_uart(TOP_MATCHA_SMC_UART_BASE_ADDR, &smc_uart);
}
LOG_INFO("Hello from the SMC!");
// Configure interrupts for camera and ISP.
CHECK_DIF_OK(camera_hm01b0_irq_init(&plic, kTopMatchaPlicTargetIbex0Smc));
CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
&plic, kTopMatchaPlicIrqIdIspWrapperIsp, kTopMatchaPlicTargetIbex0Smc,
kDifToggleEnabled));
CHECK_DIF_OK(dif_rv_plic_irq_set_enabled(
&plic, kTopMatchaPlicIrqIdIspWrapperMi, kTopMatchaPlicTargetIbex0Smc,
kDifToggleEnabled));
CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
&plic, kTopMatchaPlicIrqIdIspWrapperIsp, kDifRvPlicMaxPriority));
CHECK_DIF_OK(dif_rv_plic_irq_set_priority(
&plic, kTopMatchaPlicIrqIdIspWrapperMi, kDifRvPlicMaxPriority));
irq_global_ctrl(true);
irq_external_ctrl(true);
CHECK_DIF_OK(camera_hm01b0_init());
// Configure for a full frame, and trigger the camera.
// Check the test pattern after the frame is captured.
memset((void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR, 0, 324 * 324);
CHECK_DIF_OK(camera_hm01b0_set_default_registers(
kCameraHm01b0Resolution324x324, kCameraHm01b0FrameRate1Fps));
CHECK_DIF_OK(
camera_hm01b0_set_test_pattern(kCameraHm01b0TestPatternWalkingOnes));
CHECK_DIF_OK(dif_isp_wrapper_set_raw_324x324_byp_324x324_en(&isp_wrapper));
CHECK_DIF_OK(dif_cam_ctrl_set_en(&cam_ctrl));
while (!isp_frame_done_irq_seen) {
asm volatile("wfi");
}
isp_frame_done_irq_seen = false;
CHECK_DIF_OK(dif_cam_ctrl_clear_en(&cam_ctrl));
CHECK_DIF_OK(camera_hm01b0_validate_test_pattern(
(const uint8_t*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR,
kCameraHm01b0TestPatternWalkingOnes, kCameraHm01b0Resolution324x324));
// Configure for a 320x240 frame, and trigger the camera.
// Check the test pattern after the frame is captured.
memset((void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR, 0, 320 * 240);
CHECK_DIF_OK(camera_hm01b0_set_default_registers(
kCameraHm01b0Resolution320x240, kCameraHm01b0FrameRate1Fps));
CHECK_DIF_OK(
camera_hm01b0_set_test_pattern(kCameraHm01b0TestPatternWalkingOnes));
CHECK_DIF_OK(dif_isp_wrapper_set_raw_320x240_byp_320x240_en(&isp_wrapper));
CHECK_DIF_OK(dif_cam_ctrl_set_en(&cam_ctrl));
while (!isp_frame_done_irq_seen) {
asm volatile("wfi");
}
isp_frame_done_irq_seen = false;
CHECK_DIF_OK(dif_cam_ctrl_clear_en(&cam_ctrl));
CHECK_DIF_OK(camera_hm01b0_validate_test_pattern(
(const uint8_t*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR,
kCameraHm01b0TestPatternWalkingOnes, kCameraHm01b0Resolution320x240));
test_status_set(kTestStatusPassed);
while (true) {
asm volatile("wfi");
}
}