| // Copyright 2024 The Pigweed Authors |
| // |
| // 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 |
| // |
| // https://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 "system/system.h" |
| |
| #include "device/bme688.h" |
| #include "device/ltr559_light_and_prox_sensor.h" |
| #include "device/pico_board.h" |
| #include "hardware/adc.h" |
| #include "hardware/exception.h" |
| #include "modules/air_sensor/air_sensor.h" |
| #include "modules/buttons/manager.h" |
| #include "pico/stdlib.h" |
| #include "pw_channel/rp2_stdio_channel.h" |
| #include "pw_cpu_exception/entry.h" |
| #include "pw_digital_io_rp2040/digital_io.h" |
| #include "pw_i2c_rp2040/initiator.h" |
| #include "pw_multibuf/simple_allocator.h" |
| #include "pw_system/system.h" |
| #if defined(PICO_RP2040) && PICO_RP2040 |
| #include "system_RP2040.h" |
| #endif // defined(PICO_RP2040) && PICO_RP2040 |
| #if defined(PICO_RP2350) && PICO_RP2350 |
| #include "RP2350.h" |
| #include "system_RP2350.h" |
| #endif // defined(PICO_RP2350) && PICO_RP2350 |
| #include "system/pubsub.h" |
| #include "system/worker.h" |
| #include "targets/rp2/enviro_pins.h" |
| |
| using pw::digital_io::Rp2040DigitalIn; |
| |
| namespace sense::system { |
| namespace { |
| |
| pw::i2c::Initiator& I2cInitiator() { |
| static constexpr pw::i2c::Rp2040Initiator::Config kI2c0Config{ |
| .clock_frequency_hz = 400'000, |
| .sda_pin = board::kEnviroPinSda, |
| .scl_pin = board::kEnviroPinScl, |
| }; |
| |
| static pw::i2c::Initiator& i2c0_bus = []() -> pw::i2c::Initiator& { |
| static pw::i2c::Rp2040Initiator bus(kI2c0Config, i2c0); |
| bus.Enable(); |
| return bus; |
| }(); |
| |
| return i2c0_bus; |
| } |
| |
| Ltr559ProxAndLightSensorImpl& Ltr559() { |
| static Ltr559ProxAndLightSensorImpl sensor(I2cInitiator()); |
| return sensor; |
| } |
| |
| } // namespace |
| |
| namespace { |
| Rp2040DigitalIn io_sw_a({ |
| .pin = board::kEnviroPinSwA, |
| .polarity = pw::digital_io::Polarity::kActiveLow, |
| .enable_pull_up = true, |
| }); |
| |
| Rp2040DigitalIn io_sw_b({ |
| .pin = board::kEnviroPinSwB, |
| .polarity = pw::digital_io::Polarity::kActiveLow, |
| .enable_pull_up = true, |
| }); |
| |
| Rp2040DigitalIn io_sw_x({ |
| .pin = board::kEnviroPinSwX, |
| .polarity = pw::digital_io::Polarity::kActiveLow, |
| .enable_pull_up = true, |
| }); |
| |
| Rp2040DigitalIn io_sw_y({ |
| .pin = board::kEnviroPinSwY, |
| .polarity = pw::digital_io::Polarity::kActiveLow, |
| .enable_pull_up = true, |
| }); |
| } // namespace |
| |
| void Init() { |
| // PICO_SDK inits. |
| SystemInit(); |
| stdio_init_all(); |
| setup_default_uart(); |
| stdio_usb_init(); |
| adc_init(); |
| |
| // Install the CPU exception handler. |
| exception_set_exclusive_handler(HARDFAULT_EXCEPTION, pw_cpu_exception_Entry); |
| #if defined(PICO_RP2350) && PICO_RP2350 |
| // TODO: b/373723963 - The pico sdk exception_number enum doesn't currently |
| // have values for MemManage, BusFault or UsageFault, so cast the values for |
| // now until pico sdk has been updated. |
| // Enable the MemManage handler |
| SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; |
| exception_set_exclusive_handler(static_cast<exception_number>(4), |
| pw_cpu_exception_Entry); |
| // Enable the BusFault handler |
| SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk; |
| exception_set_exclusive_handler(static_cast<exception_number>(5), |
| pw_cpu_exception_Entry); |
| // Enable the UsageFault handler |
| SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk; |
| exception_set_exclusive_handler(static_cast<exception_number>(6), |
| pw_cpu_exception_Entry); |
| #endif // defined(PICO_RP2350) && PICO_RP2350 |
| |
| } |
| |
| void Start() { |
| static std::byte channel_buffer[2048]; |
| static pw::multibuf::SimpleAllocator multibuf_alloc(channel_buffer, |
| pw::System().allocator()); |
| pw::SystemStart(pw::channel::Rp2StdioChannelInit(multibuf_alloc)); |
| PW_UNREACHABLE; |
| } |
| |
| sense::AirSensor& AirSensor() { |
| static Bme688 air_sensor(I2cInitiator(), sense::system::GetWorker()); |
| return air_sensor; |
| } |
| |
| sense::Board& Board() { |
| static ::sense::PicoBoard board; |
| return board; |
| } |
| |
| sense::ButtonManager& ButtonManager() { |
| static ::sense::ButtonManager manager(io_sw_a, io_sw_b, io_sw_x, io_sw_y); |
| return manager; |
| } |
| |
| sense::AmbientLightSensor& AmbientLightSensor() { return Ltr559(); } |
| |
| sense::ProximitySensor& ProximitySensor() { return Ltr559(); } |
| |
| } // namespace sense::system |