working version!
This commit is contained in:
parent
c9ae314f71
commit
0ba0e0360f
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -170,6 +170,10 @@ dependencies = [
|
|||||||
"litrs",
|
"litrs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eb_cmds"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-executor"
|
name = "embassy-executor"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -603,7 +607,9 @@ dependencies = [
|
|||||||
"defmt",
|
"defmt",
|
||||||
"defmt-itm",
|
"defmt-itm",
|
||||||
"defmt-rtt",
|
"defmt-rtt",
|
||||||
|
"eb_cmds",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
|
"embassy-sync",
|
||||||
"embassy-usb",
|
"embassy-usb",
|
||||||
"futures",
|
"futures",
|
||||||
"u5-lib",
|
"u5-lib",
|
||||||
|
14
Cargo.toml
14
Cargo.toml
@ -19,7 +19,8 @@ cortex-m = { version = "0.7.7", features = [
|
|||||||
u5-lib = { path = "../u5_new",features = [
|
u5-lib = { path = "../u5_new",features = [
|
||||||
"stm32u5a5qj",
|
"stm32u5a5qj",
|
||||||
# "stm32u575zi"
|
# "stm32u575zi"
|
||||||
]}
|
], default-features = false }
|
||||||
|
eb_cmds = { path = "../ebutton_usb_cmds"}
|
||||||
critical-section = "1.1.2"
|
critical-section = "1.1.2"
|
||||||
defmt = "0.3.6"
|
defmt = "0.3.6"
|
||||||
defmt-rtt = { version = "0.4.0" }
|
defmt-rtt = { version = "0.4.0" }
|
||||||
@ -29,6 +30,7 @@ futures = { version = "0.3.17", default-features = false, fetures = [
|
|||||||
]}
|
]}
|
||||||
cortex-m-rt = { version = "0.7.3" }
|
cortex-m-rt = { version = "0.7.3" }
|
||||||
|
|
||||||
|
|
||||||
[dependencies.embassy-usb]
|
[dependencies.embassy-usb]
|
||||||
git = "https://github.com/embassy-rs/embassy"
|
git = "https://github.com/embassy-rs/embassy"
|
||||||
rev = "35f284e"
|
rev = "35f284e"
|
||||||
@ -38,11 +40,19 @@ features = ["nightly", "arch-cortex-m", "executor-thread"]
|
|||||||
git = "https://github.com/embassy-rs/embassy"
|
git = "https://github.com/embassy-rs/embassy"
|
||||||
rev = "35f284e"
|
rev = "35f284e"
|
||||||
|
|
||||||
|
[dependencies.embassy-sync]
|
||||||
|
git = "https://github.com/embassy-rs/embassy"
|
||||||
|
rev = "35f284e"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [dependencies.stm32-metapac]
|
# [dependencies.stm32-metapac]
|
||||||
# path = "../stm32-data/build/stm32-metapac"
|
# path = "../stm32-data/build/stm32-metapac"
|
||||||
# features = [ "memory-x", "rt"]
|
# features = [ "memory-x", "rt"]
|
||||||
|
|
||||||
# disable all optimizations
|
# disable all optimizations
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 1
|
||||||
debug = true
|
debug = true
|
@ -31,7 +31,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
async fn async_main(_spawner: Spawner) {
|
async fn async_main(_spawner: Spawner) {
|
||||||
clock::init_clock(true, false, clock::ClockFreqs::KernelFreq160Mhz);
|
clock::init_clock(true, true, false, clock::ClockFreqs::KernelFreq160Mhz);
|
||||||
BLUE.setup();
|
BLUE.setup();
|
||||||
defmt::info!("setup led finished!");
|
defmt::info!("setup led finished!");
|
||||||
loop {
|
loop {
|
||||||
|
219
src/main.rs
219
src/main.rs
@ -8,17 +8,21 @@ use core::panic::PanicInfo;
|
|||||||
use cortex_m::asm::delay;
|
use cortex_m::asm::delay;
|
||||||
|
|
||||||
use defmt_rtt as _;
|
use defmt_rtt as _;
|
||||||
use embassy_executor::{Spawner};
|
use eb_cmds::Command;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
use embassy_usb::{
|
use embassy_usb::{
|
||||||
Builder,
|
|
||||||
class::cdc_acm::{CdcAcmClass, State},
|
class::cdc_acm::{CdcAcmClass, State},
|
||||||
driver::EndpointError,
|
driver::EndpointError,
|
||||||
|
Builder,
|
||||||
};
|
};
|
||||||
use futures::future::{join};
|
use futures::future::join;
|
||||||
|
|
||||||
use u5_lib::{gpio::{SDMMC2_CMD_PD7, SDMMC2_D0_PB14}, *};
|
|
||||||
use u5_lib::clock::delay_ms;
|
use u5_lib::clock::delay_ms;
|
||||||
use u5_lib::com_interface::ComInterface;
|
use u5_lib::com_interface::ComInterface;
|
||||||
|
use u5_lib::{
|
||||||
|
gpio::{SDMMC2_CMD_PD7, SDMMC2_D0_PB14},
|
||||||
|
*,
|
||||||
|
};
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
@ -32,16 +36,21 @@ fn panic(_info: &PanicInfo) -> ! {
|
|||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn setup_camera() -> (gpio::GpioPort, i2c::I2c) {
|
fn setup_camera() -> (gpio::GpioPort, i2c::I2c) {
|
||||||
clock::set_mco(gpio::GPIO_MCO_PA8, clock::Mcosel::HSI, clock::Mcopre::DIV1); // clock. which use PA8 as clock output
|
clock::set_mco(gpio::GPIO_MCO_PA8, clock::Mcosel::HSI, clock::Mcopre::DIV1); // clock. which use PA8 as clock output
|
||||||
let cam_down = gpio::PD13;
|
let cam_down = gpio::PD13;
|
||||||
cam_down.setup();
|
cam_down.setup();
|
||||||
cam_down.set_high();
|
cam_down.set_high();
|
||||||
cam_down.set_low();
|
cam_down.set_low();
|
||||||
// wait for short time
|
// wait for short time
|
||||||
delay_ms(50);
|
delay_ms(50);
|
||||||
let mut i2c = i2c::I2c::new(i2c::I2cConfig::new(2, 100_000, gpio::I2C2_SDA_PF0, gpio::I2C2_SCL_PF1)).unwrap();
|
let mut i2c = i2c::I2c::new(i2c::I2cConfig::new(
|
||||||
|
2,
|
||||||
|
100_000,
|
||||||
|
gpio::I2C2_SDA_PF0,
|
||||||
|
gpio::I2C2_SCL_PF1,
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
// delay_ms(1);
|
// delay_ms(1);
|
||||||
camera::setup_camera(&mut i2c);
|
camera::setup_camera(&mut i2c);
|
||||||
(cam_down, i2c)
|
(cam_down, i2c)
|
||||||
@ -52,56 +61,123 @@ fn setup_led() -> gpio::GpioPort {
|
|||||||
green.setup();
|
green.setup();
|
||||||
green
|
green
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_sd() -> sdmmc::SdInstance {
|
fn setup_sd() -> sdmmc::SdInstance {
|
||||||
let mut sd = sdmmc::SdInstance::new( sdmmc::SDMMC2);
|
let mut sd = sdmmc::SdInstance::new(sdmmc::SDMMC2);
|
||||||
sd.init(gpio::SDMMC2_CK_PD6, SDMMC2_CMD_PD7, SDMMC2_D0_PB14);
|
sd.init(gpio::SDMMC2_CK_PD6, SDMMC2_CMD_PD7, SDMMC2_D0_PB14);
|
||||||
sd
|
sd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_dcmi() -> dcmi::DcmiPort {
|
||||||
|
let dcmi = dcmi::DCMI;
|
||||||
|
|
||||||
|
dcmi.init(
|
||||||
|
gpio::DCMI_D0_PA9, // todo: updat the pin
|
||||||
|
gpio::DCMI_D1_PA10,
|
||||||
|
gpio::DCMI_D2_PE0,
|
||||||
|
gpio::DCMI_D3_PE1,
|
||||||
|
gpio::DCMI_D4_PE4,
|
||||||
|
gpio::DCMI_D5_PB6,
|
||||||
|
gpio::DCMI_D6_PE5,
|
||||||
|
gpio::DCMI_D7_PE6,
|
||||||
|
gpio::DCMI_HSYNC_PA4,
|
||||||
|
gpio::DCMI_VSYNC_PB7,
|
||||||
|
gpio::DCMI_PIXCLK_PD9,
|
||||||
|
);
|
||||||
|
dcmi
|
||||||
|
}
|
||||||
|
|
||||||
// #[embassy_executor::main]
|
// #[embassy_executor::main]
|
||||||
#[task]
|
#[task]
|
||||||
async fn async_main(spawner: Spawner) {
|
async fn async_main(spawner: Spawner) {
|
||||||
// clock::init_clock(true, false, clock::ClockFreqs::KernelFreq4Mhz);
|
// clock::init_clock(true, false, clock::ClockFreqs::KernelFreq4Mhz);
|
||||||
clock::init_clock(false, true, clock::ClockFreqs::KernelFreq160Mhz);
|
clock::init_clock(false, true, true, clock::ClockFreqs::KernelFreq160Mhz);
|
||||||
// let (cam_down, i2c) = setup_camera();
|
|
||||||
// cam_down.set_high();
|
// cam_down.set_high();
|
||||||
delay_ms(200);
|
delay_ms(200);
|
||||||
defmt::info!("camera init finished!");
|
defmt::info!("camera init finished!");
|
||||||
let sd = setup_sd();
|
|
||||||
defmt::info!("sd init finished!");
|
defmt::info!("sd init finished!");
|
||||||
let green = setup_led();
|
let green = setup_led();
|
||||||
spawner.spawn(btn()).unwrap();
|
spawner.spawn(btn()).unwrap();
|
||||||
spawner.spawn(pwr::vddusb_monitor_up()).unwrap();
|
spawner.spawn(pwr::vddusb_monitor_up()).unwrap();
|
||||||
spawner.spawn(usb_task()).unwrap();
|
spawner.spawn(usb_task()).unwrap();
|
||||||
// start emmc
|
// init dcmi
|
||||||
|
|
||||||
|
let (cam_down, mut i2c, sd, dcmi) =
|
||||||
|
clock::hclk_request(clock::ClockFreqs::KernelFreq160Mhz, || {
|
||||||
|
let (cam_down, i2c) = setup_camera();
|
||||||
|
let sd = setup_sd();
|
||||||
|
let dcmi = set_dcmi();
|
||||||
|
(cam_down, i2c, sd, dcmi)
|
||||||
|
});
|
||||||
|
|
||||||
defmt::info!("usb init finished!");
|
defmt::info!("usb init finished!");
|
||||||
|
let mut power_on = false;
|
||||||
loop {
|
loop {
|
||||||
exti::EXTI2_PB2.wait_for_raising().await;
|
if !power_on {
|
||||||
|
let val = POWER_SIGNAL.wait().await;
|
||||||
|
if val {
|
||||||
|
defmt::info!("power on");
|
||||||
|
power_on = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if POWER_SIGNAL.signaled() {
|
||||||
|
let val = POWER_SIGNAL.wait().await;
|
||||||
|
power_on = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !power_on {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exti::EXTI2_PB2.wait_for_raising().await;
|
||||||
|
// clock::init_clock(false, true, clock::ClockFreqs::KernelFreq160Mhz);
|
||||||
|
// clock::set_mco(gpio::GPIO_MCO_PA8, clock::Mcosel::HSI, clock::Mcopre::DIV1); // clock. which use PA8 as clock output
|
||||||
|
// delay_ms(1);
|
||||||
|
// rtc::rtc_interrupt().await;
|
||||||
green.toggle();
|
green.toggle();
|
||||||
defmt::info!("exti2 triggered");
|
let mut pic_buf = [0u8; 700_000];
|
||||||
unsafe {defmt::info!("deep sleep flag: {}", low_power::REF_COUNT_DEEP);}
|
// deep sleep is not allowed
|
||||||
|
clock::hclk_request_async(clock::ClockFreqs::KernelFreq160Mhz, || async {
|
||||||
|
low_power::run_no_deep_sleep_async(|| async {
|
||||||
|
camera::capture(&cam_down, &mut i2c, &dcmi, &mut pic_buf).await;
|
||||||
|
camera::save_picture(&mut pic_buf, &sd).await;
|
||||||
|
defmt::info!("finish save picture, ########################");
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use low_power::Executor;
|
use low_power::Executor;
|
||||||
|
|
||||||
#[cortex_m_rt::entry]
|
#[cortex_m_rt::entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
Executor::take().run(|spawner| {
|
Executor::take().run(|spawner| {
|
||||||
// unwrap!(spawner.spawn(async_main(spawner)));
|
|
||||||
spawner.spawn(async_main(spawner)).unwrap();
|
spawner.spawn(async_main(spawner)).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
use embassy_sync::signal::Signal;
|
||||||
|
|
||||||
|
// static mut POWER_STATE: bool = false;
|
||||||
|
static POWER_SIGNAL: Signal<CriticalSectionRawMutex, bool> = Signal::new();
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn btn() {
|
async fn btn() {
|
||||||
let _last_time: (u8, u8, u8) = (0, 0, 0);
|
let _last_time: (u8, u8, u8) = (0, 0, 0);
|
||||||
defmt::info!("waiting for btn");
|
defmt::info!("waiting for btn");
|
||||||
loop {
|
unsafe {
|
||||||
exti::EXTI13_PC13.wait_for_raising().await;
|
static mut POWER_STATE: bool = false;
|
||||||
|
loop {
|
||||||
|
exti::EXTI2_PB2.wait_for_raising().await;
|
||||||
|
defmt::info!("btn pressed");
|
||||||
|
let green: gpio::GpioPort = gpio::PD14;
|
||||||
|
green.toggle();
|
||||||
|
POWER_STATE = !POWER_STATE;
|
||||||
|
POWER_SIGNAL.signal(POWER_STATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,23 +245,112 @@ impl From<EndpointError> for Disconnected {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: these should be rewrite
|
||||||
|
const IMG_START_BLOCK: u32 = 10;
|
||||||
|
const IMG_SIZE: u32 = 2000;
|
||||||
|
// 2000 block = 2000 * 512 = 1M
|
||||||
|
const SIZE_BLOCK: u32 = 1; // first block store the number of image files
|
||||||
|
|
||||||
async fn usb_handler<'d>(class: &mut CdcAcmClass<'d, usb_otg::Driver>) -> Result<(), Disconnected> {
|
async fn usb_handler<'d>(class: &mut CdcAcmClass<'d, usb_otg::Driver>) -> Result<(), Disconnected> {
|
||||||
let mut buf: [u8; 128] = [0; 128];
|
let mut in_buf: [u8; 128] = [0; 128];
|
||||||
// the maximum size of the command is 64 bytes
|
// the maximum size of the command is 64 bytes
|
||||||
|
|
||||||
|
let sd = setup_sd();
|
||||||
defmt::info!("start usb handler");
|
defmt::info!("start usb handler");
|
||||||
loop {
|
loop {
|
||||||
// select(future1, future2)
|
// select(future1, future2)
|
||||||
let ret = class.read_packet(&mut buf).await;
|
let ret = class.read_packet(&mut in_buf).await;
|
||||||
match ret {
|
let n = match ret {
|
||||||
Ok(n) => {
|
Ok(n) => n,
|
||||||
defmt::info!("read {} bytes", n);
|
Err(EndpointError::Disabled) => return Err(Disconnected {}),
|
||||||
class.write_packet(&buf[0..n]).await.unwrap();
|
Err(EndpointError::BufferOverflow) => panic!("Buffer overflow"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let command = eb_cmds::Command::from_array(&in_buf[..n]);
|
||||||
|
match command {
|
||||||
|
Command::SetTim(year, month, day, hour, minute, second, period) => {
|
||||||
|
// rtc::set_time(year, month, day, hour, minute, second, period);
|
||||||
|
rtc::setup(year, month, day, hour, minute, second, period, rtc::RtcSource::LSE);
|
||||||
|
let response = eb_cmds::Response::SetTim(0);
|
||||||
|
let (buf, len) = response.to_array();
|
||||||
|
class.write_packet(&buf[..len]).await.unwrap();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Command::GetTim => {
|
||||||
defmt::info!("error: {:?}", e);
|
let date = rtc::get_date();
|
||||||
return Err(e.into());
|
let time = rtc::get_time();
|
||||||
|
let response = eb_cmds::Response::GetTim(date.0, date.1, date.2, time.0, time.1, time.2);
|
||||||
|
let (buf, len) = response.to_array();
|
||||||
|
class.write_packet(&buf[..len]).await.unwrap();
|
||||||
}
|
}
|
||||||
|
Command::GetPic(id) => {
|
||||||
|
let mut buf = [0; 64];
|
||||||
|
buf[0] = 0x02;
|
||||||
|
let mut pic_buf = [0; 512];
|
||||||
|
let start_block = (id + IMG_START_BLOCK) * IMG_SIZE;
|
||||||
|
sd.read_single_block_async(&mut pic_buf, start_block).await.unwrap();
|
||||||
|
// get the end of picture
|
||||||
|
let pic_end = ((pic_buf[0] as u32) << 24)
|
||||||
|
| ((pic_buf[1] as u32) << 16)
|
||||||
|
| ((pic_buf[2] as u32) << 8)
|
||||||
|
| (pic_buf[3] as u32);
|
||||||
|
let block_count: u32 = ((pic_end + 512 - 1) / 512) as u32;
|
||||||
|
let mut ordinal = 0;
|
||||||
|
let mut send_len: usize;
|
||||||
|
let mut res: eb_cmds::Response;
|
||||||
|
let mut start = 16;
|
||||||
|
loop {
|
||||||
|
if start >= pic_buf.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(ordinal, send_len, res) =
|
||||||
|
eb_cmds::Response::pic_res_from_data(id, ordinal, &pic_buf[start..]);
|
||||||
|
if send_len == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start += send_len;
|
||||||
|
|
||||||
|
let (buf_tmp, len) = res.to_array();
|
||||||
|
class.write_packet(&buf_tmp[0..len]).await.unwrap();
|
||||||
|
// Timer::after(Duration::from_millis(100)).await;
|
||||||
|
// LED_BLUE.toggle();
|
||||||
|
}
|
||||||
|
// LED_GREEN.toggle();
|
||||||
|
for block in 1..block_count {
|
||||||
|
// sd.read_single_block(&mut buf, start_block + block).unwrap();
|
||||||
|
// let mut pic_buf = [0; 512]; // why without this line, the program not work?
|
||||||
|
sd.read_single_block_async(&mut pic_buf, start_block + block).await.unwrap();
|
||||||
|
start = 0;
|
||||||
|
loop {
|
||||||
|
if start >= pic_buf.len() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(ordinal, send_len, res) =
|
||||||
|
eb_cmds::Response::pic_res_from_data(id, ordinal, &pic_buf[start..]);
|
||||||
|
if send_len == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
start += send_len;
|
||||||
|
let (buf_tmp, len) = res.to_array();
|
||||||
|
class.write_packet(&buf_tmp[0..len]).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command::GetPicNum => {
|
||||||
|
let mut buf = [0u8; 512];
|
||||||
|
sd.read_single_block_async(&mut buf, SIZE_BLOCK).await.unwrap();
|
||||||
|
let num = ((buf[0] as u32) << 24)
|
||||||
|
| ((buf[1] as u32) << 16)
|
||||||
|
| ((buf[2] as u32) << 8)
|
||||||
|
| (buf[3] as u32);
|
||||||
|
// ebcmd::Response::GetPicNum(num)
|
||||||
|
let res = eb_cmds::Response::GetPicNum(num);
|
||||||
|
let (buf, len) = res.to_array();
|
||||||
|
class.write_packet(&buf[0..len]).await.unwrap();
|
||||||
|
}
|
||||||
|
Command::ClearPic => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let ret = select(class.read_packet(&mut buf), class.write_packet(&buf)).await;
|
||||||
// class.write_packet(&buf[0..n]).await.unwrap();
|
// class.write_packet(&buf[0..n]).await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user