1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #pragma once 16 17 #include <cinttypes> 18 #include <mutex> 19 #include <optional> 20 21 #include "fsl_spi.h" 22 #include "pw_spi/chip_selector.h" 23 #include "pw_spi/initiator.h" 24 #include "pw_status/status.h" 25 #include "pw_sync/binary_semaphore.h" 26 #include "pw_sync/lock_annotations.h" 27 #include "pw_sync/mutex.h" 28 29 namespace pw::spi { 30 31 // Mcuxpresso SDK implementation of the SPI Initiator 32 class McuxpressoInitiator : public Initiator { 33 public: 34 McuxpressoInitiator(SPI_Type* register_map, 35 uint32_t max_speed_hz, 36 uint32_t baud_rate_bps, 37 bool blocking = true) register_map_(register_map)38 : register_map_(register_map), 39 max_speed_hz_(max_speed_hz), 40 baud_rate_bps_(baud_rate_bps), 41 blocking_(blocking) {} 42 ~McuxpressoInitiator(); 43 44 Status SetChipSelect(uint32_t pin) PW_LOCKS_EXCLUDED(mutex_); 45 46 private: 47 // inclusive-language: disable 48 static void SpiCallback(SPI_Type* base, 49 spi_master_handle_t* driver_handle, 50 status_t status, 51 void* context); 52 53 Status DoConfigureLocked(const Config& config, 54 const std::lock_guard<sync::Mutex>& lock); 55 is_initialized()56 bool is_initialized() { return !!current_config_; } 57 58 // Implements pw::spi::Initiator 59 Status DoConfigure(const Config& config) PW_LOCKS_EXCLUDED(mutex_) override; 60 Status DoWriteRead(ConstByteSpan write_buffer, ByteSpan read_buffer) 61 PW_LOCKS_EXCLUDED(mutex_) override; 62 63 SPI_Type* register_map_; 64 spi_master_handle_t driver_handle_; 65 // inclusive-language: enable 66 sync::BinarySemaphore transfer_semaphore_; 67 sync::Mutex mutex_; 68 Status last_transfer_status_; 69 uint32_t max_speed_hz_; 70 uint32_t baud_rate_bps_; 71 bool blocking_; 72 std::optional<const Config> current_config_; 73 uint32_t pin_ = 0; 74 }; 75 76 // Mcuxpresso userspace implementation of SPI ChipSelector 77 // NOTE: This implementation deviates from the expected for this interface. 78 // It only specifies which chipselect pin should be activated and does not 79 // activate the pin itself. Activation of the pin is handled at a lower level by 80 // the Mcuxpresso vendor driver. 81 // This chipselector may only be used with a single McuxpressoInitiator 82 class McuxpressoChipSelector : public ChipSelector { 83 public: McuxpressoChipSelector(McuxpressoInitiator & initiator,uint32_t pin)84 McuxpressoChipSelector(McuxpressoInitiator& initiator, uint32_t pin) 85 : initiator_(initiator), pin_(pin) {} 86 87 // Implements pw::spi::ChipSelector 88 // Instead of directly activating the cs line, this informs the underlying 89 // driver to do so. SetActive(bool active)90 Status SetActive(bool active) override { 91 // TODO: https://pwbug.dev/348512572 - Respect 'active' 92 static_cast<void>(active); 93 return initiator_.SetChipSelect(pin_); 94 } 95 96 private: 97 McuxpressoInitiator& initiator_; 98 uint32_t pin_; 99 }; 100 101 } // namespace pw::spi 102