diff options
103 files changed, 2211 insertions, 1159 deletions
| @@ -58,6 +58,7 @@ cargo batch \ | |||
| 58 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits,log \ | 58 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits,log \ |
| 59 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits \ | 59 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,unstable-traits \ |
| 60 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \ | 60 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly \ |
| 61 | --- build --release --manifest-path embassy-rp/Cargo.toml --target thumbv6m-none-eabi --features nightly,intrinsics \ | ||
| 61 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits \ | 62 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f410tb,defmt,exti,time-driver-any,unstable-traits \ |
| 62 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits \ | 63 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f411ce,defmt,exti,time-driver-any,unstable-traits \ |
| 63 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits \ | 64 | --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32f429zi,log,exti,time-driver-any,unstable-traits \ |
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 4a2b112a9..8286601ec 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | #![feature(type_alias_impl_trait)] | 1 | #![feature(type_alias_impl_trait)] |
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![no_std] | 2 | #![no_std] |
| 4 | #![warn(missing_docs)] | 3 | #![warn(missing_docs)] |
| 5 | #![doc = include_str!("../../README.md")] | 4 | #![doc = include_str!("../../README.md")] |
| @@ -222,10 +221,7 @@ impl BootLoader { | |||
| 222 | page: &mut [u8], | 221 | page: &mut [u8], |
| 223 | ) -> Result<State, BootError> { | 222 | ) -> Result<State, BootError> { |
| 224 | // Ensure we have enough progress pages to store copy progress | 223 | // Ensure we have enough progress pages to store copy progress |
| 225 | assert_eq!(self.active.len() % page.len(), 0); | 224 | assert_partitions(self.active, self.dfu, self.state, page.len(), P::STATE::WRITE_SIZE); |
| 226 | assert_eq!(self.dfu.len() % page.len(), 0); | ||
| 227 | assert!(self.dfu.len() - self.active.len() >= page.len()); | ||
| 228 | assert!(self.active.len() / page.len() <= (self.state.len() - P::STATE::WRITE_SIZE) / P::STATE::WRITE_SIZE); | ||
| 229 | assert_eq!(magic.len(), P::STATE::WRITE_SIZE); | 225 | assert_eq!(magic.len(), P::STATE::WRITE_SIZE); |
| 230 | 226 | ||
| 231 | // Copy contents from partition N to active | 227 | // Copy contents from partition N to active |
| @@ -409,6 +405,13 @@ impl BootLoader { | |||
| 409 | } | 405 | } |
| 410 | } | 406 | } |
| 411 | 407 | ||
| 408 | fn assert_partitions(active: Partition, dfu: Partition, state: Partition, page_size: usize, write_size: usize) { | ||
| 409 | assert_eq!(active.len() % page_size, 0); | ||
| 410 | assert_eq!(dfu.len() % page_size, 0); | ||
| 411 | assert!(dfu.len() - active.len() >= page_size); | ||
| 412 | assert!(2 * (active.len() / page_size) <= (state.len() - write_size) / write_size); | ||
| 413 | } | ||
| 414 | |||
| 412 | /// Convenience provider that uses a single flash for all partitions. | 415 | /// Convenience provider that uses a single flash for all partitions. |
| 413 | pub struct SingleFlashConfig<'a, F> | 416 | pub struct SingleFlashConfig<'a, F> |
| 414 | where | 417 | where |
| @@ -447,24 +450,24 @@ where | |||
| 447 | } | 450 | } |
| 448 | 451 | ||
| 449 | /// A flash wrapper implementing the Flash and embedded_storage traits. | 452 | /// A flash wrapper implementing the Flash and embedded_storage traits. |
| 450 | pub struct BootFlash<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8 = 0xFF> | 453 | pub struct BootFlash<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8 = 0xFF> |
| 451 | where | 454 | where |
| 452 | F: NorFlash + ReadNorFlash, | 455 | F: NorFlash + ReadNorFlash, |
| 453 | { | 456 | { |
| 454 | flash: &'a mut F, | 457 | flash: F, |
| 455 | } | 458 | } |
| 456 | 459 | ||
| 457 | impl<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> BootFlash<'a, F, BLOCK_SIZE, ERASE_VALUE> | 460 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> BootFlash<F, BLOCK_SIZE, ERASE_VALUE> |
| 458 | where | 461 | where |
| 459 | F: NorFlash + ReadNorFlash, | 462 | F: NorFlash + ReadNorFlash, |
| 460 | { | 463 | { |
| 461 | /// Create a new instance of a bootable flash | 464 | /// Create a new instance of a bootable flash |
| 462 | pub fn new(flash: &'a mut F) -> Self { | 465 | pub fn new(flash: F) -> Self { |
| 463 | Self { flash } | 466 | Self { flash } |
| 464 | } | 467 | } |
| 465 | } | 468 | } |
| 466 | 469 | ||
| 467 | impl<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> Flash for BootFlash<'a, F, BLOCK_SIZE, ERASE_VALUE> | 470 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> Flash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> |
| 468 | where | 471 | where |
| 469 | F: NorFlash + ReadNorFlash, | 472 | F: NorFlash + ReadNorFlash, |
| 470 | { | 473 | { |
| @@ -472,14 +475,14 @@ where | |||
| 472 | const ERASE_VALUE: u8 = ERASE_VALUE; | 475 | const ERASE_VALUE: u8 = ERASE_VALUE; |
| 473 | } | 476 | } |
| 474 | 477 | ||
| 475 | impl<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ErrorType for BootFlash<'a, F, BLOCK_SIZE, ERASE_VALUE> | 478 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ErrorType for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> |
| 476 | where | 479 | where |
| 477 | F: ReadNorFlash + NorFlash, | 480 | F: ReadNorFlash + NorFlash, |
| 478 | { | 481 | { |
| 479 | type Error = F::Error; | 482 | type Error = F::Error; |
| 480 | } | 483 | } |
| 481 | 484 | ||
| 482 | impl<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> NorFlash for BootFlash<'a, F, BLOCK_SIZE, ERASE_VALUE> | 485 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> NorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> |
| 483 | where | 486 | where |
| 484 | F: ReadNorFlash + NorFlash, | 487 | F: ReadNorFlash + NorFlash, |
| 485 | { | 488 | { |
| @@ -487,26 +490,26 @@ where | |||
| 487 | const ERASE_SIZE: usize = F::ERASE_SIZE; | 490 | const ERASE_SIZE: usize = F::ERASE_SIZE; |
| 488 | 491 | ||
| 489 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | 492 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
| 490 | F::erase(self.flash, from, to) | 493 | F::erase(&mut self.flash, from, to) |
| 491 | } | 494 | } |
| 492 | 495 | ||
| 493 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | 496 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { |
| 494 | F::write(self.flash, offset, bytes) | 497 | F::write(&mut self.flash, offset, bytes) |
| 495 | } | 498 | } |
| 496 | } | 499 | } |
| 497 | 500 | ||
| 498 | impl<'a, F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<'a, F, BLOCK_SIZE, ERASE_VALUE> | 501 | impl<F, const BLOCK_SIZE: usize, const ERASE_VALUE: u8> ReadNorFlash for BootFlash<F, BLOCK_SIZE, ERASE_VALUE> |
| 499 | where | 502 | where |
| 500 | F: ReadNorFlash + NorFlash, | 503 | F: ReadNorFlash + NorFlash, |
| 501 | { | 504 | { |
| 502 | const READ_SIZE: usize = F::READ_SIZE; | 505 | const READ_SIZE: usize = F::READ_SIZE; |
| 503 | 506 | ||
| 504 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 507 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 505 | F::read(self.flash, offset, bytes) | 508 | F::read(&mut self.flash, offset, bytes) |
| 506 | } | 509 | } |
| 507 | 510 | ||
| 508 | fn capacity(&self) -> usize { | 511 | fn capacity(&self) -> usize { |
| 509 | F::capacity(self.flash) | 512 | F::capacity(&self.flash) |
| 510 | } | 513 | } |
| 511 | } | 514 | } |
| 512 | 515 | ||
| @@ -601,6 +604,21 @@ impl FirmwareUpdater { | |||
| 601 | self.dfu.len() | 604 | self.dfu.len() |
| 602 | } | 605 | } |
| 603 | 606 | ||
| 607 | /// Obtain the current state. | ||
| 608 | /// | ||
| 609 | /// This is useful to check if the bootloader has just done a swap, in order | ||
| 610 | /// to do verifications and self-tests of the new image before calling | ||
| 611 | /// `mark_booted`. | ||
| 612 | pub async fn get_state<F: AsyncNorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<State, F::Error> { | ||
| 613 | flash.read(self.state.from as u32, aligned).await?; | ||
| 614 | |||
| 615 | if !aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 616 | Ok(State::Swap) | ||
| 617 | } else { | ||
| 618 | Ok(State::Boot) | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 604 | /// Mark to trigger firmware swap on next boot. | 622 | /// Mark to trigger firmware swap on next boot. |
| 605 | /// | 623 | /// |
| 606 | /// # Safety | 624 | /// # Safety |
| @@ -657,12 +675,6 @@ impl FirmwareUpdater { | |||
| 657 | ) -> Result<(), F::Error> { | 675 | ) -> Result<(), F::Error> { |
| 658 | assert!(data.len() >= F::ERASE_SIZE); | 676 | assert!(data.len() >= F::ERASE_SIZE); |
| 659 | 677 | ||
| 660 | trace!( | ||
| 661 | "Writing firmware at offset 0x{:x} len {}", | ||
| 662 | self.dfu.from + offset, | ||
| 663 | data.len() | ||
| 664 | ); | ||
| 665 | |||
| 666 | flash | 678 | flash |
| 667 | .erase( | 679 | .erase( |
| 668 | (self.dfu.from + offset) as u32, | 680 | (self.dfu.from + offset) as u32, |
| @@ -676,7 +688,156 @@ impl FirmwareUpdater { | |||
| 676 | self.dfu.from + offset + data.len() | 688 | self.dfu.from + offset + data.len() |
| 677 | ); | 689 | ); |
| 678 | 690 | ||
| 679 | let mut write_offset = self.dfu.from + offset; | 691 | FirmwareWriter(self.dfu) |
| 692 | .write_block(offset, data, flash, block_size) | ||
| 693 | .await?; | ||
| 694 | |||
| 695 | Ok(()) | ||
| 696 | } | ||
| 697 | |||
| 698 | /// Prepare for an incoming DFU update by erasing the entire DFU area and | ||
| 699 | /// returning a `FirmwareWriter`. | ||
| 700 | /// | ||
| 701 | /// Using this instead of `write_firmware` allows for an optimized API in | ||
| 702 | /// exchange for added complexity. | ||
| 703 | pub async fn prepare_update<F: AsyncNorFlash>(&mut self, flash: &mut F) -> Result<FirmwareWriter, F::Error> { | ||
| 704 | flash.erase((self.dfu.from) as u32, (self.dfu.to) as u32).await?; | ||
| 705 | |||
| 706 | trace!("Erased from {} to {}", self.dfu.from, self.dfu.to); | ||
| 707 | |||
| 708 | Ok(FirmwareWriter(self.dfu)) | ||
| 709 | } | ||
| 710 | |||
| 711 | // | ||
| 712 | // Blocking API | ||
| 713 | // | ||
| 714 | |||
| 715 | /// Obtain the current state. | ||
| 716 | /// | ||
| 717 | /// This is useful to check if the bootloader has just done a swap, in order | ||
| 718 | /// to do verifications and self-tests of the new image before calling | ||
| 719 | /// `mark_booted`. | ||
| 720 | pub fn get_state_blocking<F: NorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<State, F::Error> { | ||
| 721 | flash.read(self.state.from as u32, aligned)?; | ||
| 722 | |||
| 723 | if !aligned.iter().any(|&b| b != SWAP_MAGIC) { | ||
| 724 | Ok(State::Swap) | ||
| 725 | } else { | ||
| 726 | Ok(State::Boot) | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | /// Mark to trigger firmware swap on next boot. | ||
| 731 | /// | ||
| 732 | /// # Safety | ||
| 733 | /// | ||
| 734 | /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 735 | pub fn mark_updated_blocking<F: NorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<(), F::Error> { | ||
| 736 | assert_eq!(aligned.len(), F::WRITE_SIZE); | ||
| 737 | self.set_magic_blocking(aligned, SWAP_MAGIC, flash) | ||
| 738 | } | ||
| 739 | |||
| 740 | /// Mark firmware boot successful and stop rollback on reset. | ||
| 741 | /// | ||
| 742 | /// # Safety | ||
| 743 | /// | ||
| 744 | /// The `aligned` buffer must have a size of F::WRITE_SIZE, and follow the alignment rules for the flash being written to. | ||
| 745 | pub fn mark_booted_blocking<F: NorFlash>(&mut self, flash: &mut F, aligned: &mut [u8]) -> Result<(), F::Error> { | ||
| 746 | assert_eq!(aligned.len(), F::WRITE_SIZE); | ||
| 747 | self.set_magic_blocking(aligned, BOOT_MAGIC, flash) | ||
| 748 | } | ||
| 749 | |||
| 750 | fn set_magic_blocking<F: NorFlash>( | ||
| 751 | &mut self, | ||
| 752 | aligned: &mut [u8], | ||
| 753 | magic: u8, | ||
| 754 | flash: &mut F, | ||
| 755 | ) -> Result<(), F::Error> { | ||
| 756 | flash.read(self.state.from as u32, aligned)?; | ||
| 757 | |||
| 758 | if aligned.iter().any(|&b| b != magic) { | ||
| 759 | aligned.fill(0); | ||
| 760 | |||
| 761 | flash.write(self.state.from as u32, aligned)?; | ||
| 762 | flash.erase(self.state.from as u32, self.state.to as u32)?; | ||
| 763 | |||
| 764 | aligned.fill(magic); | ||
| 765 | flash.write(self.state.from as u32, aligned)?; | ||
| 766 | } | ||
| 767 | Ok(()) | ||
| 768 | } | ||
| 769 | |||
| 770 | /// Write data to a flash page. | ||
| 771 | /// | ||
| 772 | /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. | ||
| 773 | /// | ||
| 774 | /// # Safety | ||
| 775 | /// | ||
| 776 | /// Failing to meet alignment and size requirements may result in a panic. | ||
| 777 | pub fn write_firmware_blocking<F: NorFlash>( | ||
| 778 | &mut self, | ||
| 779 | offset: usize, | ||
| 780 | data: &[u8], | ||
| 781 | flash: &mut F, | ||
| 782 | block_size: usize, | ||
| 783 | ) -> Result<(), F::Error> { | ||
| 784 | assert!(data.len() >= F::ERASE_SIZE); | ||
| 785 | |||
| 786 | flash.erase( | ||
| 787 | (self.dfu.from + offset) as u32, | ||
| 788 | (self.dfu.from + offset + data.len()) as u32, | ||
| 789 | )?; | ||
| 790 | |||
| 791 | trace!( | ||
| 792 | "Erased from {} to {}", | ||
| 793 | self.dfu.from + offset, | ||
| 794 | self.dfu.from + offset + data.len() | ||
| 795 | ); | ||
| 796 | |||
| 797 | FirmwareWriter(self.dfu).write_block_blocking(offset, data, flash, block_size)?; | ||
| 798 | |||
| 799 | Ok(()) | ||
| 800 | } | ||
| 801 | |||
| 802 | /// Prepare for an incoming DFU update by erasing the entire DFU area and | ||
| 803 | /// returning a `FirmwareWriter`. | ||
| 804 | /// | ||
| 805 | /// Using this instead of `write_firmware_blocking` allows for an optimized | ||
| 806 | /// API in exchange for added complexity. | ||
| 807 | pub fn prepare_update_blocking<F: NorFlash>(&mut self, flash: &mut F) -> Result<FirmwareWriter, F::Error> { | ||
| 808 | flash.erase((self.dfu.from) as u32, (self.dfu.to) as u32)?; | ||
| 809 | |||
| 810 | trace!("Erased from {} to {}", self.dfu.from, self.dfu.to); | ||
| 811 | |||
| 812 | Ok(FirmwareWriter(self.dfu)) | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 816 | /// FirmwareWriter allows writing blocks to an already erased flash. | ||
| 817 | pub struct FirmwareWriter(Partition); | ||
| 818 | |||
| 819 | impl FirmwareWriter { | ||
| 820 | /// Write data to a flash page. | ||
| 821 | /// | ||
| 822 | /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. | ||
| 823 | /// | ||
| 824 | /// # Safety | ||
| 825 | /// | ||
| 826 | /// Failing to meet alignment and size requirements may result in a panic. | ||
| 827 | pub async fn write_block<F: AsyncNorFlash>( | ||
| 828 | &mut self, | ||
| 829 | offset: usize, | ||
| 830 | data: &[u8], | ||
| 831 | flash: &mut F, | ||
| 832 | block_size: usize, | ||
| 833 | ) -> Result<(), F::Error> { | ||
| 834 | trace!( | ||
| 835 | "Writing firmware at offset 0x{:x} len {}", | ||
| 836 | self.0.from + offset, | ||
| 837 | data.len() | ||
| 838 | ); | ||
| 839 | |||
| 840 | let mut write_offset = self.0.from + offset; | ||
| 680 | for chunk in data.chunks(block_size) { | 841 | for chunk in data.chunks(block_size) { |
| 681 | trace!("Wrote chunk at {}: {:?}", write_offset, chunk); | 842 | trace!("Wrote chunk at {}: {:?}", write_offset, chunk); |
| 682 | flash.write(write_offset as u32, chunk).await?; | 843 | flash.write(write_offset as u32, chunk).await?; |
| @@ -699,6 +860,50 @@ impl FirmwareUpdater { | |||
| 699 | 860 | ||
| 700 | Ok(()) | 861 | Ok(()) |
| 701 | } | 862 | } |
| 863 | |||
| 864 | /// Write data to a flash page. | ||
| 865 | /// | ||
| 866 | /// The buffer must follow alignment requirements of the target flash and a multiple of page size big. | ||
| 867 | /// | ||
| 868 | /// # Safety | ||
| 869 | /// | ||
| 870 | /// Failing to meet alignment and size requirements may result in a panic. | ||
| 871 | pub fn write_block_blocking<F: NorFlash>( | ||
| 872 | &mut self, | ||
| 873 | offset: usize, | ||
| 874 | data: &[u8], | ||
| 875 | flash: &mut F, | ||
| 876 | block_size: usize, | ||
| 877 | ) -> Result<(), F::Error> { | ||
| 878 | trace!( | ||
| 879 | "Writing firmware at offset 0x{:x} len {}", | ||
| 880 | self.0.from + offset, | ||
| 881 | data.len() | ||
| 882 | ); | ||
| 883 | |||
| 884 | let mut write_offset = self.0.from + offset; | ||
| 885 | for chunk in data.chunks(block_size) { | ||
| 886 | trace!("Wrote chunk at {}: {:?}", write_offset, chunk); | ||
| 887 | flash.write(write_offset as u32, chunk)?; | ||
| 888 | write_offset += chunk.len(); | ||
| 889 | } | ||
| 890 | /* | ||
| 891 | trace!("Wrote data, reading back for verification"); | ||
| 892 | |||
| 893 | let mut buf: [u8; 4096] = [0; 4096]; | ||
| 894 | let mut data_offset = 0; | ||
| 895 | let mut read_offset = self.dfu.from + offset; | ||
| 896 | for chunk in buf.chunks_mut(block_size) { | ||
| 897 | flash.read(read_offset as u32, chunk).await?; | ||
| 898 | trace!("Read chunk at {}: {:?}", read_offset, chunk); | ||
| 899 | assert_eq!(&data[data_offset..data_offset + block_size], chunk); | ||
| 900 | read_offset += chunk.len(); | ||
| 901 | data_offset += chunk.len(); | ||
| 902 | } | ||
| 903 | */ | ||
| 904 | |||
| 905 | Ok(()) | ||
| 906 | } | ||
| 702 | } | 907 | } |
| 703 | 908 | ||
| 704 | #[cfg(test)] | 909 | #[cfg(test)] |
| @@ -919,6 +1124,15 @@ mod tests { | |||
| 919 | } | 1124 | } |
| 920 | } | 1125 | } |
| 921 | 1126 | ||
| 1127 | #[test] | ||
| 1128 | #[should_panic] | ||
| 1129 | fn test_range_asserts() { | ||
| 1130 | const ACTIVE: Partition = Partition::new(4096, 4194304); | ||
| 1131 | const DFU: Partition = Partition::new(4194304, 2 * 4194304); | ||
| 1132 | const STATE: Partition = Partition::new(0, 4096); | ||
| 1133 | assert_partitions(ACTIVE, DFU, STATE, 4096, 4); | ||
| 1134 | } | ||
| 1135 | |||
| 922 | struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize>([u8; SIZE]); | 1136 | struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize>([u8; SIZE]); |
| 923 | 1137 | ||
| 924 | impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> NorFlash | 1138 | impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> NorFlash |
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index 0c14781a2..385e089fe 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(type_alias_impl_trait)] | 2 | #![feature(type_alias_impl_trait)] |
| 4 | #![warn(missing_docs)] | 3 | #![warn(missing_docs)] |
| 5 | #![doc = include_str!("../../README.md")] | 4 | #![doc = include_str!("../../README.md")] |
diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs index 39f080517..edba39cca 100644 --- a/embassy-boot/stm32/src/lib.rs +++ b/embassy-boot/stm32/src/lib.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(type_alias_impl_trait)] | 2 | #![feature(type_alias_impl_trait)] |
| 4 | #![warn(missing_docs)] | 3 | #![warn(missing_docs)] |
| 5 | #![doc = include_str!("../../README.md")] | 4 | #![doc = include_str!("../../README.md")] |
diff --git a/embassy-embedded-hal/src/lib.rs b/embassy-embedded-hal/src/lib.rs index 0c6f2786a..a12a3a3a0 100644 --- a/embassy-embedded-hal/src/lib.rs +++ b/embassy-embedded-hal/src/lib.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![cfg_attr(not(feature = "std"), no_std)] | 1 | #![cfg_attr(not(feature = "std"), no_std)] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | #![warn(missing_docs)] | 3 | #![warn(missing_docs)] |
| 4 | 4 | ||
| 5 | //! Utilities to use `embedded-hal` traits with Embassy. | 5 | //! Utilities to use `embedded-hal` traits with Embassy. |
diff --git a/embassy-executor/src/spawner.rs b/embassy-executor/src/spawner.rs index 25a0d7dbb..400d973ff 100644 --- a/embassy-executor/src/spawner.rs +++ b/embassy-executor/src/spawner.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | use core::mem; | 3 | use core::mem; |
| 3 | use core::ptr::NonNull; | 4 | use core::ptr::NonNull; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use futures_util::future::poll_fn; | ||
| 7 | |||
| 8 | use super::raw; | 7 | use super::raw; |
| 9 | 8 | ||
| 10 | /// Token to spawn a newly-created task in an executor. | 9 | /// Token to spawn a newly-created task in an executor. |
diff --git a/embassy-lora/src/lib.rs b/embassy-lora/src/lib.rs index 2483dcb2e..90ba0d1d4 100644 --- a/embassy-lora/src/lib.rs +++ b/embassy-lora/src/lib.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![feature(type_alias_impl_trait)] | 2 | #![feature(type_alias_impl_trait)] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | //! embassy-lora is a collection of async radio drivers that integrate with the lorawan-device | 3 | //! embassy-lora is a collection of async radio drivers that integrate with the lorawan-device |
| 5 | //! crate's async LoRaWAN MAC implementation. | 4 | //! crate's async LoRaWAN MAC implementation. |
| 6 | 5 | ||
diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 4d11244b6..e28fa2c1a 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | //! A radio driver integration for the radio found on STM32WL family devices. | 1 | //! A radio driver integration for the radio found on STM32WL family devices. |
| 2 | use core::future::Future; | 2 | use core::future::{poll_fn, Future}; |
| 3 | use core::task::Poll; | 3 | use core::task::Poll; |
| 4 | 4 | ||
| 5 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 5 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; |
| @@ -11,7 +11,6 @@ use embassy_stm32::subghz::{ | |||
| 11 | Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, | 11 | Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, |
| 12 | }; | 12 | }; |
| 13 | use embassy_sync::waitqueue::AtomicWaker; | 13 | use embassy_sync::waitqueue::AtomicWaker; |
| 14 | use futures::future::poll_fn; | ||
| 15 | use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}; | 14 | use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}; |
| 16 | use lorawan_device::async_device::Timings; | 15 | use lorawan_device::async_device::Timings; |
| 17 | 16 | ||
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 8eebc798e..4d30550d3 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![cfg_attr(not(feature = "std"), no_std)] | 1 | #![cfg_attr(not(feature = "std"), no_std)] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | 3 | ||
| 4 | // This mod MUST go first, so that the others see its macros. | 4 | // This mod MUST go first, so that the others see its macros. |
| 5 | pub(crate) mod fmt; | 5 | pub(crate) mod fmt; |
diff --git a/embassy-net/src/stack.rs b/embassy-net/src/stack.rs index 8d2dd4bca..3a7610758 100644 --- a/embassy-net/src/stack.rs +++ b/embassy-net/src/stack.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use core::future::Future; | 2 | use core::future::{poll_fn, Future}; |
| 3 | use core::task::{Context, Poll}; | 3 | use core::task::{Context, Poll}; |
| 4 | 4 | ||
| 5 | use embassy_sync::waitqueue::WakerRegistration; | 5 | use embassy_sync::waitqueue::WakerRegistration; |
| 6 | use embassy_time::{Instant, Timer}; | 6 | use embassy_time::{Instant, Timer}; |
| 7 | use futures::future::poll_fn; | ||
| 8 | use futures::pin_mut; | 7 | use futures::pin_mut; |
| 9 | use heapless::Vec; | 8 | use heapless::Vec; |
| 10 | #[cfg(feature = "dhcpv4")] | 9 | #[cfg(feature = "dhcpv4")] |
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 0fa873602..f8fff3e2d 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use core::future::poll_fn; | ||
| 2 | use core::mem; | 3 | use core::mem; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use futures::future::poll_fn; | ||
| 6 | use smoltcp::iface::{Interface, SocketHandle}; | 6 | use smoltcp::iface::{Interface, SocketHandle}; |
| 7 | use smoltcp::socket::tcp; | 7 | use smoltcp::socket::tcp; |
| 8 | use smoltcp::time::Duration; | 8 | use smoltcp::time::Duration; |
| @@ -103,7 +103,7 @@ impl<'a> TcpSocket<'a> { | |||
| 103 | Err(tcp::ConnectError::Unaddressable) => return Err(ConnectError::NoRoute), | 103 | Err(tcp::ConnectError::Unaddressable) => return Err(ConnectError::NoRoute), |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | futures::future::poll_fn(|cx| unsafe { | 106 | poll_fn(|cx| unsafe { |
| 107 | self.io.with_mut(|s, _| match s.state() { | 107 | self.io.with_mut(|s, _| match s.state() { |
| 108 | tcp::State::Closed | tcp::State::TimeWait => Poll::Ready(Err(ConnectError::ConnectionReset)), | 108 | tcp::State::Closed | tcp::State::TimeWait => Poll::Ready(Err(ConnectError::ConnectionReset)), |
| 109 | tcp::State::Listen => unreachable!(), | 109 | tcp::State::Listen => unreachable!(), |
| @@ -128,7 +128,7 @@ impl<'a> TcpSocket<'a> { | |||
| 128 | Err(tcp::ListenError::Unaddressable) => return Err(AcceptError::InvalidPort), | 128 | Err(tcp::ListenError::Unaddressable) => return Err(AcceptError::InvalidPort), |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | futures::future::poll_fn(|cx| unsafe { | 131 | poll_fn(|cx| unsafe { |
| 132 | self.io.with_mut(|s, _| match s.state() { | 132 | self.io.with_mut(|s, _| match s.state() { |
| 133 | tcp::State::Listen | tcp::State::SynSent | tcp::State::SynReceived => { | 133 | tcp::State::Listen | tcp::State::SynSent | tcp::State::SynReceived => { |
| 134 | s.register_send_waker(cx.waker()); | 134 | s.register_send_waker(cx.waker()); |
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 78b09a492..f2e33493c 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use core::future::poll_fn; | ||
| 2 | use core::mem; | 3 | use core::mem; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use futures::future::poll_fn; | ||
| 6 | use smoltcp::iface::{Interface, SocketHandle}; | 6 | use smoltcp::iface::{Interface, SocketHandle}; |
| 7 | use smoltcp::socket::udp::{self, PacketMetadata}; | 7 | use smoltcp::socket::udp::{self, PacketMetadata}; |
| 8 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; | 8 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; |
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index c3cba2470..6e85a159f 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | use core::cell::RefCell; | 16 | use core::cell::RefCell; |
| 17 | use core::cmp::min; | 17 | use core::cmp::min; |
| 18 | use core::future::Future; | 18 | use core::future::{poll_fn, Future}; |
| 19 | use core::sync::atomic::{compiler_fence, Ordering}; | 19 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 20 | use core::task::Poll; | 20 | use core::task::Poll; |
| 21 | 21 | ||
| @@ -23,11 +23,10 @@ use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorag | |||
| 23 | use embassy_hal_common::ring_buffer::RingBuffer; | 23 | use embassy_hal_common::ring_buffer::RingBuffer; |
| 24 | use embassy_hal_common::{into_ref, PeripheralRef}; | 24 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 25 | use embassy_sync::waitqueue::WakerRegistration; | 25 | use embassy_sync::waitqueue::WakerRegistration; |
| 26 | use futures::future::poll_fn; | ||
| 27 | // Re-export SVD variants to allow user to directly set values | 26 | // Re-export SVD variants to allow user to directly set values |
| 28 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 27 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| 29 | 28 | ||
| 30 | use crate::gpio::Pin as GpioPin; | 29 | use crate::gpio::{self, Pin as GpioPin}; |
| 31 | use crate::interrupt::InterruptExt; | 30 | use crate::interrupt::InterruptExt; |
| 32 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 31 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 33 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; | 32 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; |
| @@ -429,21 +428,23 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> { | |||
| 429 | fn drop(&mut self) { | 428 | fn drop(&mut self) { |
| 430 | let r = U::regs(); | 429 | let r = U::regs(); |
| 431 | 430 | ||
| 432 | // TODO this probably deadlocks. do like Uarte instead. | ||
| 433 | |||
| 434 | self.timer.stop(); | 431 | self.timer.stop(); |
| 435 | if let RxState::Receiving = self.rx_state { | 432 | |
| 436 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 433 | r.inten.reset(); |
| 437 | } | 434 | r.events_rxto.reset(); |
| 438 | if let TxState::Transmitting(_) = self.tx_state { | 435 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 439 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); | 436 | r.events_txstopped.reset(); |
| 440 | } | 437 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); |
| 441 | if let RxState::Receiving = self.rx_state { | 438 | |
| 442 | low_power_wait_until(|| r.events_endrx.read().bits() == 1); | 439 | while r.events_txstopped.read().bits() == 0 {} |
| 443 | } | 440 | while r.events_rxto.read().bits() == 0 {} |
| 444 | if let TxState::Transmitting(_) = self.tx_state { | 441 | |
| 445 | low_power_wait_until(|| r.events_endtx.read().bits() == 1); | 442 | r.enable.write(|w| w.enable().disabled()); |
| 446 | } | 443 | |
| 444 | gpio::deconfigure_pin(r.psel.rxd.read().bits()); | ||
| 445 | gpio::deconfigure_pin(r.psel.txd.read().bits()); | ||
| 446 | gpio::deconfigure_pin(r.psel.rts.read().bits()); | ||
| 447 | gpio::deconfigure_pin(r.psel.cts.read().bits()); | ||
| 447 | } | 448 | } |
| 448 | } | 449 | } |
| 449 | 450 | ||
| @@ -549,13 +550,3 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a, | |||
| 549 | trace!("irq: end"); | 550 | trace!("irq: end"); |
| 550 | } | 551 | } |
| 551 | } | 552 | } |
| 552 | |||
| 553 | /// Low power blocking wait loop using WFE/SEV. | ||
| 554 | fn low_power_wait_until(mut condition: impl FnMut() -> bool) { | ||
| 555 | while !condition() { | ||
| 556 | // WFE might "eat" an event that would have otherwise woken the executor. | ||
| 557 | cortex_m::asm::wfe(); | ||
| 558 | } | ||
| 559 | // Retrigger an event to be transparent to the executor. | ||
| 560 | cortex_m::asm::sev(); | ||
| 561 | } | ||
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index d99f592b0..b418be9d5 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::convert::Infallible; | 1 | use core::convert::Infallible; |
| 2 | use core::future::Future; | 2 | use core::future::{poll_fn, Future}; |
| 3 | use core::task::{Context, Poll}; | 3 | use core::task::{Context, Poll}; |
| 4 | 4 | ||
| 5 | use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef}; | 5 | use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef}; |
| 6 | use embassy_sync::waitqueue::AtomicWaker; | 6 | use embassy_sync::waitqueue::AtomicWaker; |
| 7 | use futures::future::poll_fn; | ||
| 8 | 7 | ||
| 9 | use crate::gpio::sealed::Pin as _; | 8 | use crate::gpio::sealed::Pin as _; |
| 10 | use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; | 9 | use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin}; |
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index f3b3ca0ca..d7bd21702 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -43,7 +43,7 @@ | |||
| 43 | //! mutable slices always reside in RAM. | 43 | //! mutable slices always reside in RAM. |
| 44 | 44 | ||
| 45 | #![no_std] | 45 | #![no_std] |
| 46 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 46 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 47 | 47 | ||
| 48 | #[cfg(not(any( | 48 | #[cfg(not(any( |
| 49 | feature = "nrf51", | 49 | feature = "nrf51", |
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs index 762e09715..253c85c32 100644 --- a/embassy-nrf/src/qdec.rs +++ b/embassy-nrf/src/qdec.rs | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | //! Quadrature decoder interface | 1 | //! Quadrature decoder interface |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use embassy_hal_common::{into_ref, PeripheralRef}; | 6 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 6 | use embassy_sync::waitqueue::AtomicWaker; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 7 | use futures::future::poll_fn; | ||
| 8 | 8 | ||
| 9 | use crate::gpio::sealed::Pin as _; | 9 | use crate::gpio::sealed::Pin as _; |
| 10 | use crate::gpio::{AnyPin, Pin as GpioPin}; | 10 | use crate::gpio::{AnyPin, Pin as GpioPin}; |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index c97cb1656..ea0a17031 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::ptr; | 4 | use core::ptr; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_hal_common::drop::DropBomb; | 7 | use embassy_hal_common::drop::DropBomb; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | use futures::future::poll_fn; | ||
| 9 | 9 | ||
| 10 | use crate::gpio::{self, Pin as GpioPin}; | 10 | use crate::gpio::{self, Pin as GpioPin}; |
| 11 | use crate::interrupt::{Interrupt, InterruptExt}; | 11 | use crate::interrupt::{Interrupt, InterruptExt}; |
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 42da51d0f..e0caeaaee 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 1 | use core::ptr; | 2 | use core::ptr; |
| 2 | use core::sync::atomic::{AtomicPtr, Ordering}; | 3 | use core::sync::atomic::{AtomicPtr, Ordering}; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| @@ -5,7 +6,6 @@ use core::task::Poll; | |||
| 5 | use embassy_hal_common::drop::OnDrop; | 6 | use embassy_hal_common::drop::OnDrop; |
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | 7 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | use futures::future::poll_fn; | ||
| 9 | 9 | ||
| 10 | use crate::interrupt::InterruptExt; | 10 | use crate::interrupt::InterruptExt; |
| 11 | use crate::peripherals::RNG; | 11 | use crate::peripherals::RNG; |
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 9bc89eb38..d1c82423e 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_hal_common::drop::OnDrop; | 7 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use futures::future::poll_fn; | ||
| 10 | use pac::{saadc, SAADC}; | 10 | use pac::{saadc, SAADC}; |
| 11 | use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; | 11 | use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; |
| 12 | // We treat the positive and negative channels with the same enum values to keep our type tidy and given they are the same | 12 | // We treat the positive and negative channels with the same enum values to keep our type tidy and given they are the same |
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 2955182e4..51cd73a47 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_embedded_hal::SetConfig; | 7 | use embassy_embedded_hal::SetConfig; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 9 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 9 | use futures::future::poll_fn; | ||
| 10 | pub use pac::spim0::frequency::FREQUENCY_A as Frequency; | 10 | pub use pac::spim0::frequency::FREQUENCY_A as Frequency; |
| 11 | 11 | ||
| 12 | use crate::chip::FORCE_COPY_BUFFER_SIZE; | 12 | use crate::chip::FORCE_COPY_BUFFER_SIZE; |
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs index d520fd686..7a7f61b51 100644 --- a/embassy-nrf/src/temp.rs +++ b/embassy-nrf/src/temp.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | //! Temperature sensor interface. | 1 | //! Temperature sensor interface. |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use embassy_hal_common::drop::OnDrop; | 6 | use embassy_hal_common::drop::OnDrop; |
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | 7 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | use fixed::types::I30F2; | 9 | use fixed::types::I30F2; |
| 9 | use futures::future::poll_fn; | ||
| 10 | 10 | ||
| 11 | use crate::interrupt::InterruptExt; | 11 | use crate::interrupt::InterruptExt; |
| 12 | use crate::peripherals::TEMP; | 12 | use crate::peripherals::TEMP; |
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 3de5a8962..bc8710640 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_hal_common::drop::OnDrop; | 7 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use futures::future::poll_fn; | ||
| 10 | 10 | ||
| 11 | use crate::interrupt::{Interrupt, InterruptExt}; | 11 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 12 | use crate::ppi::{Event, Task}; | 12 | use crate::ppi::{Event, Task}; |
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index 3d4af753a..7c6ca1d30 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | //! | 6 | //! |
| 7 | //! - nRF52832: Section 33 | 7 | //! - nRF52832: Section 33 |
| 8 | //! - nRF52840: Section 6.31 | 8 | //! - nRF52840: Section 6.31 |
| 9 | use core::future::Future; | 9 | use core::future::{poll_fn, Future}; |
| 10 | use core::sync::atomic::compiler_fence; | 10 | use core::sync::atomic::compiler_fence; |
| 11 | use core::sync::atomic::Ordering::SeqCst; | 11 | use core::sync::atomic::Ordering::SeqCst; |
| 12 | use core::task::Poll; | 12 | use core::task::Poll; |
| @@ -16,7 +16,6 @@ use embassy_hal_common::{into_ref, PeripheralRef}; | |||
| 16 | use embassy_sync::waitqueue::AtomicWaker; | 16 | use embassy_sync::waitqueue::AtomicWaker; |
| 17 | #[cfg(feature = "time")] | 17 | #[cfg(feature = "time")] |
| 18 | use embassy_time::{Duration, Instant}; | 18 | use embassy_time::{Duration, Instant}; |
| 19 | use futures::future::poll_fn; | ||
| 20 | 19 | ||
| 21 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; | 20 | use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; |
| 22 | use crate::gpio::Pin as GpioPin; | 21 | use crate::gpio::Pin as GpioPin; |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index c250e24ca..5f9c4f17d 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -13,12 +13,12 @@ | |||
| 13 | //! memory may be used given that buffers are passed in directly to its read and write | 13 | //! memory may be used given that buffers are passed in directly to its read and write |
| 14 | //! methods. | 14 | //! methods. |
| 15 | 15 | ||
| 16 | use core::future::poll_fn; | ||
| 16 | use core::sync::atomic::{compiler_fence, Ordering}; | 17 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 17 | use core::task::Poll; | 18 | use core::task::Poll; |
| 18 | 19 | ||
| 19 | use embassy_hal_common::drop::OnDrop; | 20 | use embassy_hal_common::drop::OnDrop; |
| 20 | use embassy_hal_common::{into_ref, PeripheralRef}; | 21 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 21 | use futures::future::poll_fn; | ||
| 22 | use pac::uarte0::RegisterBlock; | 22 | use pac::uarte0::RegisterBlock; |
| 23 | // Re-export SVD variants to allow user to directly set values. | 23 | // Re-export SVD variants to allow user to directly set values. |
| 24 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 24 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs index 688326e9c..20510eb49 100644 --- a/embassy-nrf/src/usb.rs +++ b/embassy-nrf/src/usb.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::{poll_fn, Future}; | ||
| 3 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 4 | use core::mem::MaybeUninit; | 5 | use core::mem::MaybeUninit; |
| 5 | use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; | 6 | use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU32, Ordering}; |
| @@ -9,10 +10,9 @@ use cortex_m::peripheral::NVIC; | |||
| 9 | use embassy_hal_common::{into_ref, PeripheralRef}; | 10 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 11 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | pub use embassy_usb; | 12 | pub use embassy_usb; |
| 12 | use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; | 13 | use embassy_usb::driver::{ |
| 13 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; | 14 | self, Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, |
| 14 | use futures::future::poll_fn; | 15 | }; |
| 15 | use futures::Future; | ||
| 16 | use pac::usbd::RegisterBlock; | 16 | use pac::usbd::RegisterBlock; |
| 17 | 17 | ||
| 18 | use crate::interrupt::{Interrupt, InterruptExt}; | 18 | use crate::interrupt::{Interrupt, InterruptExt}; |
| @@ -244,7 +244,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P> | |||
| 244 | interval: u8, | 244 | interval: u8, |
| 245 | ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { | 245 | ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { |
| 246 | let index = self.alloc_in.allocate(ep_type)?; | 246 | let index = self.alloc_in.allocate(ep_type)?; |
| 247 | let ep_addr = EndpointAddress::from_parts(index, UsbDirection::In); | 247 | let ep_addr = EndpointAddress::from_parts(index, Direction::In); |
| 248 | Ok(Endpoint::new(EndpointInfo { | 248 | Ok(Endpoint::new(EndpointInfo { |
| 249 | addr: ep_addr, | 249 | addr: ep_addr, |
| 250 | ep_type, | 250 | ep_type, |
| @@ -260,7 +260,7 @@ impl<'d, T: Instance, P: UsbSupply + 'd> driver::Driver<'d> for Driver<'d, T, P> | |||
| 260 | interval: u8, | 260 | interval: u8, |
| 261 | ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { | 261 | ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { |
| 262 | let index = self.alloc_out.allocate(ep_type)?; | 262 | let index = self.alloc_out.allocate(ep_type)?; |
| 263 | let ep_addr = EndpointAddress::from_parts(index, UsbDirection::Out); | 263 | let ep_addr = EndpointAddress::from_parts(index, Direction::Out); |
| 264 | Ok(Endpoint::new(EndpointInfo { | 264 | Ok(Endpoint::new(EndpointInfo { |
| 265 | addr: ep_addr, | 265 | addr: ep_addr, |
| 266 | ep_type, | 266 | ep_type, |
| @@ -429,8 +429,8 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||
| 429 | let regs = T::regs(); | 429 | let regs = T::regs(); |
| 430 | let i = ep_addr.index(); | 430 | let i = ep_addr.index(); |
| 431 | match ep_addr.direction() { | 431 | match ep_addr.direction() { |
| 432 | UsbDirection::Out => regs.halted.epout[i].read().getstatus().is_halted(), | 432 | Direction::Out => regs.halted.epout[i].read().getstatus().is_halted(), |
| 433 | UsbDirection::In => regs.halted.epin[i].read().getstatus().is_halted(), | 433 | Direction::In => regs.halted.epin[i].read().getstatus().is_halted(), |
| 434 | } | 434 | } |
| 435 | } | 435 | } |
| 436 | 436 | ||
| @@ -443,7 +443,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||
| 443 | debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); | 443 | debug!("endpoint_set_enabled {:?} {}", ep_addr, enabled); |
| 444 | 444 | ||
| 445 | match ep_addr.direction() { | 445 | match ep_addr.direction() { |
| 446 | UsbDirection::In => { | 446 | Direction::In => { |
| 447 | let mut was_enabled = false; | 447 | let mut was_enabled = false; |
| 448 | regs.epinen.modify(|r, w| { | 448 | regs.epinen.modify(|r, w| { |
| 449 | let mut bits = r.bits(); | 449 | let mut bits = r.bits(); |
| @@ -467,7 +467,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> { | |||
| 467 | 467 | ||
| 468 | In::waker(i).wake(); | 468 | In::waker(i).wake(); |
| 469 | } | 469 | } |
| 470 | UsbDirection::Out => { | 470 | Direction::Out => { |
| 471 | regs.epouten.modify(|r, w| { | 471 | regs.epouten.modify(|r, w| { |
| 472 | let mut bits = r.bits(); | 472 | let mut bits = r.bits(); |
| 473 | if enabled { | 473 | if enabled { |
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 3debca710..d0cf8025c 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml | |||
| @@ -6,7 +6,7 @@ edition = "2021" | |||
| 6 | [package.metadata.embassy_docs] | 6 | [package.metadata.embassy_docs] |
| 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-rp-v$VERSION/embassy-rp/src/" | 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-rp-v$VERSION/embassy-rp/src/" |
| 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-rp/src/" | 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-rp/src/" |
| 9 | features = ["nightly", "defmt", "unstable-pac", "unstable-traits"] | 9 | features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver"] |
| 10 | flavors = [ | 10 | flavors = [ |
| 11 | { name = "rp2040", target = "thumbv6m-none-eabi" }, | 11 | { name = "rp2040", target = "thumbv6m-none-eabi" }, |
| 12 | ] | 12 | ] |
| @@ -20,6 +20,12 @@ defmt = ["dep:defmt", "embassy-usb?/defmt"] | |||
| 20 | # There are no plans to make this stable. | 20 | # There are no plans to make this stable. |
| 21 | unstable-pac = [] | 21 | unstable-pac = [] |
| 22 | 22 | ||
| 23 | time-driver = [] | ||
| 24 | |||
| 25 | rom-func-cache = [] | ||
| 26 | intrinsics = [] | ||
| 27 | rom-v2-intrinsics = [] | ||
| 28 | |||
| 23 | # Enable nightly-only features | 29 | # Enable nightly-only features |
| 24 | nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb", "dep:embedded-io"] | 30 | nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb", "dep:embedded-io"] |
| 25 | 31 | ||
| @@ -31,6 +37,7 @@ unstable-traits = ["embedded-hal-1"] | |||
| 31 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | 37 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } |
| 32 | embassy-executor = { version = "0.1.0", path = "../embassy-executor" } | 38 | embassy-executor = { version = "0.1.0", path = "../embassy-executor" } |
| 33 | embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } | 39 | embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } |
| 40 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | ||
| 34 | embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]} | 41 | embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]} |
| 35 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } | 42 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } |
| 36 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 43 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
| @@ -44,6 +51,7 @@ cortex-m-rt = ">=0.6.15,<0.8" | |||
| 44 | cortex-m = "0.7.6" | 51 | cortex-m = "0.7.6" |
| 45 | critical-section = "1.1" | 52 | critical-section = "1.1" |
| 46 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 53 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 54 | chrono = { version = "0.4", default-features = false, optional = true } | ||
| 47 | embedded-io = { version = "0.3.0", features = ["async"], optional = true } | 55 | embedded-io = { version = "0.3.0", features = ["async"], optional = true } |
| 48 | 56 | ||
| 49 | rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } | 57 | rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } |
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 3ad1e5d82..1c446f389 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs | |||
| @@ -122,7 +122,7 @@ pub(crate) fn clk_peri_freq() -> u32 { | |||
| 122 | 125_000_000 | 122 | 125_000_000 |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | pub(crate) fn _clk_rtc_freq() -> u32 { | 125 | pub(crate) fn clk_rtc_freq() -> u32 { |
| 126 | 46875 | 126 | 46875 |
| 127 | } | 127 | } |
| 128 | 128 | ||
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index acf338225..410c48666 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::future::Future; | ||
| 1 | use core::pin::Pin; | 2 | use core::pin::Pin; |
| 2 | use core::sync::atomic::{compiler_fence, Ordering}; | 3 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 3 | use core::task::{Context, Poll}; | 4 | use core::task::{Context, Poll}; |
| @@ -5,7 +6,6 @@ use core::task::{Context, Poll}; | |||
| 5 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; | 6 | use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; |
| 6 | use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; | 7 | use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | use futures::Future; | ||
| 9 | use pac::dma::vals::DataSize; | 9 | use pac::dma::vals::DataSize; |
| 10 | 10 | ||
| 11 | use crate::pac::dma::vals; | 11 | use crate::pac::dma::vals; |
| @@ -75,6 +75,25 @@ pub unsafe fn write<'a, C: Channel, W: Word>( | |||
| 75 | ) | 75 | ) |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | pub unsafe fn write_repeated<'a, C: Channel, W: Word>( | ||
| 79 | ch: impl Peripheral<P = C> + 'a, | ||
| 80 | to: *mut W, | ||
| 81 | len: usize, | ||
| 82 | dreq: u8, | ||
| 83 | ) -> Transfer<'a, C> { | ||
| 84 | let dummy: u32 = 0; | ||
| 85 | copy_inner( | ||
| 86 | ch, | ||
| 87 | &dummy as *const u32, | ||
| 88 | to as *mut u32, | ||
| 89 | len, | ||
| 90 | W::size(), | ||
| 91 | false, | ||
| 92 | false, | ||
| 93 | dreq, | ||
| 94 | ) | ||
| 95 | } | ||
| 96 | |||
| 78 | pub unsafe fn copy<'a, C: Channel, W: Word>( | 97 | pub unsafe fn copy<'a, C: Channel, W: Word>( |
| 79 | ch: impl Peripheral<P = C> + 'a, | 98 | ch: impl Peripheral<P = C> + 'a, |
| 80 | from: &[W], | 99 | from: &[W], |
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index a0328302a..9b9a08110 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs | |||
| @@ -159,7 +159,7 @@ unsafe fn IO_IRQ_BANK0() { | |||
| 159 | w.set_edge_low(pin_group, false); | 159 | w.set_edge_low(pin_group, false); |
| 160 | } | 160 | } |
| 161 | InterruptTrigger::LevelHigh => { | 161 | InterruptTrigger::LevelHigh => { |
| 162 | debug!("IO_IRQ_BANK0 pin {} LevelHigh triggered\n", pin); | 162 | debug!("IO_IRQ_BANK0 pin {} LevelHigh triggered", pin); |
| 163 | w.set_level_high(pin_group, false); | 163 | w.set_level_high(pin_group, false); |
| 164 | } | 164 | } |
| 165 | InterruptTrigger::LevelLow => { | 165 | InterruptTrigger::LevelLow => { |
| @@ -198,7 +198,7 @@ impl<'d, T: Pin> InputFuture<'d, T> { | |||
| 198 | critical_section::with(|_| { | 198 | critical_section::with(|_| { |
| 199 | pin.int_proc().inte((pin.pin() / 8) as usize).modify(|w| match level { | 199 | pin.int_proc().inte((pin.pin() / 8) as usize).modify(|w| match level { |
| 200 | InterruptTrigger::LevelHigh => { | 200 | InterruptTrigger::LevelHigh => { |
| 201 | debug!("InputFuture::new enable LevelHigh for pin {} \n", pin.pin()); | 201 | debug!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); |
| 202 | w.set_level_high(pin_group, true); | 202 | w.set_level_high(pin_group, true); |
| 203 | } | 203 | } |
| 204 | InterruptTrigger::LevelLow => { | 204 | InterruptTrigger::LevelLow => { |
| @@ -245,45 +245,45 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> { | |||
| 245 | // the pin and if it has been disabled that means it was done by the | 245 | // the pin and if it has been disabled that means it was done by the |
| 246 | // interrupt service routine, so we then know that the event/trigger | 246 | // interrupt service routine, so we then know that the event/trigger |
| 247 | // happened and Poll::Ready will be returned. | 247 | // happened and Poll::Ready will be returned. |
| 248 | debug!("{:?} for pin {}\n", self.level, self.pin.pin()); | 248 | debug!("{:?} for pin {}", self.level, self.pin.pin()); |
| 249 | match self.level { | 249 | match self.level { |
| 250 | InterruptTrigger::AnyEdge => { | 250 | InterruptTrigger::AnyEdge => { |
| 251 | if !inte.edge_high(pin_group) && !inte.edge_low(pin_group) { | 251 | if !inte.edge_high(pin_group) && !inte.edge_low(pin_group) { |
| 252 | #[rustfmt::skip] | 252 | #[rustfmt::skip] |
| 253 | debug!("{:?} for pin {} was cleared, return Poll::Ready\n", self.level, self.pin.pin()); | 253 | debug!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); |
| 254 | return Poll::Ready(()); | 254 | return Poll::Ready(()); |
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | InterruptTrigger::LevelHigh => { | 257 | InterruptTrigger::LevelHigh => { |
| 258 | if !inte.level_high(pin_group) { | 258 | if !inte.level_high(pin_group) { |
| 259 | #[rustfmt::skip] | 259 | #[rustfmt::skip] |
| 260 | debug!("{:?} for pin {} was cleared, return Poll::Ready\n", self.level, self.pin.pin()); | 260 | debug!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); |
| 261 | return Poll::Ready(()); | 261 | return Poll::Ready(()); |
| 262 | } | 262 | } |
| 263 | } | 263 | } |
| 264 | InterruptTrigger::LevelLow => { | 264 | InterruptTrigger::LevelLow => { |
| 265 | if !inte.level_low(pin_group) { | 265 | if !inte.level_low(pin_group) { |
| 266 | #[rustfmt::skip] | 266 | #[rustfmt::skip] |
| 267 | debug!("{:?} for pin {} was cleared, return Poll::Ready\n", self.level, self.pin.pin()); | 267 | debug!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); |
| 268 | return Poll::Ready(()); | 268 | return Poll::Ready(()); |
| 269 | } | 269 | } |
| 270 | } | 270 | } |
| 271 | InterruptTrigger::EdgeHigh => { | 271 | InterruptTrigger::EdgeHigh => { |
| 272 | if !inte.edge_high(pin_group) { | 272 | if !inte.edge_high(pin_group) { |
| 273 | #[rustfmt::skip] | 273 | #[rustfmt::skip] |
| 274 | debug!("{:?} for pin {} was cleared, return Poll::Ready\n", self.level, self.pin.pin()); | 274 | debug!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); |
| 275 | return Poll::Ready(()); | 275 | return Poll::Ready(()); |
| 276 | } | 276 | } |
| 277 | } | 277 | } |
| 278 | InterruptTrigger::EdgeLow => { | 278 | InterruptTrigger::EdgeLow => { |
| 279 | if !inte.edge_low(pin_group) { | 279 | if !inte.edge_low(pin_group) { |
| 280 | #[rustfmt::skip] | 280 | #[rustfmt::skip] |
| 281 | debug!("{:?} for pin {} was cleared, return Poll::Ready\n", self.level, self.pin.pin()); | 281 | debug!("{:?} for pin {} was cleared, return Poll::Ready", self.level, self.pin.pin()); |
| 282 | return Poll::Ready(()); | 282 | return Poll::Ready(()); |
| 283 | } | 283 | } |
| 284 | } | 284 | } |
| 285 | } | 285 | } |
| 286 | debug!("InputFuture::poll return Poll::Pending\n"); | 286 | debug!("InputFuture::poll return Poll::Pending"); |
| 287 | Poll::Pending | 287 | Poll::Pending |
| 288 | } | 288 | } |
| 289 | } | 289 | } |
diff --git a/embassy-rp/src/intrinsics.rs b/embassy-rp/src/intrinsics.rs new file mode 100644 index 000000000..3e75fb7fc --- /dev/null +++ b/embassy-rp/src/intrinsics.rs | |||
| @@ -0,0 +1,276 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | // Credit: taken from `rp-hal` (also licensed Apache+MIT) | ||
| 4 | // https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/intrinsics.rs | ||
| 5 | |||
| 6 | /// Generate a series of aliases for an intrinsic function. | ||
| 7 | macro_rules! intrinsics_aliases { | ||
| 8 | ( | ||
| 9 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, | ||
| 10 | ) => {}; | ||
| 11 | ( | ||
| 12 | unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, | ||
| 13 | ) => {}; | ||
| 14 | |||
| 15 | ( | ||
| 16 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, | ||
| 17 | $alias:ident | ||
| 18 | $($rest:ident)* | ||
| 19 | ) => { | ||
| 20 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 21 | intrinsics! { | ||
| 22 | extern $abi fn $alias( $($argname: $ty),* ) -> $ret { | ||
| 23 | $name($($argname),*) | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | intrinsics_aliases! { | ||
| 28 | extern $abi fn $name( $($argname: $ty),* ) -> $ret, | ||
| 29 | $($rest)* | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | |||
| 33 | ( | ||
| 34 | unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, | ||
| 35 | $alias:ident | ||
| 36 | $($rest:ident)* | ||
| 37 | ) => { | ||
| 38 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 39 | intrinsics! { | ||
| 40 | unsafe extern $abi fn $alias( $($argname: $ty),* ) -> $ret { | ||
| 41 | $name($($argname),*) | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | intrinsics_aliases! { | ||
| 46 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, | ||
| 47 | $($rest)* | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | |||
| 52 | /// The macro used to define overridden intrinsics. | ||
| 53 | /// | ||
| 54 | /// This is heavily inspired by the macro used by compiler-builtins. The idea | ||
| 55 | /// is to abstract anything special that needs to be done to override an | ||
| 56 | /// intrinsic function. Intrinsic generation is disabled for non-ARM targets | ||
| 57 | /// so things like CI and docs generation do not have problems. Additionally | ||
| 58 | /// they can be disabled by disabling the crate feature `intrinsics` for | ||
| 59 | /// testing or comparing performance. | ||
| 60 | /// | ||
| 61 | /// Like the compiler-builtins macro, it accepts a series of functions that | ||
| 62 | /// looks like normal Rust code: | ||
| 63 | /// | ||
| 64 | /// intrinsics! { | ||
| 65 | /// extern "C" fn foo(a: i32) -> u32 { | ||
| 66 | /// // ... | ||
| 67 | /// } | ||
| 68 | /// | ||
| 69 | /// #[nonstandard_attribute] | ||
| 70 | /// extern "C" fn bar(a: i32) -> u32 { | ||
| 71 | /// // ... | ||
| 72 | /// } | ||
| 73 | /// } | ||
| 74 | /// | ||
| 75 | /// Each function can also be decorated with nonstandard attributes to control | ||
| 76 | /// additional behaviour: | ||
| 77 | /// | ||
| 78 | /// * `slower_than_default` - indicates that the override is slower than the | ||
| 79 | /// default implementation. Currently this just disables the override | ||
| 80 | /// entirely. | ||
| 81 | /// * `bootrom_v2` - indicates that the override is only available | ||
| 82 | /// on a V2 bootrom or higher. Only enabled when the feature | ||
| 83 | /// `rom-v2-intrinsics` is set. | ||
| 84 | /// * `alias` - accepts a list of names to alias the intrinsic to. | ||
| 85 | /// * `aeabi` - accepts a list of ARM EABI names to alias to. | ||
| 86 | /// | ||
| 87 | macro_rules! intrinsics { | ||
| 88 | () => {}; | ||
| 89 | |||
| 90 | ( | ||
| 91 | #[slower_than_default] | ||
| 92 | $(#[$($attr:tt)*])* | ||
| 93 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 94 | $($body:tt)* | ||
| 95 | } | ||
| 96 | |||
| 97 | $($rest:tt)* | ||
| 98 | ) => { | ||
| 99 | // Not exported, but defined so the actual implementation is | ||
| 100 | // considered used | ||
| 101 | #[allow(dead_code)] | ||
| 102 | fn $name( $($argname: $ty),* ) -> $ret { | ||
| 103 | $($body)* | ||
| 104 | } | ||
| 105 | |||
| 106 | intrinsics!($($rest)*); | ||
| 107 | }; | ||
| 108 | |||
| 109 | ( | ||
| 110 | #[bootrom_v2] | ||
| 111 | $(#[$($attr:tt)*])* | ||
| 112 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 113 | $($body:tt)* | ||
| 114 | } | ||
| 115 | |||
| 116 | $($rest:tt)* | ||
| 117 | ) => { | ||
| 118 | // Not exported, but defined so the actual implementation is | ||
| 119 | // considered used | ||
| 120 | #[cfg(not(feature = "rom-v2-intrinsics"))] | ||
| 121 | #[allow(dead_code)] | ||
| 122 | fn $name( $($argname: $ty),* ) -> $ret { | ||
| 123 | $($body)* | ||
| 124 | } | ||
| 125 | |||
| 126 | #[cfg(feature = "rom-v2-intrinsics")] | ||
| 127 | intrinsics! { | ||
| 128 | $(#[$($attr)*])* | ||
| 129 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 130 | $($body)* | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | intrinsics!($($rest)*); | ||
| 135 | }; | ||
| 136 | |||
| 137 | ( | ||
| 138 | #[alias = $($alias:ident),*] | ||
| 139 | $(#[$($attr:tt)*])* | ||
| 140 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 141 | $($body:tt)* | ||
| 142 | } | ||
| 143 | |||
| 144 | $($rest:tt)* | ||
| 145 | ) => { | ||
| 146 | intrinsics! { | ||
| 147 | $(#[$($attr)*])* | ||
| 148 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 149 | $($body)* | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | intrinsics_aliases! { | ||
| 154 | extern $abi fn $name( $($argname: $ty),* ) -> $ret, | ||
| 155 | $($alias) * | ||
| 156 | } | ||
| 157 | |||
| 158 | intrinsics!($($rest)*); | ||
| 159 | }; | ||
| 160 | |||
| 161 | ( | ||
| 162 | #[alias = $($alias:ident),*] | ||
| 163 | $(#[$($attr:tt)*])* | ||
| 164 | unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 165 | $($body:tt)* | ||
| 166 | } | ||
| 167 | |||
| 168 | $($rest:tt)* | ||
| 169 | ) => { | ||
| 170 | intrinsics! { | ||
| 171 | $(#[$($attr)*])* | ||
| 172 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 173 | $($body)* | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | intrinsics_aliases! { | ||
| 178 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, | ||
| 179 | $($alias) * | ||
| 180 | } | ||
| 181 | |||
| 182 | intrinsics!($($rest)*); | ||
| 183 | }; | ||
| 184 | |||
| 185 | ( | ||
| 186 | #[aeabi = $($alias:ident),*] | ||
| 187 | $(#[$($attr:tt)*])* | ||
| 188 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 189 | $($body:tt)* | ||
| 190 | } | ||
| 191 | |||
| 192 | $($rest:tt)* | ||
| 193 | ) => { | ||
| 194 | intrinsics! { | ||
| 195 | $(#[$($attr)*])* | ||
| 196 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 197 | $($body)* | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | intrinsics_aliases! { | ||
| 202 | extern "aapcs" fn $name( $($argname: $ty),* ) -> $ret, | ||
| 203 | $($alias) * | ||
| 204 | } | ||
| 205 | |||
| 206 | intrinsics!($($rest)*); | ||
| 207 | }; | ||
| 208 | |||
| 209 | ( | ||
| 210 | $(#[$($attr:tt)*])* | ||
| 211 | extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 212 | $($body:tt)* | ||
| 213 | } | ||
| 214 | |||
| 215 | $($rest:tt)* | ||
| 216 | ) => { | ||
| 217 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 218 | $(#[$($attr)*])* | ||
| 219 | extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 220 | $($body)* | ||
| 221 | } | ||
| 222 | |||
| 223 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 224 | mod $name { | ||
| 225 | #[no_mangle] | ||
| 226 | $(#[$($attr)*])* | ||
| 227 | pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 228 | super::$name($($argname),*) | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | // Not exported, but defined so the actual implementation is | ||
| 233 | // considered used | ||
| 234 | #[cfg(not(all(target_arch = "arm", feature = "intrinsics")))] | ||
| 235 | #[allow(dead_code)] | ||
| 236 | fn $name( $($argname: $ty),* ) -> $ret { | ||
| 237 | $($body)* | ||
| 238 | } | ||
| 239 | |||
| 240 | intrinsics!($($rest)*); | ||
| 241 | }; | ||
| 242 | |||
| 243 | ( | ||
| 244 | $(#[$($attr:tt)*])* | ||
| 245 | unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { | ||
| 246 | $($body:tt)* | ||
| 247 | } | ||
| 248 | |||
| 249 | $($rest:tt)* | ||
| 250 | ) => { | ||
| 251 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 252 | $(#[$($attr)*])* | ||
| 253 | unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 254 | $($body)* | ||
| 255 | } | ||
| 256 | |||
| 257 | #[cfg(all(target_arch = "arm", feature = "intrinsics"))] | ||
| 258 | mod $name { | ||
| 259 | #[no_mangle] | ||
| 260 | $(#[$($attr)*])* | ||
| 261 | pub unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { | ||
| 262 | super::$name($($argname),*) | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | // Not exported, but defined so the actual implementation is | ||
| 267 | // considered used | ||
| 268 | #[cfg(not(all(target_arch = "arm", feature = "intrinsics")))] | ||
| 269 | #[allow(dead_code)] | ||
| 270 | unsafe fn $name( $($argname: $ty),* ) -> $ret { | ||
| 271 | $($body)* | ||
| 272 | } | ||
| 273 | |||
| 274 | intrinsics!($($rest)*); | ||
| 275 | }; | ||
| 276 | } | ||
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index aebbbf567..9ac98d226 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -1,13 +1,18 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | 3 | ||
| 4 | // This mod MUST go first, so that the others see its macros. | 4 | // This mod MUST go first, so that the others see its macros. |
| 5 | pub(crate) mod fmt; | 5 | pub(crate) mod fmt; |
| 6 | 6 | ||
| 7 | mod intrinsics; | ||
| 8 | |||
| 7 | pub mod dma; | 9 | pub mod dma; |
| 8 | pub mod gpio; | 10 | pub mod gpio; |
| 9 | pub mod interrupt; | 11 | pub mod interrupt; |
| 12 | pub mod rom_data; | ||
| 13 | pub mod rtc; | ||
| 10 | pub mod spi; | 14 | pub mod spi; |
| 15 | #[cfg(feature = "time-driver")] | ||
| 11 | pub mod timer; | 16 | pub mod timer; |
| 12 | pub mod uart; | 17 | pub mod uart; |
| 13 | #[cfg(feature = "nightly")] | 18 | #[cfg(feature = "nightly")] |
| @@ -84,6 +89,8 @@ embassy_hal_common::peripherals! { | |||
| 84 | DMA_CH11, | 89 | DMA_CH11, |
| 85 | 90 | ||
| 86 | USB, | 91 | USB, |
| 92 | |||
| 93 | RTC, | ||
| 87 | } | 94 | } |
| 88 | 95 | ||
| 89 | #[link_section = ".boot2"] | 96 | #[link_section = ".boot2"] |
| @@ -108,6 +115,7 @@ pub fn init(_config: config::Config) -> Peripherals { | |||
| 108 | 115 | ||
| 109 | unsafe { | 116 | unsafe { |
| 110 | clocks::init(); | 117 | clocks::init(); |
| 118 | #[cfg(feature = "time-driver")] | ||
| 111 | timer::init(); | 119 | timer::init(); |
| 112 | dma::init(); | 120 | dma::init(); |
| 113 | } | 121 | } |
diff --git a/embassy-rp/src/rom_data.rs b/embassy-rp/src/rom_data.rs new file mode 100644 index 000000000..757a27114 --- /dev/null +++ b/embassy-rp/src/rom_data.rs | |||
| @@ -0,0 +1,733 @@ | |||
| 1 | //! Functions and data from the RPI Bootrom. | ||
| 2 | //! | ||
| 3 | //! From the [RP2040 datasheet](https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf), Section 2.8.2.1: | ||
| 4 | //! | ||
| 5 | //! > The Bootrom contains a number of public functions that provide useful | ||
| 6 | //! > RP2040 functionality that might be needed in the absence of any other code | ||
| 7 | //! > on the device, as well as highly optimized versions of certain key | ||
| 8 | //! > functionality that would otherwise have to take up space in most user | ||
| 9 | //! > binaries. | ||
| 10 | |||
| 11 | // Credit: taken from `rp-hal` (also licensed Apache+MIT) | ||
| 12 | // https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/src/rom_data.rs | ||
| 13 | |||
| 14 | /// A bootrom function table code. | ||
| 15 | pub type RomFnTableCode = [u8; 2]; | ||
| 16 | |||
| 17 | /// This function searches for (table) | ||
| 18 | type RomTableLookupFn<T> = unsafe extern "C" fn(*const u16, u32) -> T; | ||
| 19 | |||
| 20 | /// The following addresses are described at `2.8.2. Bootrom Contents` | ||
| 21 | /// Pointer to the lookup table function supplied by the rom. | ||
| 22 | const ROM_TABLE_LOOKUP_PTR: *const u16 = 0x0000_0018 as _; | ||
| 23 | |||
| 24 | /// Pointer to helper functions lookup table. | ||
| 25 | const FUNC_TABLE: *const u16 = 0x0000_0014 as _; | ||
| 26 | |||
| 27 | /// Pointer to the public data lookup table. | ||
| 28 | const DATA_TABLE: *const u16 = 0x0000_0016 as _; | ||
| 29 | |||
| 30 | /// Address of the version number of the ROM. | ||
| 31 | const VERSION_NUMBER: *const u8 = 0x0000_0013 as _; | ||
| 32 | |||
| 33 | /// Retrive rom content from a table using a code. | ||
| 34 | fn rom_table_lookup<T>(table: *const u16, tag: RomFnTableCode) -> T { | ||
| 35 | unsafe { | ||
| 36 | let rom_table_lookup_ptr: *const u32 = rom_hword_as_ptr(ROM_TABLE_LOOKUP_PTR); | ||
| 37 | let rom_table_lookup: RomTableLookupFn<T> = core::mem::transmute(rom_table_lookup_ptr); | ||
| 38 | rom_table_lookup(rom_hword_as_ptr(table) as *const u16, u16::from_le_bytes(tag) as u32) | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | /// To save space, the ROM likes to store memory pointers (which are 32-bit on | ||
| 43 | /// the Cortex-M0+) using only the bottom 16-bits. The assumption is that the | ||
| 44 | /// values they point at live in the first 64 KiB of ROM, and the ROM is mapped | ||
| 45 | /// to address `0x0000_0000` and so 16-bits are always sufficient. | ||
| 46 | /// | ||
| 47 | /// This functions grabs a 16-bit value from ROM and expands it out to a full 32-bit pointer. | ||
| 48 | unsafe fn rom_hword_as_ptr(rom_address: *const u16) -> *const u32 { | ||
| 49 | let ptr: u16 = *rom_address; | ||
| 50 | ptr as *const u32 | ||
| 51 | } | ||
| 52 | |||
| 53 | macro_rules! declare_rom_function { | ||
| 54 | ( | ||
| 55 | $(#[$outer:meta])* | ||
| 56 | fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty | ||
| 57 | $lookup:block | ||
| 58 | ) => { | ||
| 59 | #[doc = r"Additional access for the `"] | ||
| 60 | #[doc = stringify!($name)] | ||
| 61 | #[doc = r"` ROM function."] | ||
| 62 | pub mod $name { | ||
| 63 | /// Retrieve a function pointer. | ||
| 64 | #[cfg(not(feature = "rom-func-cache"))] | ||
| 65 | pub fn ptr() -> extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 66 | let p: *const u32 = $lookup; | ||
| 67 | unsafe { | ||
| 68 | let func : extern "C" fn( $($argname: $ty),* ) -> $ret = core::mem::transmute(p); | ||
| 69 | func | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | /// Retrieve a function pointer. | ||
| 74 | #[cfg(feature = "rom-func-cache")] | ||
| 75 | pub fn ptr() -> extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 76 | use core::sync::atomic::{AtomicU16, Ordering}; | ||
| 77 | |||
| 78 | // All pointers in the ROM fit in 16 bits, so we don't need a | ||
| 79 | // full width word to store the cached value. | ||
| 80 | static CACHED_PTR: AtomicU16 = AtomicU16::new(0); | ||
| 81 | // This is safe because the lookup will always resolve | ||
| 82 | // to the same value. So even if an interrupt or another | ||
| 83 | // core starts at the same time, it just repeats some | ||
| 84 | // work and eventually writes back the correct value. | ||
| 85 | let p: *const u32 = match CACHED_PTR.load(Ordering::Relaxed) { | ||
| 86 | 0 => { | ||
| 87 | let raw: *const u32 = $lookup; | ||
| 88 | CACHED_PTR.store(raw as u16, Ordering::Relaxed); | ||
| 89 | raw | ||
| 90 | }, | ||
| 91 | val => val as *const u32, | ||
| 92 | }; | ||
| 93 | unsafe { | ||
| 94 | let func : extern "C" fn( $($argname: $ty),* ) -> $ret = core::mem::transmute(p); | ||
| 95 | func | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | $(#[$outer])* | ||
| 101 | pub extern "C" fn $name( $($argname: $ty),* ) -> $ret { | ||
| 102 | $name::ptr()($($argname),*) | ||
| 103 | } | ||
| 104 | }; | ||
| 105 | |||
| 106 | ( | ||
| 107 | $(#[$outer:meta])* | ||
| 108 | unsafe fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty | ||
| 109 | $lookup:block | ||
| 110 | ) => { | ||
| 111 | #[doc = r"Additional access for the `"] | ||
| 112 | #[doc = stringify!($name)] | ||
| 113 | #[doc = r"` ROM function."] | ||
| 114 | pub mod $name { | ||
| 115 | /// Retrieve a function pointer. | ||
| 116 | #[cfg(not(feature = "rom-func-cache"))] | ||
| 117 | pub fn ptr() -> unsafe extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 118 | let p: *const u32 = $lookup; | ||
| 119 | unsafe { | ||
| 120 | let func : unsafe extern "C" fn( $($argname: $ty),* ) -> $ret = core::mem::transmute(p); | ||
| 121 | func | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | /// Retrieve a function pointer. | ||
| 126 | #[cfg(feature = "rom-func-cache")] | ||
| 127 | pub fn ptr() -> unsafe extern "C" fn( $($argname: $ty),* ) -> $ret { | ||
| 128 | use core::sync::atomic::{AtomicU16, Ordering}; | ||
| 129 | |||
| 130 | // All pointers in the ROM fit in 16 bits, so we don't need a | ||
| 131 | // full width word to store the cached value. | ||
| 132 | static CACHED_PTR: AtomicU16 = AtomicU16::new(0); | ||
| 133 | // This is safe because the lookup will always resolve | ||
| 134 | // to the same value. So even if an interrupt or another | ||
| 135 | // core starts at the same time, it just repeats some | ||
| 136 | // work and eventually writes back the correct value. | ||
| 137 | let p: *const u32 = match CACHED_PTR.load(Ordering::Relaxed) { | ||
| 138 | 0 => { | ||
| 139 | let raw: *const u32 = $lookup; | ||
| 140 | CACHED_PTR.store(raw as u16, Ordering::Relaxed); | ||
| 141 | raw | ||
| 142 | }, | ||
| 143 | val => val as *const u32, | ||
| 144 | }; | ||
| 145 | unsafe { | ||
| 146 | let func : unsafe extern "C" fn( $($argname: $ty),* ) -> $ret = core::mem::transmute(p); | ||
| 147 | func | ||
| 148 | } | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | $(#[$outer])* | ||
| 153 | pub unsafe extern "C" fn $name( $($argname: $ty),* ) -> $ret { | ||
| 154 | $name::ptr()($($argname),*) | ||
| 155 | } | ||
| 156 | }; | ||
| 157 | } | ||
| 158 | |||
| 159 | macro_rules! rom_functions { | ||
| 160 | () => {}; | ||
| 161 | |||
| 162 | ( | ||
| 163 | $(#[$outer:meta])* | ||
| 164 | $c:literal fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty; | ||
| 165 | |||
| 166 | $($rest:tt)* | ||
| 167 | ) => { | ||
| 168 | declare_rom_function! { | ||
| 169 | $(#[$outer])* | ||
| 170 | fn $name( $($argname: $ty),* ) -> $ret { | ||
| 171 | $crate::rom_data::rom_table_lookup($crate::rom_data::FUNC_TABLE, *$c) | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | rom_functions!($($rest)*); | ||
| 176 | }; | ||
| 177 | |||
| 178 | ( | ||
| 179 | $(#[$outer:meta])* | ||
| 180 | $c:literal unsafe fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty; | ||
| 181 | |||
| 182 | $($rest:tt)* | ||
| 183 | ) => { | ||
| 184 | declare_rom_function! { | ||
| 185 | $(#[$outer])* | ||
| 186 | unsafe fn $name( $($argname: $ty),* ) -> $ret { | ||
| 187 | $crate::rom_data::rom_table_lookup($crate::rom_data::FUNC_TABLE, *$c) | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | rom_functions!($($rest)*); | ||
| 192 | }; | ||
| 193 | } | ||
| 194 | |||
| 195 | rom_functions! { | ||
| 196 | /// Return a count of the number of 1 bits in value. | ||
| 197 | b"P3" fn popcount32(value: u32) -> u32; | ||
| 198 | |||
| 199 | /// Return the bits of value in the reverse order. | ||
| 200 | b"R3" fn reverse32(value: u32) -> u32; | ||
| 201 | |||
| 202 | /// Return the number of consecutive high order 0 bits of value. If value is zero, returns 32. | ||
| 203 | b"L3" fn clz32(value: u32) -> u32; | ||
| 204 | |||
| 205 | /// Return the number of consecutive low order 0 bits of value. If value is zero, returns 32. | ||
| 206 | b"T3" fn ctz32(value: u32) -> u32; | ||
| 207 | |||
| 208 | /// Resets the RP2040 and uses the watchdog facility to re-start in BOOTSEL mode: | ||
| 209 | /// * gpio_activity_pin_mask is provided to enable an 'activity light' via GPIO attached LED | ||
| 210 | /// for the USB Mass Storage Device: | ||
| 211 | /// * 0 No pins are used as per cold boot. | ||
| 212 | /// * Otherwise a single bit set indicating which GPIO pin should be set to output and | ||
| 213 | /// raised whenever there is mass storage activity from the host. | ||
| 214 | /// * disable_interface_mask may be used to control the exposed USB interfaces: | ||
| 215 | /// * 0 To enable both interfaces (as per cold boot). | ||
| 216 | /// * 1 To disable the USB Mass Storage Interface. | ||
| 217 | /// * 2 to Disable the USB PICOBOOT Interface. | ||
| 218 | b"UB" fn reset_to_usb_boot(gpio_activity_pin_mask: u32, disable_interface_mask: u32) -> (); | ||
| 219 | |||
| 220 | /// Sets n bytes start at ptr to the value c and returns ptr | ||
| 221 | b"MS" unsafe fn memset(ptr: *mut u8, c: u8, n: u32) -> *mut u8; | ||
| 222 | |||
| 223 | /// Sets n bytes start at ptr to the value c and returns ptr. | ||
| 224 | /// | ||
| 225 | /// Note this is a slightly more efficient variant of _memset that may only | ||
| 226 | /// be used if ptr is word aligned. | ||
| 227 | // Note the datasheet does not match the actual ROM for the code here, see | ||
| 228 | // https://github.com/raspberrypi/pico-feedback/issues/217 | ||
| 229 | b"S4" unsafe fn memset4(ptr: *mut u32, c: u8, n: u32) -> *mut u32; | ||
| 230 | |||
| 231 | /// Copies n bytes starting at src to dest and returns dest. The results are undefined if the | ||
| 232 | /// regions overlap. | ||
| 233 | b"MC" unsafe fn memcpy(dest: *mut u8, src: *const u8, n: u32) -> *mut u8; | ||
| 234 | |||
| 235 | /// Copies n bytes starting at src to dest and returns dest. The results are undefined if the | ||
| 236 | /// regions overlap. | ||
| 237 | /// | ||
| 238 | /// Note this is a slightly more efficient variant of _memcpy that may only be | ||
| 239 | /// used if dest and src are word aligned. | ||
| 240 | b"C4" unsafe fn memcpy44(dest: *mut u32, src: *const u32, n: u32) -> *mut u8; | ||
| 241 | |||
| 242 | /// Restore all QSPI pad controls to their default state, and connect the SSI to the QSPI pads. | ||
| 243 | b"IF" unsafe fn connect_internal_flash() -> (); | ||
| 244 | |||
| 245 | /// First set up the SSI for serial-mode operations, then issue the fixed XIP exit sequence. | ||
| 246 | /// | ||
| 247 | /// Note that the bootrom code uses the IO forcing logic to drive the CS pin, which must be | ||
| 248 | /// cleared before returning the SSI to XIP mode (e.g. by a call to _flash_flush_cache). This | ||
| 249 | /// function configures the SSI with a fixed SCK clock divisor of /6. | ||
| 250 | b"EX" unsafe fn flash_exit_xip() -> (); | ||
| 251 | |||
| 252 | /// Erase a count bytes, starting at addr (offset from start of flash). Optionally, pass a | ||
| 253 | /// block erase command e.g. D8h block erase, and the size of the block erased by this | ||
| 254 | /// command — this function will use the larger block erase where possible, for much higher | ||
| 255 | /// erase speed. addr must be aligned to a 4096-byte sector, and count must be a multiple of | ||
| 256 | /// 4096 bytes. | ||
| 257 | b"RE" unsafe fn flash_range_erase(addr: u32, count: usize, block_size: u32, block_cmd: u8) -> (); | ||
| 258 | |||
| 259 | /// Program data to a range of flash addresses starting at `addr` (and | ||
| 260 | /// offset from the start of flash) and `count` bytes in size. The value | ||
| 261 | /// `addr` must be aligned to a 256-byte boundary, and `count` must be a | ||
| 262 | /// multiple of 256. | ||
| 263 | b"RP" unsafe fn flash_range_program(addr: u32, data: *const u8, count: usize) -> (); | ||
| 264 | |||
| 265 | /// Flush and enable the XIP cache. Also clears the IO forcing on QSPI CSn, so that the SSI can | ||
| 266 | /// drive the flashchip select as normal. | ||
| 267 | b"FC" unsafe fn flash_flush_cache() -> (); | ||
| 268 | |||
| 269 | /// Configure the SSI to generate a standard 03h serial read command, with 24 address bits, | ||
| 270 | /// upon each XIP access. This is a very slow XIP configuration, but is very widely supported. | ||
| 271 | /// The debugger calls this function after performing a flash erase/programming operation, so | ||
| 272 | /// that the freshly-programmed code and data is visible to the debug host, without having to | ||
| 273 | /// know exactly what kind of flash device is connected. | ||
| 274 | b"CX" unsafe fn flash_enter_cmd_xip() -> (); | ||
| 275 | |||
| 276 | /// This is the method that is entered by core 1 on reset to wait to be launched by core 0. | ||
| 277 | /// There are few cases where you should call this method (resetting core 1 is much better). | ||
| 278 | /// This method does not return and should only ever be called on core 1. | ||
| 279 | b"WV" unsafe fn wait_for_vector() -> !; | ||
| 280 | } | ||
| 281 | |||
| 282 | // Various C intrinsics in the ROM | ||
| 283 | intrinsics! { | ||
| 284 | #[alias = __popcountdi2] | ||
| 285 | extern "C" fn __popcountsi2(x: u32) -> u32 { | ||
| 286 | popcount32(x) | ||
| 287 | } | ||
| 288 | |||
| 289 | #[alias = __clzdi2] | ||
| 290 | extern "C" fn __clzsi2(x: u32) -> u32 { | ||
| 291 | clz32(x) | ||
| 292 | } | ||
| 293 | |||
| 294 | #[alias = __ctzdi2] | ||
| 295 | extern "C" fn __ctzsi2(x: u32) -> u32 { | ||
| 296 | ctz32(x) | ||
| 297 | } | ||
| 298 | |||
| 299 | // __rbit is only unofficial, but it show up in the ARM documentation, | ||
| 300 | // so may as well hook it up. | ||
| 301 | #[alias = __rbitl] | ||
| 302 | extern "C" fn __rbit(x: u32) -> u32 { | ||
| 303 | reverse32(x) | ||
| 304 | } | ||
| 305 | |||
| 306 | unsafe extern "aapcs" fn __aeabi_memset(dest: *mut u8, n: usize, c: i32) -> () { | ||
| 307 | // Different argument order | ||
| 308 | memset(dest, c as u8, n as u32); | ||
| 309 | } | ||
| 310 | |||
| 311 | #[alias = __aeabi_memset8] | ||
| 312 | unsafe extern "aapcs" fn __aeabi_memset4(dest: *mut u8, n: usize, c: i32) -> () { | ||
| 313 | // Different argument order | ||
| 314 | memset4(dest as *mut u32, c as u8, n as u32); | ||
| 315 | } | ||
| 316 | |||
| 317 | unsafe extern "aapcs" fn __aeabi_memclr(dest: *mut u8, n: usize) -> () { | ||
| 318 | memset(dest, 0, n as u32); | ||
| 319 | } | ||
| 320 | |||
| 321 | #[alias = __aeabi_memclr8] | ||
| 322 | unsafe extern "aapcs" fn __aeabi_memclr4(dest: *mut u8, n: usize) -> () { | ||
| 323 | memset4(dest as *mut u32, 0, n as u32); | ||
| 324 | } | ||
| 325 | |||
| 326 | unsafe extern "aapcs" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, n: usize) -> () { | ||
| 327 | memcpy(dest, src, n as u32); | ||
| 328 | } | ||
| 329 | |||
| 330 | #[alias = __aeabi_memcpy8] | ||
| 331 | unsafe extern "aapcs" fn __aeabi_memcpy4(dest: *mut u8, src: *const u8, n: usize) -> () { | ||
| 332 | memcpy44(dest as *mut u32, src as *const u32, n as u32); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | unsafe fn convert_str(s: *const u8) -> &'static str { | ||
| 337 | let mut end = s; | ||
| 338 | while *end != 0 { | ||
| 339 | end = end.add(1); | ||
| 340 | } | ||
| 341 | let s = core::slice::from_raw_parts(s, end.offset_from(s) as usize); | ||
| 342 | core::str::from_utf8_unchecked(s) | ||
| 343 | } | ||
| 344 | |||
| 345 | /// The version number of the rom. | ||
| 346 | pub fn rom_version_number() -> u8 { | ||
| 347 | unsafe { *VERSION_NUMBER } | ||
| 348 | } | ||
| 349 | |||
| 350 | /// The Raspberry Pi Trading Ltd copyright string. | ||
| 351 | pub fn copyright_string() -> &'static str { | ||
| 352 | let s: *const u8 = rom_table_lookup(DATA_TABLE, *b"CR"); | ||
| 353 | unsafe { convert_str(s) } | ||
| 354 | } | ||
| 355 | |||
| 356 | /// The 8 most significant hex digits of the Bootrom git revision. | ||
| 357 | pub fn git_revision() -> u32 { | ||
| 358 | let s: *const u32 = rom_table_lookup(DATA_TABLE, *b"GR"); | ||
| 359 | unsafe { *s } | ||
| 360 | } | ||
| 361 | |||
| 362 | /// The start address of the floating point library code and data. | ||
| 363 | /// | ||
| 364 | /// This and fplib_end along with the individual function pointers in | ||
| 365 | /// soft_float_table can be used to copy the floating point implementation into | ||
| 366 | /// RAM if desired. | ||
| 367 | pub fn fplib_start() -> *const u8 { | ||
| 368 | rom_table_lookup(DATA_TABLE, *b"FS") | ||
| 369 | } | ||
| 370 | |||
| 371 | /// See Table 180 in the RP2040 datasheet for the contents of this table. | ||
| 372 | pub fn soft_float_table() -> *const usize { | ||
| 373 | rom_table_lookup(DATA_TABLE, *b"SF") | ||
| 374 | } | ||
| 375 | |||
| 376 | /// The end address of the floating point library code and data. | ||
| 377 | pub fn fplib_end() -> *const u8 { | ||
| 378 | rom_table_lookup(DATA_TABLE, *b"FE") | ||
| 379 | } | ||
| 380 | |||
| 381 | /// This entry is only present in the V2 bootrom. See Table 182 in the RP2040 datasheet for the contents of this table. | ||
| 382 | pub fn soft_double_table() -> *const usize { | ||
| 383 | if rom_version_number() < 2 { | ||
| 384 | panic!( | ||
| 385 | "Double precision operations require V2 bootrom (found: V{})", | ||
| 386 | rom_version_number() | ||
| 387 | ); | ||
| 388 | } | ||
| 389 | rom_table_lookup(DATA_TABLE, *b"SD") | ||
| 390 | } | ||
| 391 | |||
| 392 | /// ROM functions using single-precision arithmetic (i.e. 'f32' in Rust terms) | ||
| 393 | pub mod float_funcs { | ||
| 394 | |||
| 395 | macro_rules! make_functions { | ||
| 396 | ( | ||
| 397 | $( | ||
| 398 | $(#[$outer:meta])* | ||
| 399 | $offset:literal $name:ident ( | ||
| 400 | $( $aname:ident : $aty:ty ),* | ||
| 401 | ) -> $ret:ty; | ||
| 402 | )* | ||
| 403 | ) => { | ||
| 404 | $( | ||
| 405 | declare_rom_function! { | ||
| 406 | $(#[$outer])* | ||
| 407 | fn $name( $( $aname : $aty ),* ) -> $ret { | ||
| 408 | let table: *const usize = $crate::rom_data::soft_float_table(); | ||
| 409 | unsafe { | ||
| 410 | // This is the entry in the table. Our offset is given as a | ||
| 411 | // byte offset, but we want the table index (each pointer in | ||
| 412 | // the table is 4 bytes long) | ||
| 413 | let entry: *const usize = table.offset($offset / 4); | ||
| 414 | // Read the pointer from the table | ||
| 415 | core::ptr::read(entry) as *const u32 | ||
| 416 | } | ||
| 417 | } | ||
| 418 | } | ||
| 419 | )* | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | make_functions! { | ||
| 424 | /// Calculates `a + b` | ||
| 425 | 0x00 fadd(a: f32, b: f32) -> f32; | ||
| 426 | /// Calculates `a - b` | ||
| 427 | 0x04 fsub(a: f32, b: f32) -> f32; | ||
| 428 | /// Calculates `a * b` | ||
| 429 | 0x08 fmul(a: f32, b: f32) -> f32; | ||
| 430 | /// Calculates `a / b` | ||
| 431 | 0x0c fdiv(a: f32, b: f32) -> f32; | ||
| 432 | |||
| 433 | // 0x10 and 0x14 are deprecated | ||
| 434 | |||
| 435 | /// Calculates `sqrt(v)` (or return -Infinity if v is negative) | ||
| 436 | 0x18 fsqrt(v: f32) -> f32; | ||
| 437 | /// Converts an f32 to a signed integer, | ||
| 438 | /// rounding towards -Infinity, and clamping the result to lie within the | ||
| 439 | /// range `-0x80000000` to `0x7FFFFFFF` | ||
| 440 | 0x1c float_to_int(v: f32) -> i32; | ||
| 441 | /// Converts an f32 to an signed fixed point | ||
| 442 | /// integer representation where n specifies the position of the binary | ||
| 443 | /// point in the resulting fixed point representation, e.g. | ||
| 444 | /// `f(0.5f, 16) == 0x8000`. This method rounds towards -Infinity, | ||
| 445 | /// and clamps the resulting integer to lie within the range `0x00000000` to | ||
| 446 | /// `0xFFFFFFFF` | ||
| 447 | 0x20 float_to_fix(v: f32, n: i32) -> i32; | ||
| 448 | /// Converts an f32 to an unsigned integer, | ||
| 449 | /// rounding towards -Infinity, and clamping the result to lie within the | ||
| 450 | /// range `0x00000000` to `0xFFFFFFFF` | ||
| 451 | 0x24 float_to_uint(v: f32) -> u32; | ||
| 452 | /// Converts an f32 to an unsigned fixed point | ||
| 453 | /// integer representation where n specifies the position of the binary | ||
| 454 | /// point in the resulting fixed point representation, e.g. | ||
| 455 | /// `f(0.5f, 16) == 0x8000`. This method rounds towards -Infinity, | ||
| 456 | /// and clamps the resulting integer to lie within the range `0x00000000` to | ||
| 457 | /// `0xFFFFFFFF` | ||
| 458 | 0x28 float_to_ufix(v: f32, n: i32) -> u32; | ||
| 459 | /// Converts a signed integer to the nearest | ||
| 460 | /// f32 value, rounding to even on tie | ||
| 461 | 0x2c int_to_float(v: i32) -> f32; | ||
| 462 | /// Converts a signed fixed point integer | ||
| 463 | /// representation to the nearest f32 value, rounding to even on tie. `n` | ||
| 464 | /// specifies the position of the binary point in fixed point, so `f = | ||
| 465 | /// nearest(v/(2^n))` | ||
| 466 | 0x30 fix_to_float(v: i32, n: i32) -> f32; | ||
| 467 | /// Converts an unsigned integer to the nearest | ||
| 468 | /// f32 value, rounding to even on tie | ||
| 469 | 0x34 uint_to_float(v: u32) -> f32; | ||
| 470 | /// Converts an unsigned fixed point integer | ||
| 471 | /// representation to the nearest f32 value, rounding to even on tie. `n` | ||
| 472 | /// specifies the position of the binary point in fixed point, so `f = | ||
| 473 | /// nearest(v/(2^n))` | ||
| 474 | 0x38 ufix_to_float(v: u32, n: i32) -> f32; | ||
| 475 | /// Calculates the cosine of `angle`. The value | ||
| 476 | /// of `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 477 | 0x3c fcos(angle: f32) -> f32; | ||
| 478 | /// Calculates the sine of `angle`. The value of | ||
| 479 | /// `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 480 | 0x40 fsin(angle: f32) -> f32; | ||
| 481 | /// Calculates the tangent of `angle`. The value | ||
| 482 | /// of `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 483 | 0x44 ftan(angle: f32) -> f32; | ||
| 484 | |||
| 485 | // 0x48 is deprecated | ||
| 486 | |||
| 487 | /// Calculates the exponential value of `v`, | ||
| 488 | /// i.e. `e ** v` | ||
| 489 | 0x4c fexp(v: f32) -> f32; | ||
| 490 | /// Calculates the natural logarithm of `v`. If `v <= 0` return -Infinity | ||
| 491 | 0x50 fln(v: f32) -> f32; | ||
| 492 | } | ||
| 493 | |||
| 494 | macro_rules! make_functions_v2 { | ||
| 495 | ( | ||
| 496 | $( | ||
| 497 | $(#[$outer:meta])* | ||
| 498 | $offset:literal $name:ident ( | ||
| 499 | $( $aname:ident : $aty:ty ),* | ||
| 500 | ) -> $ret:ty; | ||
| 501 | )* | ||
| 502 | ) => { | ||
| 503 | $( | ||
| 504 | declare_rom_function! { | ||
| 505 | $(#[$outer])* | ||
| 506 | fn $name( $( $aname : $aty ),* ) -> $ret { | ||
| 507 | if $crate::rom_data::rom_version_number() < 2 { | ||
| 508 | panic!( | ||
| 509 | "Floating point function requires V2 bootrom (found: V{})", | ||
| 510 | $crate::rom_data::rom_version_number() | ||
| 511 | ); | ||
| 512 | } | ||
| 513 | let table: *const usize = $crate::rom_data::soft_float_table(); | ||
| 514 | unsafe { | ||
| 515 | // This is the entry in the table. Our offset is given as a | ||
| 516 | // byte offset, but we want the table index (each pointer in | ||
| 517 | // the table is 4 bytes long) | ||
| 518 | let entry: *const usize = table.offset($offset / 4); | ||
| 519 | // Read the pointer from the table | ||
| 520 | core::ptr::read(entry) as *const u32 | ||
| 521 | } | ||
| 522 | } | ||
| 523 | } | ||
| 524 | )* | ||
| 525 | } | ||
| 526 | } | ||
| 527 | |||
| 528 | // These are only on BootROM v2 or higher | ||
| 529 | make_functions_v2! { | ||
| 530 | /// Compares two floating point numbers, returning: | ||
| 531 | /// • 0 if a == b | ||
| 532 | /// • -1 if a < b | ||
| 533 | /// • 1 if a > b | ||
| 534 | 0x54 fcmp(a: f32, b: f32) -> i32; | ||
| 535 | /// Computes the arc tangent of `y/x` using the | ||
| 536 | /// signs of arguments to determine the correct quadrant | ||
| 537 | 0x58 fatan2(y: f32, x: f32) -> f32; | ||
| 538 | /// Converts a signed 64-bit integer to the | ||
| 539 | /// nearest f32 value, rounding to even on tie | ||
| 540 | 0x5c int64_to_float(v: i64) -> f32; | ||
| 541 | /// Converts a signed fixed point 64-bit integer | ||
| 542 | /// representation to the nearest f32 value, rounding to even on tie. `n` | ||
| 543 | /// specifies the position of the binary point in fixed point, so `f = | ||
| 544 | /// nearest(v/(2^n))` | ||
| 545 | 0x60 fix64_to_float(v: i64, n: i32) -> f32; | ||
| 546 | /// Converts an unsigned 64-bit integer to the | ||
| 547 | /// nearest f32 value, rounding to even on tie | ||
| 548 | 0x64 uint64_to_float(v: u64) -> f32; | ||
| 549 | /// Converts an unsigned fixed point 64-bit | ||
| 550 | /// integer representation to the nearest f32 value, rounding to even on | ||
| 551 | /// tie. `n` specifies the position of the binary point in fixed point, so | ||
| 552 | /// `f = nearest(v/(2^n))` | ||
| 553 | 0x68 ufix64_to_float(v: u64, n: i32) -> f32; | ||
| 554 | /// Convert an f32 to a signed 64-bit integer, rounding towards -Infinity, | ||
| 555 | /// and clamping the result to lie within the range `-0x8000000000000000` to | ||
| 556 | /// `0x7FFFFFFFFFFFFFFF` | ||
| 557 | 0x6c float_to_int64(v: f32) -> i64; | ||
| 558 | /// Converts an f32 to a signed fixed point | ||
| 559 | /// 64-bit integer representation where n specifies the position of the | ||
| 560 | /// binary point in the resulting fixed point representation - e.g. `f(0.5f, | ||
| 561 | /// 16) == 0x8000`. This method rounds towards -Infinity, and clamps the | ||
| 562 | /// resulting integer to lie within the range `-0x8000000000000000` to | ||
| 563 | /// `0x7FFFFFFFFFFFFFFF` | ||
| 564 | 0x70 float_to_fix64(v: f32, n: i32) -> f32; | ||
| 565 | /// Converts an f32 to an unsigned 64-bit | ||
| 566 | /// integer, rounding towards -Infinity, and clamping the result to lie | ||
| 567 | /// within the range `0x0000000000000000` to `0xFFFFFFFFFFFFFFFF` | ||
| 568 | 0x74 float_to_uint64(v: f32) -> u64; | ||
| 569 | /// Converts an f32 to an unsigned fixed point | ||
| 570 | /// 64-bit integer representation where n specifies the position of the | ||
| 571 | /// binary point in the resulting fixed point representation, e.g. `f(0.5f, | ||
| 572 | /// 16) == 0x8000`. This method rounds towards -Infinity, and clamps the | ||
| 573 | /// resulting integer to lie within the range `0x0000000000000000` to | ||
| 574 | /// `0xFFFFFFFFFFFFFFFF` | ||
| 575 | 0x78 float_to_ufix64(v: f32, n: i32) -> u64; | ||
| 576 | /// Converts an f32 to an f64. | ||
| 577 | 0x7c float_to_double(v: f32) -> f64; | ||
| 578 | } | ||
| 579 | } | ||
| 580 | |||
| 581 | /// Functions using double-precision arithmetic (i.e. 'f64' in Rust terms) | ||
| 582 | pub mod double_funcs { | ||
| 583 | |||
| 584 | macro_rules! make_double_funcs { | ||
| 585 | ( | ||
| 586 | $( | ||
| 587 | $(#[$outer:meta])* | ||
| 588 | $offset:literal $name:ident ( | ||
| 589 | $( $aname:ident : $aty:ty ),* | ||
| 590 | ) -> $ret:ty; | ||
| 591 | )* | ||
| 592 | ) => { | ||
| 593 | $( | ||
| 594 | declare_rom_function! { | ||
| 595 | $(#[$outer])* | ||
| 596 | fn $name( $( $aname : $aty ),* ) -> $ret { | ||
| 597 | let table: *const usize = $crate::rom_data::soft_double_table(); | ||
| 598 | unsafe { | ||
| 599 | // This is the entry in the table. Our offset is given as a | ||
| 600 | // byte offset, but we want the table index (each pointer in | ||
| 601 | // the table is 4 bytes long) | ||
| 602 | let entry: *const usize = table.offset($offset / 4); | ||
| 603 | // Read the pointer from the table | ||
| 604 | core::ptr::read(entry) as *const u32 | ||
| 605 | } | ||
| 606 | } | ||
| 607 | } | ||
| 608 | )* | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 612 | make_double_funcs! { | ||
| 613 | /// Calculates `a + b` | ||
| 614 | 0x00 dadd(a: f64, b: f64) -> f64; | ||
| 615 | /// Calculates `a - b` | ||
| 616 | 0x04 dsub(a: f64, b: f64) -> f64; | ||
| 617 | /// Calculates `a * b` | ||
| 618 | 0x08 dmul(a: f64, b: f64) -> f64; | ||
| 619 | /// Calculates `a / b` | ||
| 620 | 0x0c ddiv(a: f64, b: f64) -> f64; | ||
| 621 | |||
| 622 | // 0x10 and 0x14 are deprecated | ||
| 623 | |||
| 624 | /// Calculates `sqrt(v)` (or return -Infinity if v is negative) | ||
| 625 | 0x18 dsqrt(v: f64) -> f64; | ||
| 626 | /// Converts an f64 to a signed integer, | ||
| 627 | /// rounding towards -Infinity, and clamping the result to lie within the | ||
| 628 | /// range `-0x80000000` to `0x7FFFFFFF` | ||
| 629 | 0x1c double_to_int(v: f64) -> i32; | ||
| 630 | /// Converts an f64 to an signed fixed point | ||
| 631 | /// integer representation where n specifies the position of the binary | ||
| 632 | /// point in the resulting fixed point representation, e.g. | ||
| 633 | /// `f(0.5f, 16) == 0x8000`. This method rounds towards -Infinity, | ||
| 634 | /// and clamps the resulting integer to lie within the range `0x00000000` to | ||
| 635 | /// `0xFFFFFFFF` | ||
| 636 | 0x20 double_to_fix(v: f64, n: i32) -> i32; | ||
| 637 | /// Converts an f64 to an unsigned integer, | ||
| 638 | /// rounding towards -Infinity, and clamping the result to lie within the | ||
| 639 | /// range `0x00000000` to `0xFFFFFFFF` | ||
| 640 | 0x24 double_to_uint(v: f64) -> u32; | ||
| 641 | /// Converts an f64 to an unsigned fixed point | ||
| 642 | /// integer representation where n specifies the position of the binary | ||
| 643 | /// point in the resulting fixed point representation, e.g. | ||
| 644 | /// `f(0.5f, 16) == 0x8000`. This method rounds towards -Infinity, | ||
| 645 | /// and clamps the resulting integer to lie within the range `0x00000000` to | ||
| 646 | /// `0xFFFFFFFF` | ||
| 647 | 0x28 double_to_ufix(v: f64, n: i32) -> u32; | ||
| 648 | /// Converts a signed integer to the nearest | ||
| 649 | /// double value, rounding to even on tie | ||
| 650 | 0x2c int_to_double(v: i32) -> f64; | ||
| 651 | /// Converts a signed fixed point integer | ||
| 652 | /// representation to the nearest double value, rounding to even on tie. `n` | ||
| 653 | /// specifies the position of the binary point in fixed point, so `f = | ||
| 654 | /// nearest(v/(2^n))` | ||
| 655 | 0x30 fix_to_double(v: i32, n: i32) -> f64; | ||
| 656 | /// Converts an unsigned integer to the nearest | ||
| 657 | /// double value, rounding to even on tie | ||
| 658 | 0x34 uint_to_double(v: u32) -> f64; | ||
| 659 | /// Converts an unsigned fixed point integer | ||
| 660 | /// representation to the nearest double value, rounding to even on tie. `n` | ||
| 661 | /// specifies the position of the binary point in fixed point, so f = | ||
| 662 | /// nearest(v/(2^n)) | ||
| 663 | 0x38 ufix_to_double(v: u32, n: i32) -> f64; | ||
| 664 | /// Calculates the cosine of `angle`. The value | ||
| 665 | /// of `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 666 | 0x3c dcos(angle: f64) -> f64; | ||
| 667 | /// Calculates the sine of `angle`. The value of | ||
| 668 | /// `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 669 | 0x40 dsin(angle: f64) -> f64; | ||
| 670 | /// Calculates the tangent of `angle`. The value | ||
| 671 | /// of `angle` is in radians, and must be in the range `-1024` to `1024` | ||
| 672 | 0x44 dtan(angle: f64) -> f64; | ||
| 673 | |||
| 674 | // 0x48 is deprecated | ||
| 675 | |||
| 676 | /// Calculates the exponential value of `v`, | ||
| 677 | /// i.e. `e ** v` | ||
| 678 | 0x4c dexp(v: f64) -> f64; | ||
| 679 | /// Calculates the natural logarithm of v. If v <= 0 return -Infinity | ||
| 680 | 0x50 dln(v: f64) -> f64; | ||
| 681 | |||
| 682 | // These are only on BootROM v2 or higher | ||
| 683 | |||
| 684 | /// Compares two floating point numbers, returning: | ||
| 685 | /// • 0 if a == b | ||
| 686 | /// • -1 if a < b | ||
| 687 | /// • 1 if a > b | ||
| 688 | 0x54 dcmp(a: f64, b: f64) -> i32; | ||
| 689 | /// Computes the arc tangent of `y/x` using the | ||
| 690 | /// signs of arguments to determine the correct quadrant | ||
| 691 | 0x58 datan2(y: f64, x: f64) -> f64; | ||
| 692 | /// Converts a signed 64-bit integer to the | ||
| 693 | /// nearest double value, rounding to even on tie | ||
| 694 | 0x5c int64_to_double(v: i64) -> f64; | ||
| 695 | /// Converts a signed fixed point 64-bit integer | ||
| 696 | /// representation to the nearest double value, rounding to even on tie. `n` | ||
| 697 | /// specifies the position of the binary point in fixed point, so `f = | ||
| 698 | /// nearest(v/(2^n))` | ||
| 699 | 0x60 fix64_to_doubl(v: i64, n: i32) -> f64; | ||
| 700 | /// Converts an unsigned 64-bit integer to the | ||
| 701 | /// nearest double value, rounding to even on tie | ||
| 702 | 0x64 uint64_to_double(v: u64) -> f64; | ||
| 703 | /// Converts an unsigned fixed point 64-bit | ||
| 704 | /// integer representation to the nearest double value, rounding to even on | ||
| 705 | /// tie. `n` specifies the position of the binary point in fixed point, so | ||
| 706 | /// `f = nearest(v/(2^n))` | ||
| 707 | 0x68 ufix64_to_double(v: u64, n: i32) -> f64; | ||
| 708 | /// Convert an f64 to a signed 64-bit integer, rounding towards -Infinity, | ||
| 709 | /// and clamping the result to lie within the range `-0x8000000000000000` to | ||
| 710 | /// `0x7FFFFFFFFFFFFFFF` | ||
| 711 | 0x6c double_to_int64(v: f64) -> i64; | ||
| 712 | /// Converts an f64 to a signed fixed point | ||
| 713 | /// 64-bit integer representation where n specifies the position of the | ||
| 714 | /// binary point in the resulting fixed point representation - e.g. `f(0.5f, | ||
| 715 | /// 16) == 0x8000`. This method rounds towards -Infinity, and clamps the | ||
| 716 | /// resulting integer to lie within the range `-0x8000000000000000` to | ||
| 717 | /// `0x7FFFFFFFFFFFFFFF` | ||
| 718 | 0x70 double_to_fix64(v: f64, n: i32) -> i64; | ||
| 719 | /// Converts an f64 to an unsigned 64-bit | ||
| 720 | /// integer, rounding towards -Infinity, and clamping the result to lie | ||
| 721 | /// within the range `0x0000000000000000` to `0xFFFFFFFFFFFFFFFF` | ||
| 722 | 0x74 double_to_uint64(v: f64) -> u64; | ||
| 723 | /// Converts an f64 to an unsigned fixed point | ||
| 724 | /// 64-bit integer representation where n specifies the position of the | ||
| 725 | /// binary point in the resulting fixed point representation, e.g. `f(0.5f, | ||
| 726 | /// 16) == 0x8000`. This method rounds towards -Infinity, and clamps the | ||
| 727 | /// resulting integer to lie within the range `0x0000000000000000` to | ||
| 728 | /// `0xFFFFFFFFFFFFFFFF` | ||
| 729 | 0x78 double_to_ufix64(v: f64, n: i32) -> u64; | ||
| 730 | /// Converts an f64 to an f32 | ||
| 731 | 0x7c double_to_float(v: f64) -> f32; | ||
| 732 | } | ||
| 733 | } | ||
diff --git a/embassy-rp/src/rtc/datetime_chrono.rs b/embassy-rp/src/rtc/datetime_chrono.rs new file mode 100644 index 000000000..b3c78dd47 --- /dev/null +++ b/embassy-rp/src/rtc/datetime_chrono.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | use chrono::{Datelike, Timelike}; | ||
| 2 | |||
| 3 | use crate::pac::rtc::regs::{Rtc0, Rtc1, Setup0, Setup1}; | ||
| 4 | |||
| 5 | /// Alias for [`chrono::NaiveDateTime`] | ||
| 6 | pub type DateTime = chrono::NaiveDateTime; | ||
| 7 | /// Alias for [`chrono::Weekday`] | ||
| 8 | pub type DayOfWeek = chrono::Weekday; | ||
| 9 | |||
| 10 | /// Errors regarding the [`DateTime`] and [`DateTimeFilter`] structs. | ||
| 11 | /// | ||
| 12 | /// [`DateTimeFilter`]: struct.DateTimeFilter.html | ||
| 13 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
| 14 | pub enum Error { | ||
| 15 | /// The [DateTime] has an invalid year. The year must be between 0 and 4095. | ||
| 16 | InvalidYear, | ||
| 17 | /// The [DateTime] contains an invalid date. | ||
| 18 | InvalidDate, | ||
| 19 | /// The [DateTime] contains an invalid time. | ||
| 20 | InvalidTime, | ||
| 21 | } | ||
| 22 | |||
| 23 | pub(super) fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 { | ||
| 24 | dotw.num_days_from_sunday() as u8 | ||
| 25 | } | ||
| 26 | |||
| 27 | pub(crate) fn validate_datetime(dt: &DateTime) -> Result<(), Error> { | ||
| 28 | if dt.year() < 0 || dt.year() > 4095 { | ||
| 29 | // rp2040 can't hold these years | ||
| 30 | Err(Error::InvalidYear) | ||
| 31 | } else { | ||
| 32 | // The rest of the chrono date is assumed to be valid | ||
| 33 | Ok(()) | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | pub(super) fn write_setup_0(dt: &DateTime, w: &mut Setup0) { | ||
| 38 | w.set_year(dt.year() as u16); | ||
| 39 | w.set_month(dt.month() as u8); | ||
| 40 | w.set_day(dt.day() as u8); | ||
| 41 | } | ||
| 42 | |||
| 43 | pub(super) fn write_setup_1(dt: &DateTime, w: &mut Setup1) { | ||
| 44 | w.set_dotw(dt.weekday().num_days_from_sunday() as u8); | ||
| 45 | w.set_hour(dt.hour() as u8); | ||
| 46 | w.set_min(dt.minute() as u8); | ||
| 47 | w.set_sec(dt.second() as u8); | ||
| 48 | } | ||
| 49 | |||
| 50 | pub(super) fn datetime_from_registers(rtc_0: Rtc0, rtc_1: Rtc1) -> Result<DateTime, Error> { | ||
| 51 | let year = rtc_1.year() as i32; | ||
| 52 | let month = rtc_1.month() as u32; | ||
| 53 | let day = rtc_1.day() as u32; | ||
| 54 | |||
| 55 | let hour = rtc_0.hour() as u32; | ||
| 56 | let minute = rtc_0.min() as u32; | ||
| 57 | let second = rtc_0.sec() as u32; | ||
| 58 | |||
| 59 | let date = chrono::NaiveDate::from_ymd_opt(year, month, day).ok_or(Error::InvalidDate)?; | ||
| 60 | let time = chrono::NaiveTime::from_hms_opt(hour, minute, second).ok_or(Error::InvalidTime)?; | ||
| 61 | Ok(DateTime::new(date, time)) | ||
| 62 | } | ||
diff --git a/embassy-rp/src/rtc/datetime_no_deps.rs b/embassy-rp/src/rtc/datetime_no_deps.rs new file mode 100644 index 000000000..92770e984 --- /dev/null +++ b/embassy-rp/src/rtc/datetime_no_deps.rs | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | use crate::pac::rtc::regs::{Rtc0, Rtc1, Setup0, Setup1}; | ||
| 2 | |||
| 3 | /// Errors regarding the [`DateTime`] and [`DateTimeFilter`] structs. | ||
| 4 | /// | ||
| 5 | /// [`DateTimeFilter`]: struct.DateTimeFilter.html | ||
| 6 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
| 7 | pub enum Error { | ||
| 8 | /// The [DateTime] contains an invalid year value. Must be between `0..=4095`. | ||
| 9 | InvalidYear, | ||
| 10 | /// The [DateTime] contains an invalid month value. Must be between `1..=12`. | ||
| 11 | InvalidMonth, | ||
| 12 | /// The [DateTime] contains an invalid day value. Must be between `1..=31`. | ||
| 13 | InvalidDay, | ||
| 14 | /// The [DateTime] contains an invalid day of week. Must be between `0..=6` where 0 is Sunday. | ||
| 15 | InvalidDayOfWeek( | ||
| 16 | /// The value of the DayOfWeek that was given. | ||
| 17 | u8, | ||
| 18 | ), | ||
| 19 | /// The [DateTime] contains an invalid hour value. Must be between `0..=23`. | ||
| 20 | InvalidHour, | ||
| 21 | /// The [DateTime] contains an invalid minute value. Must be between `0..=59`. | ||
| 22 | InvalidMinute, | ||
| 23 | /// The [DateTime] contains an invalid second value. Must be between `0..=59`. | ||
| 24 | InvalidSecond, | ||
| 25 | } | ||
| 26 | |||
| 27 | /// Structure containing date and time information | ||
| 28 | pub struct DateTime { | ||
| 29 | /// 0..4095 | ||
| 30 | pub year: u16, | ||
| 31 | /// 1..12, 1 is January | ||
| 32 | pub month: u8, | ||
| 33 | /// 1..28,29,30,31 depending on month | ||
| 34 | pub day: u8, | ||
| 35 | /// | ||
| 36 | pub day_of_week: DayOfWeek, | ||
| 37 | /// 0..23 | ||
| 38 | pub hour: u8, | ||
| 39 | /// 0..59 | ||
| 40 | pub minute: u8, | ||
| 41 | /// 0..59 | ||
| 42 | pub second: u8, | ||
| 43 | } | ||
| 44 | |||
| 45 | /// A day of the week | ||
| 46 | #[repr(u8)] | ||
| 47 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] | ||
| 48 | #[allow(missing_docs)] | ||
| 49 | pub enum DayOfWeek { | ||
| 50 | Sunday = 0, | ||
| 51 | Monday = 1, | ||
| 52 | Tuesday = 2, | ||
| 53 | Wednesday = 3, | ||
| 54 | Thursday = 4, | ||
| 55 | Friday = 5, | ||
| 56 | Saturday = 6, | ||
| 57 | } | ||
| 58 | |||
| 59 | fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> { | ||
| 60 | Ok(match v { | ||
| 61 | 0 => DayOfWeek::Sunday, | ||
| 62 | 1 => DayOfWeek::Monday, | ||
| 63 | 2 => DayOfWeek::Tuesday, | ||
| 64 | 3 => DayOfWeek::Wednesday, | ||
| 65 | 4 => DayOfWeek::Thursday, | ||
| 66 | 5 => DayOfWeek::Friday, | ||
| 67 | 6 => DayOfWeek::Saturday, | ||
| 68 | x => return Err(Error::InvalidDayOfWeek(x)), | ||
| 69 | }) | ||
| 70 | } | ||
| 71 | |||
| 72 | pub(super) fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 { | ||
| 73 | dotw as u8 | ||
| 74 | } | ||
| 75 | |||
| 76 | pub(super) fn validate_datetime(dt: &DateTime) -> Result<(), Error> { | ||
| 77 | if dt.year > 4095 { | ||
| 78 | Err(Error::InvalidYear) | ||
| 79 | } else if dt.month < 1 || dt.month > 12 { | ||
| 80 | Err(Error::InvalidMonth) | ||
| 81 | } else if dt.day < 1 || dt.day > 31 { | ||
| 82 | Err(Error::InvalidDay) | ||
| 83 | } else if dt.hour > 23 { | ||
| 84 | Err(Error::InvalidHour) | ||
| 85 | } else if dt.minute > 59 { | ||
| 86 | Err(Error::InvalidMinute) | ||
| 87 | } else if dt.second > 59 { | ||
| 88 | Err(Error::InvalidSecond) | ||
| 89 | } else { | ||
| 90 | Ok(()) | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | pub(super) fn write_setup_0(dt: &DateTime, w: &mut Setup0) { | ||
| 95 | w.set_year(dt.year); | ||
| 96 | w.set_month(dt.month); | ||
| 97 | w.set_day(dt.day); | ||
| 98 | } | ||
| 99 | |||
| 100 | pub(super) fn write_setup_1(dt: &DateTime, w: &mut Setup1) { | ||
| 101 | w.set_dotw(dt.day_of_week as u8); | ||
| 102 | w.set_hour(dt.hour); | ||
| 103 | w.set_min(dt.minute); | ||
| 104 | w.set_sec(dt.second); | ||
| 105 | } | ||
| 106 | |||
| 107 | pub(super) fn datetime_from_registers(rtc_0: Rtc0, rtc_1: Rtc1) -> Result<DateTime, Error> { | ||
| 108 | let year = rtc_1.year(); | ||
| 109 | let month = rtc_1.month(); | ||
| 110 | let day = rtc_1.day(); | ||
| 111 | |||
| 112 | let day_of_week = rtc_0.dotw(); | ||
| 113 | let hour = rtc_0.hour(); | ||
| 114 | let minute = rtc_0.min(); | ||
| 115 | let second = rtc_0.sec(); | ||
| 116 | |||
| 117 | let day_of_week = day_of_week_from_u8(day_of_week)?; | ||
| 118 | Ok(DateTime { | ||
| 119 | year, | ||
| 120 | month, | ||
| 121 | day, | ||
| 122 | day_of_week, | ||
| 123 | hour, | ||
| 124 | minute, | ||
| 125 | second, | ||
| 126 | }) | ||
| 127 | } | ||
diff --git a/embassy-rp/src/rtc/filter.rs b/embassy-rp/src/rtc/filter.rs new file mode 100644 index 000000000..d4a3bab2f --- /dev/null +++ b/embassy-rp/src/rtc/filter.rs | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | use super::DayOfWeek; | ||
| 2 | use crate::pac::rtc::regs::{IrqSetup0, IrqSetup1}; | ||
| 3 | |||
| 4 | /// A filter used for [`RealTimeClock::schedule_alarm`]. | ||
| 5 | /// | ||
| 6 | /// [`RealTimeClock::schedule_alarm`]: struct.RealTimeClock.html#method.schedule_alarm | ||
| 7 | #[derive(Default)] | ||
| 8 | pub struct DateTimeFilter { | ||
| 9 | /// The year that this alarm should trigger on, `None` if the RTC alarm should not trigger on a year value. | ||
| 10 | pub year: Option<u16>, | ||
| 11 | /// The month that this alarm should trigger on, `None` if the RTC alarm should not trigger on a month value. | ||
| 12 | pub month: Option<u8>, | ||
| 13 | /// The day that this alarm should trigger on, `None` if the RTC alarm should not trigger on a day value. | ||
| 14 | pub day: Option<u8>, | ||
| 15 | /// The day of week that this alarm should trigger on, `None` if the RTC alarm should not trigger on a day of week value. | ||
| 16 | pub day_of_week: Option<DayOfWeek>, | ||
| 17 | /// The hour that this alarm should trigger on, `None` if the RTC alarm should not trigger on a hour value. | ||
| 18 | pub hour: Option<u8>, | ||
| 19 | /// The minute that this alarm should trigger on, `None` if the RTC alarm should not trigger on a minute value. | ||
| 20 | pub minute: Option<u8>, | ||
| 21 | /// The second that this alarm should trigger on, `None` if the RTC alarm should not trigger on a second value. | ||
| 22 | pub second: Option<u8>, | ||
| 23 | } | ||
| 24 | |||
| 25 | impl DateTimeFilter { | ||
| 26 | /// Set a filter on the given year | ||
| 27 | pub fn year(mut self, year: u16) -> Self { | ||
| 28 | self.year = Some(year); | ||
| 29 | self | ||
| 30 | } | ||
| 31 | /// Set a filter on the given month | ||
| 32 | pub fn month(mut self, month: u8) -> Self { | ||
| 33 | self.month = Some(month); | ||
| 34 | self | ||
| 35 | } | ||
| 36 | /// Set a filter on the given day | ||
| 37 | pub fn day(mut self, day: u8) -> Self { | ||
| 38 | self.day = Some(day); | ||
| 39 | self | ||
| 40 | } | ||
| 41 | /// Set a filter on the given day of the week | ||
| 42 | pub fn day_of_week(mut self, day_of_week: DayOfWeek) -> Self { | ||
| 43 | self.day_of_week = Some(day_of_week); | ||
| 44 | self | ||
| 45 | } | ||
| 46 | /// Set a filter on the given hour | ||
| 47 | pub fn hour(mut self, hour: u8) -> Self { | ||
| 48 | self.hour = Some(hour); | ||
| 49 | self | ||
| 50 | } | ||
| 51 | /// Set a filter on the given minute | ||
| 52 | pub fn minute(mut self, minute: u8) -> Self { | ||
| 53 | self.minute = Some(minute); | ||
| 54 | self | ||
| 55 | } | ||
| 56 | /// Set a filter on the given second | ||
| 57 | pub fn second(mut self, second: u8) -> Self { | ||
| 58 | self.second = Some(second); | ||
| 59 | self | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | // register helper functions | ||
| 64 | impl DateTimeFilter { | ||
| 65 | pub(super) fn write_setup_0(&self, w: &mut IrqSetup0) { | ||
| 66 | if let Some(year) = self.year { | ||
| 67 | w.set_year_ena(true); | ||
| 68 | |||
| 69 | w.set_year(year); | ||
| 70 | } | ||
| 71 | if let Some(month) = self.month { | ||
| 72 | w.set_month_ena(true); | ||
| 73 | w.set_month(month); | ||
| 74 | } | ||
| 75 | if let Some(day) = self.day { | ||
| 76 | w.set_day_ena(true); | ||
| 77 | w.set_day(day); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | pub(super) fn write_setup_1(&self, w: &mut IrqSetup1) { | ||
| 81 | if let Some(day_of_week) = self.day_of_week { | ||
| 82 | w.set_dotw_ena(true); | ||
| 83 | let bits = super::datetime::day_of_week_to_u8(day_of_week); | ||
| 84 | |||
| 85 | w.set_dotw(bits); | ||
| 86 | } | ||
| 87 | if let Some(hour) = self.hour { | ||
| 88 | w.set_hour_ena(true); | ||
| 89 | w.set_hour(hour); | ||
| 90 | } | ||
| 91 | if let Some(minute) = self.minute { | ||
| 92 | w.set_min_ena(true); | ||
| 93 | w.set_min(minute); | ||
| 94 | } | ||
| 95 | if let Some(second) = self.second { | ||
| 96 | w.set_sec_ena(true); | ||
| 97 | w.set_sec(second); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs new file mode 100644 index 000000000..7f3bbbe73 --- /dev/null +++ b/embassy-rp/src/rtc/mod.rs | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | mod filter; | ||
| 2 | |||
| 3 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | ||
| 4 | |||
| 5 | pub use self::filter::DateTimeFilter; | ||
| 6 | |||
| 7 | #[cfg_attr(feature = "chrono", path = "datetime_chrono.rs")] | ||
| 8 | #[cfg_attr(not(feature = "chrono"), path = "datetime_no_deps.rs")] | ||
| 9 | mod datetime; | ||
| 10 | |||
| 11 | pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; | ||
| 12 | use crate::clocks::clk_rtc_freq; | ||
| 13 | |||
| 14 | /// A reference to the real time clock of the system | ||
| 15 | pub struct RealTimeClock<'d, T: Instance> { | ||
| 16 | inner: PeripheralRef<'d, T>, | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<'d, T: Instance> RealTimeClock<'d, T> { | ||
| 20 | /// Create a new instance of the real time clock, with the given date as an initial value. | ||
| 21 | /// | ||
| 22 | /// # Errors | ||
| 23 | /// | ||
| 24 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. | ||
| 25 | pub fn new(inner: impl Peripheral<P = T> + 'd, initial_date: DateTime) -> Result<Self, RtcError> { | ||
| 26 | into_ref!(inner); | ||
| 27 | |||
| 28 | // Set the RTC divider | ||
| 29 | unsafe { | ||
| 30 | inner | ||
| 31 | .regs() | ||
| 32 | .clkdiv_m1() | ||
| 33 | .write(|w| w.set_clkdiv_m1(clk_rtc_freq() as u16 - 1)) | ||
| 34 | }; | ||
| 35 | |||
| 36 | let mut result = Self { inner }; | ||
| 37 | result.set_leap_year_check(true); // should be on by default, make sure this is the case. | ||
| 38 | result.set_datetime(initial_date)?; | ||
| 39 | Ok(result) | ||
| 40 | } | ||
| 41 | |||
| 42 | /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. | ||
| 43 | /// | ||
| 44 | /// Leap year checking is enabled by default. | ||
| 45 | pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { | ||
| 46 | unsafe { | ||
| 47 | self.inner | ||
| 48 | .regs() | ||
| 49 | .ctrl() | ||
| 50 | .modify(|w| w.set_force_notleapyear(!leap_year_check_enabled)) | ||
| 51 | }; | ||
| 52 | } | ||
| 53 | |||
| 54 | /// Checks to see if this RealTimeClock is running | ||
| 55 | pub fn is_running(&self) -> bool { | ||
| 56 | unsafe { self.inner.regs().ctrl().read().rtc_active() } | ||
| 57 | } | ||
| 58 | |||
| 59 | /// Set the datetime to a new value. | ||
| 60 | /// | ||
| 61 | /// # Errors | ||
| 62 | /// | ||
| 63 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. | ||
| 64 | pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { | ||
| 65 | self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?; | ||
| 66 | |||
| 67 | // disable RTC while we configure it | ||
| 68 | unsafe { | ||
| 69 | self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); | ||
| 70 | while self.inner.regs().ctrl().read().rtc_active() { | ||
| 71 | core::hint::spin_loop(); | ||
| 72 | } | ||
| 73 | |||
| 74 | self.inner.regs().setup_0().write(|w| { | ||
| 75 | self::datetime::write_setup_0(&t, w); | ||
| 76 | }); | ||
| 77 | self.inner.regs().setup_1().write(|w| { | ||
| 78 | self::datetime::write_setup_1(&t, w); | ||
| 79 | }); | ||
| 80 | |||
| 81 | // Load the new datetime and re-enable RTC | ||
| 82 | self.inner.regs().ctrl().write(|w| w.set_load(true)); | ||
| 83 | self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); | ||
| 84 | while !self.inner.regs().ctrl().read().rtc_active() { | ||
| 85 | core::hint::spin_loop(); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | Ok(()) | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Return the current datetime. | ||
| 92 | /// | ||
| 93 | /// # Errors | ||
| 94 | /// | ||
| 95 | /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. | ||
| 96 | pub fn now(&self) -> Result<DateTime, RtcError> { | ||
| 97 | if !self.is_running() { | ||
| 98 | return Err(RtcError::NotRunning); | ||
| 99 | } | ||
| 100 | |||
| 101 | let rtc_0 = unsafe { self.inner.regs().rtc_0().read() }; | ||
| 102 | let rtc_1 = unsafe { self.inner.regs().rtc_1().read() }; | ||
| 103 | |||
| 104 | self::datetime::datetime_from_registers(rtc_0, rtc_1).map_err(RtcError::InvalidDateTime) | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Disable the alarm that was scheduled with [`schedule_alarm`]. | ||
| 108 | /// | ||
| 109 | /// [`schedule_alarm`]: #method.schedule_alarm | ||
| 110 | pub fn disable_alarm(&mut self) { | ||
| 111 | unsafe { | ||
| 112 | self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false)); | ||
| 113 | |||
| 114 | while self.inner.regs().irq_setup_0().read().match_active() { | ||
| 115 | core::hint::spin_loop(); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | /// Schedule an alarm. The `filter` determines at which point in time this alarm is set. | ||
| 121 | /// | ||
| 122 | /// Keep in mind that the filter only triggers on the specified time. If you want to schedule this alarm every minute, you have to call: | ||
| 123 | /// ```no_run | ||
| 124 | /// # #[cfg(feature = "chrono")] | ||
| 125 | /// # fn main() { } | ||
| 126 | /// # #[cfg(not(feature = "chrono"))] | ||
| 127 | /// # fn main() { | ||
| 128 | /// # use embassy_rp::rtc::{RealTimeClock, DateTimeFilter}; | ||
| 129 | /// # let mut real_time_clock: RealTimeClock = unsafe { core::mem::zeroed() }; | ||
| 130 | /// let now = real_time_clock.now().unwrap(); | ||
| 131 | /// real_time_clock.schedule_alarm( | ||
| 132 | /// DateTimeFilter::default() | ||
| 133 | /// .minute(if now.minute == 59 { 0 } else { now.minute + 1 }) | ||
| 134 | /// ); | ||
| 135 | /// # } | ||
| 136 | /// ``` | ||
| 137 | pub fn schedule_alarm(&mut self, filter: DateTimeFilter) { | ||
| 138 | self.disable_alarm(); | ||
| 139 | |||
| 140 | unsafe { | ||
| 141 | self.inner.regs().irq_setup_0().write(|w| { | ||
| 142 | filter.write_setup_0(w); | ||
| 143 | }); | ||
| 144 | self.inner.regs().irq_setup_1().write(|w| { | ||
| 145 | filter.write_setup_1(w); | ||
| 146 | }); | ||
| 147 | |||
| 148 | // Set the enable bit and check if it is set | ||
| 149 | self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); | ||
| 150 | while !self.inner.regs().irq_setup_0().read().match_active() { | ||
| 151 | core::hint::spin_loop(); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | /// Clear the interrupt. This should be called every time the `RTC_IRQ` interrupt is triggered, | ||
| 157 | /// or the next [`schedule_alarm`] will never fire. | ||
| 158 | /// | ||
| 159 | /// [`schedule_alarm`]: #method.schedule_alarm | ||
| 160 | pub fn clear_interrupt(&mut self) { | ||
| 161 | self.disable_alarm(); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /// Errors that can occur on methods on [RtcClock] | ||
| 166 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
| 167 | pub enum RtcError { | ||
| 168 | /// An invalid DateTime was given or stored on the hardware. | ||
| 169 | InvalidDateTime(DateTimeError), | ||
| 170 | |||
| 171 | /// The RTC clock is not running | ||
| 172 | NotRunning, | ||
| 173 | } | ||
| 174 | |||
| 175 | mod sealed { | ||
| 176 | pub trait Instance { | ||
| 177 | fn regs(&self) -> crate::pac::rtc::Rtc; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | pub trait Instance: sealed::Instance {} | ||
| 182 | |||
| 183 | impl sealed::Instance for crate::peripherals::RTC { | ||
| 184 | fn regs(&self) -> crate::pac::rtc::Rtc { | ||
| 185 | crate::pac::RTC | ||
| 186 | } | ||
| 187 | } | ||
| 188 | impl Instance for crate::peripherals::RTC {} | ||
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 74f0b04de..03293e064 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | 2 | ||
| 3 | use embassy_embedded_hal::SetConfig; | 3 | use embassy_embedded_hal::SetConfig; |
| 4 | use embassy_futures::join::join; | ||
| 4 | use embassy_hal_common::{into_ref, PeripheralRef}; | 5 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 5 | pub use embedded_hal_02::spi::{Phase, Polarity}; | 6 | pub use embedded_hal_02::spi::{Phase, Polarity}; |
| 6 | use futures::future::join; | ||
| 7 | 7 | ||
| 8 | use crate::dma::{AnyChannel, Channel}; | 8 | use crate::dma::{AnyChannel, Channel}; |
| 9 | use crate::gpio::sealed::Pin as _; | 9 | use crate::gpio::sealed::Pin as _; |
| @@ -325,30 +325,52 @@ impl<'d, T: Instance> Spi<'d, T, Async> { | |||
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 327 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 328 | let ch = self.tx_dma.as_mut().unwrap(); | 328 | let tx_ch = self.tx_dma.as_mut().unwrap(); |
| 329 | let transfer = unsafe { | 329 | let tx_transfer = unsafe { |
| 330 | self.inner.regs().dmacr().modify(|reg| { | 330 | self.inner.regs().dmacr().modify(|reg| { |
| 331 | reg.set_txdmae(true); | 331 | reg.set_txdmae(true); |
| 332 | }); | 332 | }); |
| 333 | // If we don't assign future to a variable, the data register pointer | 333 | // If we don't assign future to a variable, the data register pointer |
| 334 | // is held across an await and makes the future non-Send. | 334 | // is held across an await and makes the future non-Send. |
| 335 | crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | 335 | crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) |
| 336 | }; | 336 | }; |
| 337 | transfer.await; | 337 | tx_transfer.await; |
| 338 | |||
| 339 | let p = self.inner.regs(); | ||
| 340 | unsafe { | ||
| 341 | while p.sr().read().bsy() {} | ||
| 342 | |||
| 343 | // clear RX FIFO contents to prevent stale reads | ||
| 344 | while p.sr().read().rne() { | ||
| 345 | let _: u16 = p.dr().read().data(); | ||
| 346 | } | ||
| 347 | // clear RX overrun interrupt | ||
| 348 | p.icr().write(|w| w.set_roric(true)); | ||
| 349 | } | ||
| 350 | |||
| 338 | Ok(()) | 351 | Ok(()) |
| 339 | } | 352 | } |
| 340 | 353 | ||
| 341 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | 354 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 342 | let ch = self.rx_dma.as_mut().unwrap(); | 355 | unsafe { |
| 343 | let transfer = unsafe { | 356 | self.inner.regs().dmacr().write(|reg| { |
| 344 | self.inner.regs().dmacr().modify(|reg| { | ||
| 345 | reg.set_rxdmae(true); | 357 | reg.set_rxdmae(true); |
| 346 | }); | 358 | reg.set_txdmae(true); |
| 359 | }) | ||
| 360 | }; | ||
| 361 | let tx_ch = self.tx_dma.as_mut().unwrap(); | ||
| 362 | let tx_transfer = unsafe { | ||
| 347 | // If we don't assign future to a variable, the data register pointer | 363 | // If we don't assign future to a variable, the data register pointer |
| 348 | // is held across an await and makes the future non-Send. | 364 | // is held across an await and makes the future non-Send. |
| 349 | crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) | 365 | crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) |
| 350 | }; | 366 | }; |
| 351 | transfer.await; | 367 | let rx_ch = self.rx_dma.as_mut().unwrap(); |
| 368 | let rx_transfer = unsafe { | ||
| 369 | // If we don't assign future to a variable, the data register pointer | ||
| 370 | // is held across an await and makes the future non-Send. | ||
| 371 | crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) | ||
| 372 | }; | ||
| 373 | join(tx_transfer, rx_transfer).await; | ||
| 352 | Ok(()) | 374 | Ok(()) |
| 353 | } | 375 | } |
| 354 | 376 | ||
| @@ -364,20 +386,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> { | |||
| 364 | let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); | 386 | let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); |
| 365 | let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); | 387 | let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); |
| 366 | assert_eq!(from_len, to_len); | 388 | assert_eq!(from_len, to_len); |
| 389 | unsafe { | ||
| 390 | self.inner.regs().dmacr().write(|reg| { | ||
| 391 | reg.set_rxdmae(true); | ||
| 392 | reg.set_txdmae(true); | ||
| 393 | }) | ||
| 394 | }; | ||
| 367 | let tx_ch = self.tx_dma.as_mut().unwrap(); | 395 | let tx_ch = self.tx_dma.as_mut().unwrap(); |
| 368 | let tx_transfer = unsafe { | 396 | let tx_transfer = unsafe { |
| 369 | self.inner.regs().dmacr().modify(|reg| { | ||
| 370 | reg.set_txdmae(true); | ||
| 371 | }); | ||
| 372 | // If we don't assign future to a variable, the data register pointer | 397 | // If we don't assign future to a variable, the data register pointer |
| 373 | // is held across an await and makes the future non-Send. | 398 | // is held across an await and makes the future non-Send. |
| 374 | crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | 399 | crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) |
| 375 | }; | 400 | }; |
| 376 | let rx_ch = self.rx_dma.as_mut().unwrap(); | 401 | let rx_ch = self.rx_dma.as_mut().unwrap(); |
| 377 | let rx_transfer = unsafe { | 402 | let rx_transfer = unsafe { |
| 378 | self.inner.regs().dmacr().modify(|reg| { | ||
| 379 | reg.set_rxdmae(true); | ||
| 380 | }); | ||
| 381 | // If we don't assign future to a variable, the data register pointer | 403 | // If we don't assign future to a variable, the data register pointer |
| 382 | // is held across an await and makes the future non-Send. | 404 | // is held across an await and makes the future non-Send. |
| 383 | crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) | 405 | crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) |
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 82eafdefd..ce473b21d 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::future::{poll_fn, Future}; | ||
| 1 | use core::marker::PhantomData; | 2 | use core::marker::PhantomData; |
| 2 | use core::slice; | 3 | use core::slice; |
| 3 | use core::sync::atomic::Ordering; | 4 | use core::sync::atomic::Ordering; |
| @@ -6,10 +7,9 @@ use core::task::Poll; | |||
| 6 | use atomic_polyfill::compiler_fence; | 7 | use atomic_polyfill::compiler_fence; |
| 7 | use embassy_hal_common::into_ref; | 8 | use embassy_hal_common::into_ref; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; | 10 | use embassy_usb::driver::{ |
| 10 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; | 11 | self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, |
| 11 | use futures::future::poll_fn; | 12 | }; |
| 12 | use futures::Future; | ||
| 13 | 13 | ||
| 14 | use crate::interrupt::{Interrupt, InterruptExt}; | 14 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 15 | use crate::{pac, peripherals, Peripheral, RegExt}; | 15 | use crate::{pac, peripherals, Peripheral, RegExt}; |
| @@ -205,8 +205,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 205 | ); | 205 | ); |
| 206 | 206 | ||
| 207 | let alloc = match D::dir() { | 207 | let alloc = match D::dir() { |
| 208 | UsbDirection::Out => &mut self.ep_out, | 208 | Direction::Out => &mut self.ep_out, |
| 209 | UsbDirection::In => &mut self.ep_in, | 209 | Direction::In => &mut self.ep_in, |
| 210 | }; | 210 | }; |
| 211 | 211 | ||
| 212 | let index = alloc.iter_mut().enumerate().find(|(i, ep)| { | 212 | let index = alloc.iter_mut().enumerate().find(|(i, ep)| { |
| @@ -255,7 +255,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 255 | }; | 255 | }; |
| 256 | 256 | ||
| 257 | match D::dir() { | 257 | match D::dir() { |
| 258 | UsbDirection::Out => unsafe { | 258 | Direction::Out => unsafe { |
| 259 | T::dpram().ep_out_control(index - 1).write(|w| { | 259 | T::dpram().ep_out_control(index - 1).write(|w| { |
| 260 | w.set_enable(false); | 260 | w.set_enable(false); |
| 261 | w.set_buffer_address(addr); | 261 | w.set_buffer_address(addr); |
| @@ -263,7 +263,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 263 | w.set_endpoint_type(ep_type_reg); | 263 | w.set_endpoint_type(ep_type_reg); |
| 264 | }) | 264 | }) |
| 265 | }, | 265 | }, |
| 266 | UsbDirection::In => unsafe { | 266 | Direction::In => unsafe { |
| 267 | T::dpram().ep_in_control(index - 1).write(|w| { | 267 | T::dpram().ep_in_control(index - 1).write(|w| { |
| 268 | w.set_enable(false); | 268 | w.set_enable(false); |
| 269 | w.set_buffer_address(addr); | 269 | w.set_buffer_address(addr); |
| @@ -430,14 +430,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 430 | 430 | ||
| 431 | let n = ep_addr.index(); | 431 | let n = ep_addr.index(); |
| 432 | match ep_addr.direction() { | 432 | match ep_addr.direction() { |
| 433 | UsbDirection::In => unsafe { | 433 | Direction::In => unsafe { |
| 434 | T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); | 434 | T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); |
| 435 | T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { | 435 | T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { |
| 436 | w.set_pid(0, true); // first packet is DATA0, but PID is flipped before | 436 | w.set_pid(0, true); // first packet is DATA0, but PID is flipped before |
| 437 | }); | 437 | }); |
| 438 | EP_IN_WAKERS[n].wake(); | 438 | EP_IN_WAKERS[n].wake(); |
| 439 | }, | 439 | }, |
| 440 | UsbDirection::Out => unsafe { | 440 | Direction::Out => unsafe { |
| 441 | T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); | 441 | T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); |
| 442 | 442 | ||
| 443 | T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { | 443 | T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { |
| @@ -475,14 +475,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 475 | } | 475 | } |
| 476 | 476 | ||
| 477 | trait Dir { | 477 | trait Dir { |
| 478 | fn dir() -> UsbDirection; | 478 | fn dir() -> Direction; |
| 479 | fn waker(i: usize) -> &'static AtomicWaker; | 479 | fn waker(i: usize) -> &'static AtomicWaker; |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | pub enum In {} | 482 | pub enum In {} |
| 483 | impl Dir for In { | 483 | impl Dir for In { |
| 484 | fn dir() -> UsbDirection { | 484 | fn dir() -> Direction { |
| 485 | UsbDirection::In | 485 | Direction::In |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | #[inline] | 488 | #[inline] |
| @@ -493,8 +493,8 @@ impl Dir for In { | |||
| 493 | 493 | ||
| 494 | pub enum Out {} | 494 | pub enum Out {} |
| 495 | impl Dir for Out { | 495 | impl Dir for Out { |
| 496 | fn dir() -> UsbDirection { | 496 | fn dir() -> Direction { |
| 497 | UsbDirection::Out | 497 | Direction::Out |
| 498 | } | 498 | } |
| 499 | 499 | ||
| 500 | #[inline] | 500 | #[inline] |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b4c19f32e..484496f24 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -34,6 +34,7 @@ flavors = [ | |||
| 34 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | 34 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } |
| 35 | embassy-executor = { version = "0.1.0", path = "../embassy-executor" } | 35 | embassy-executor = { version = "0.1.0", path = "../embassy-executor" } |
| 36 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } | 36 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } |
| 37 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | ||
| 37 | embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} | 38 | embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} |
| 38 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } | 39 | embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } |
| 39 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 40 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index c0bd44e0f..bd92b35a0 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs | |||
| @@ -12,6 +12,7 @@ pub struct Can<'d, T: Instance> { | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | impl<'d, T: Instance> Can<'d, T> { | 14 | impl<'d, T: Instance> Can<'d, T> { |
| 15 | /// Creates a new Bxcan instance, blocking for 11 recessive bits to sync with the CAN bus. | ||
| 15 | pub fn new( | 16 | pub fn new( |
| 16 | peri: impl Peripheral<P = T> + 'd, | 17 | peri: impl Peripheral<P = T> + 'd, |
| 17 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 18 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| @@ -31,6 +32,28 @@ impl<'d, T: Instance> Can<'d, T> { | |||
| 31 | can: bxcan::Can::builder(BxcanInstance(peri)).enable(), | 32 | can: bxcan::Can::builder(BxcanInstance(peri)).enable(), |
| 32 | } | 33 | } |
| 33 | } | 34 | } |
| 35 | |||
| 36 | /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. | ||
| 37 | /// You must call [Can::enable_non_blocking] to use the peripheral. | ||
| 38 | pub fn new_disabled( | ||
| 39 | peri: impl Peripheral<P = T> + 'd, | ||
| 40 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 41 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 42 | ) -> Self { | ||
| 43 | into_ref!(peri, rx, tx); | ||
| 44 | |||
| 45 | unsafe { | ||
| 46 | rx.set_as_af(rx.af_num(), AFType::Input); | ||
| 47 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 48 | } | ||
| 49 | |||
| 50 | T::enable(); | ||
| 51 | T::reset(); | ||
| 52 | |||
| 53 | Self { | ||
| 54 | can: bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(), | ||
| 55 | } | ||
| 56 | } | ||
| 34 | } | 57 | } |
| 35 | 58 | ||
| 36 | impl<'d, T: Instance> Drop for Can<'d, T> { | 59 | impl<'d, T: Instance> Drop for Can<'d, T> { |
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index fb9dc9d08..20e1a4070 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 1 | use core::task::Poll; | 2 | use core::task::Poll; |
| 2 | 3 | ||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 4 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | use embassy_sync::waitqueue::AtomicWaker; | 5 | use embassy_sync::waitqueue::AtomicWaker; |
| 5 | use futures::future::poll_fn; | ||
| 6 | 6 | ||
| 7 | use crate::gpio::sealed::AFType; | 7 | use crate::gpio::sealed::AFType; |
| 8 | use crate::gpio::Speed; | 8 | use crate::gpio::Speed; |
| @@ -429,7 +429,7 @@ where | |||
| 429 | } | 429 | } |
| 430 | }); | 430 | }); |
| 431 | 431 | ||
| 432 | let (_, result) = futures::future::join(dma_read, result).await; | 432 | let (_, result) = embassy_futures::join::join(dma_read, result).await; |
| 433 | 433 | ||
| 434 | unsafe { Self::toggle(false) }; | 434 | unsafe { Self::toggle(false) }; |
| 435 | 435 | ||
| @@ -537,7 +537,7 @@ where | |||
| 537 | 537 | ||
| 538 | unsafe { Self::toggle(true) }; | 538 | unsafe { Self::toggle(true) }; |
| 539 | 539 | ||
| 540 | let (_, result) = futures::future::join(dma_result, result).await; | 540 | let (_, result) = embassy_futures::join::join(dma_result, result).await; |
| 541 | 541 | ||
| 542 | unsafe { Self::toggle(false) }; | 542 | unsafe { Self::toggle(false) }; |
| 543 | 543 | ||
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 1ab0438ad..38629a932 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs | |||
| @@ -29,7 +29,7 @@ use super::*; | |||
| 29 | 29 | ||
| 30 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(StateStorage<Inner<'d, T, TX, RX>>); | 30 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(StateStorage<Inner<'d, T, TX, RX>>); |
| 31 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { | 31 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { |
| 32 | pub fn new() -> Self { | 32 | pub const fn new() -> Self { |
| 33 | Self(StateStorage::new()) | 33 | Self(StateStorage::new()) |
| 34 | } | 34 | } |
| 35 | } | 35 | } |
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index d67c3c5e4..a81ee1183 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs | |||
| @@ -19,7 +19,7 @@ use super::*; | |||
| 19 | 19 | ||
| 20 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(StateStorage<Inner<'d, T, TX, RX>>); | 20 | pub struct State<'d, T: Instance, const TX: usize, const RX: usize>(StateStorage<Inner<'d, T, TX, RX>>); |
| 21 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { | 21 | impl<'d, T: Instance, const TX: usize, const RX: usize> State<'d, T, TX, RX> { |
| 22 | pub fn new() -> Self { | 22 | pub const fn new() -> Self { |
| 23 | Self(StateStorage::new()) | 23 | Self(StateStorage::new()) |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index db4924461..b7c89931c 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use core::cmp; | 1 | use core::cmp; |
| 2 | use core::future::poll_fn; | ||
| 2 | use core::task::Poll; | 3 | use core::task::Poll; |
| 3 | 4 | ||
| 4 | use atomic_polyfill::{AtomicUsize, Ordering}; | 5 | use atomic_polyfill::{AtomicUsize, Ordering}; |
| @@ -6,7 +7,6 @@ use embassy_embedded_hal::SetConfig; | |||
| 6 | use embassy_hal_common::drop::OnDrop; | 7 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use futures::future::poll_fn; | ||
| 10 | 10 | ||
| 11 | use crate::dma::NoDma; | 11 | use crate::dma::NoDma; |
| 12 | use crate::gpio::sealed::AFType; | 12 | use crate::gpio::sealed::AFType; |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 30ff02d56..0392e8086 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | 3 | ||
| 4 | // This must go FIRST so that all the other modules see its macros. | 4 | // This must go FIRST so that all the other modules see its macros. |
| 5 | pub mod fmt; | 5 | pub mod fmt; |
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 520f2ab9a..10fc4a75e 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::poll_fn; | ||
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 5 | use embassy_hal_common::{into_ref, PeripheralRef}; | 6 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 6 | use embassy_sync::waitqueue::AtomicWaker; | 7 | use embassy_sync::waitqueue::AtomicWaker; |
| 7 | use futures::future::poll_fn; | ||
| 8 | use rand_core::{CryptoRng, RngCore}; | 8 | use rand_core::{CryptoRng, RngCore}; |
| 9 | 9 | ||
| 10 | use crate::{pac, peripherals, Peripheral}; | 10 | use crate::{pac, peripherals, Peripheral}; |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 67758c492..a8bc6385f 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::default::Default; | 3 | use core::default::Default; |
| 4 | use core::future::poll_fn; | ||
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_hal_common::drop::OnDrop; | 7 | use embassy_hal_common::drop::OnDrop; |
| 7 | use embassy_hal_common::{into_ref, PeripheralRef}; | 8 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | use futures::future::poll_fn; | ||
| 10 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | 10 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; |
| 11 | 11 | ||
| 12 | use crate::dma::NoDma; | 12 | use crate::dma::NoDma; |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 02e6020b0..556d12305 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | use core::ptr; | 3 | use core::ptr; |
| 4 | 4 | ||
| 5 | use embassy_embedded_hal::SetConfig; | 5 | use embassy_embedded_hal::SetConfig; |
| 6 | use embassy_futures::join::join; | ||
| 6 | use embassy_hal_common::{into_ref, PeripheralRef}; | 7 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 7 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; | 8 | pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; |
| 8 | use futures::future::join; | ||
| 9 | 9 | ||
| 10 | use self::sealed::WordSize; | 10 | use self::sealed::WordSize; |
| 11 | use crate::dma::{slice_ptr_parts, NoDma, Transfer}; | 11 | use crate::dma::{slice_ptr_parts, NoDma, Transfer}; |
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index a7fa43894..46c49a997 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -1,17 +1,16 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::{poll_fn, Future}; |
| 2 | use core::task::Poll; | 2 | use core::task::Poll; |
| 3 | 3 | ||
| 4 | use atomic_polyfill::{compiler_fence, Ordering}; | 4 | use atomic_polyfill::{compiler_fence, Ordering}; |
| 5 | use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | 5 | use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; |
| 6 | use embassy_hal_common::ring_buffer::RingBuffer; | 6 | use embassy_hal_common::ring_buffer::RingBuffer; |
| 7 | use embassy_sync::waitqueue::WakerRegistration; | 7 | use embassy_sync::waitqueue::WakerRegistration; |
| 8 | use futures::future::poll_fn; | ||
| 9 | 8 | ||
| 10 | use super::*; | 9 | use super::*; |
| 11 | 10 | ||
| 12 | pub struct State<'d, T: BasicInstance>(StateStorage<StateInner<'d, T>>); | 11 | pub struct State<'d, T: BasicInstance>(StateStorage<StateInner<'d, T>>); |
| 13 | impl<'d, T: BasicInstance> State<'d, T> { | 12 | impl<'d, T: BasicInstance> State<'d, T> { |
| 14 | pub fn new() -> Self { | 13 | pub const fn new() -> Self { |
| 15 | Self(StateStorage::new()) | 14 | Self(StateStorage::new()) |
| 16 | } | 15 | } |
| 17 | } | 16 | } |
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index db965824a..39809a3e1 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::future::{poll_fn, Future}; | ||
| 3 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 4 | use core::sync::atomic::Ordering; | 5 | use core::sync::atomic::Ordering; |
| 5 | use core::task::Poll; | 6 | use core::task::Poll; |
| @@ -8,10 +9,9 @@ use atomic_polyfill::{AtomicBool, AtomicU8}; | |||
| 8 | use embassy_hal_common::into_ref; | 9 | use embassy_hal_common::into_ref; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | use embassy_time::{block_for, Duration}; | 11 | use embassy_time::{block_for, Duration}; |
| 11 | use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; | 12 | use embassy_usb::driver::{ |
| 12 | use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; | 13 | self, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, |
| 13 | use futures::future::poll_fn; | 14 | }; |
| 14 | use futures::Future; | ||
| 15 | use pac::common::{Reg, RW}; | 15 | use pac::common::{Reg, RW}; |
| 16 | use pac::usb::vals::{EpType, Stat}; | 16 | use pac::usb::vals::{EpType, Stat}; |
| 17 | 17 | ||
| @@ -280,8 +280,8 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 280 | } | 280 | } |
| 281 | let used = ep.used_out || ep.used_in; | 281 | let used = ep.used_out || ep.used_in; |
| 282 | let used_dir = match D::dir() { | 282 | let used_dir = match D::dir() { |
| 283 | UsbDirection::Out => ep.used_out, | 283 | Direction::Out => ep.used_out, |
| 284 | UsbDirection::In => ep.used_in, | 284 | Direction::In => ep.used_in, |
| 285 | }; | 285 | }; |
| 286 | !used || (ep.ep_type == ep_type && !used_dir) | 286 | !used || (ep.ep_type == ep_type && !used_dir) |
| 287 | }); | 287 | }); |
| @@ -294,7 +294,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 294 | ep.ep_type = ep_type; | 294 | ep.ep_type = ep_type; |
| 295 | 295 | ||
| 296 | let buf = match D::dir() { | 296 | let buf = match D::dir() { |
| 297 | UsbDirection::Out => { | 297 | Direction::Out => { |
| 298 | assert!(!ep.used_out); | 298 | assert!(!ep.used_out); |
| 299 | ep.used_out = true; | 299 | ep.used_out = true; |
| 300 | 300 | ||
| @@ -313,7 +313,7 @@ impl<'d, T: Instance> Driver<'d, T> { | |||
| 313 | _phantom: PhantomData, | 313 | _phantom: PhantomData, |
| 314 | } | 314 | } |
| 315 | } | 315 | } |
| 316 | UsbDirection::In => { | 316 | Direction::In => { |
| 317 | assert!(!ep.used_in); | 317 | assert!(!ep.used_in); |
| 318 | ep.used_in = true; | 318 | ep.used_in = true; |
| 319 | 319 | ||
| @@ -505,7 +505,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 505 | // This can race, so do a retry loop. | 505 | // This can race, so do a retry loop. |
| 506 | let reg = T::regs().epr(ep_addr.index() as _); | 506 | let reg = T::regs().epr(ep_addr.index() as _); |
| 507 | match ep_addr.direction() { | 507 | match ep_addr.direction() { |
| 508 | UsbDirection::In => { | 508 | Direction::In => { |
| 509 | loop { | 509 | loop { |
| 510 | let r = unsafe { reg.read() }; | 510 | let r = unsafe { reg.read() }; |
| 511 | match r.stat_tx() { | 511 | match r.stat_tx() { |
| @@ -524,7 +524,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 524 | } | 524 | } |
| 525 | EP_IN_WAKERS[ep_addr.index()].wake(); | 525 | EP_IN_WAKERS[ep_addr.index()].wake(); |
| 526 | } | 526 | } |
| 527 | UsbDirection::Out => { | 527 | Direction::Out => { |
| 528 | loop { | 528 | loop { |
| 529 | let r = unsafe { reg.read() }; | 529 | let r = unsafe { reg.read() }; |
| 530 | match r.stat_rx() { | 530 | match r.stat_rx() { |
| @@ -550,8 +550,8 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 550 | let regs = T::regs(); | 550 | let regs = T::regs(); |
| 551 | let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; | 551 | let epr = unsafe { regs.epr(ep_addr.index() as _).read() }; |
| 552 | match ep_addr.direction() { | 552 | match ep_addr.direction() { |
| 553 | UsbDirection::In => epr.stat_tx() == Stat::STALL, | 553 | Direction::In => epr.stat_tx() == Stat::STALL, |
| 554 | UsbDirection::Out => epr.stat_rx() == Stat::STALL, | 554 | Direction::Out => epr.stat_rx() == Stat::STALL, |
| 555 | } | 555 | } |
| 556 | } | 556 | } |
| 557 | 557 | ||
| @@ -561,7 +561,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 561 | let reg = T::regs().epr(ep_addr.index() as _); | 561 | let reg = T::regs().epr(ep_addr.index() as _); |
| 562 | trace!("EPR before: {:04x}", unsafe { reg.read() }.0); | 562 | trace!("EPR before: {:04x}", unsafe { reg.read() }.0); |
| 563 | match ep_addr.direction() { | 563 | match ep_addr.direction() { |
| 564 | UsbDirection::In => { | 564 | Direction::In => { |
| 565 | loop { | 565 | loop { |
| 566 | let want_stat = match enabled { | 566 | let want_stat = match enabled { |
| 567 | false => Stat::DISABLED, | 567 | false => Stat::DISABLED, |
| @@ -577,7 +577,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 577 | } | 577 | } |
| 578 | EP_IN_WAKERS[ep_addr.index()].wake(); | 578 | EP_IN_WAKERS[ep_addr.index()].wake(); |
| 579 | } | 579 | } |
| 580 | UsbDirection::Out => { | 580 | Direction::Out => { |
| 581 | loop { | 581 | loop { |
| 582 | let want_stat = match enabled { | 582 | let want_stat = match enabled { |
| 583 | false => Stat::DISABLED, | 583 | false => Stat::DISABLED, |
| @@ -617,14 +617,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { | |||
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | trait Dir { | 619 | trait Dir { |
| 620 | fn dir() -> UsbDirection; | 620 | fn dir() -> Direction; |
| 621 | fn waker(i: usize) -> &'static AtomicWaker; | 621 | fn waker(i: usize) -> &'static AtomicWaker; |
| 622 | } | 622 | } |
| 623 | 623 | ||
| 624 | pub enum In {} | 624 | pub enum In {} |
| 625 | impl Dir for In { | 625 | impl Dir for In { |
| 626 | fn dir() -> UsbDirection { | 626 | fn dir() -> Direction { |
| 627 | UsbDirection::In | 627 | Direction::In |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | #[inline] | 630 | #[inline] |
| @@ -635,8 +635,8 @@ impl Dir for In { | |||
| 635 | 635 | ||
| 636 | pub enum Out {} | 636 | pub enum Out {} |
| 637 | impl Dir for Out { | 637 | impl Dir for Out { |
| 638 | fn dir() -> UsbDirection { | 638 | fn dir() -> Direction { |
| 639 | UsbDirection::Out | 639 | Direction::Out |
| 640 | } | 640 | } |
| 641 | 641 | ||
| 642 | #[inline] | 642 | #[inline] |
diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs index 25150e8aa..80bb907a3 100644 --- a/embassy-sync/src/lib.rs +++ b/embassy-sync/src/lib.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] | 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | #![allow(clippy::new_without_default)] | 3 | #![allow(clippy::new_without_default)] |
| 4 | #![doc = include_str!("../README.md")] | 4 | #![doc = include_str!("../README.md")] |
| 5 | #![warn(missing_docs)] | 5 | #![warn(missing_docs)] |
diff --git a/embassy-sync/src/mutex.rs b/embassy-sync/src/mutex.rs index 75a6e8dd3..fcf056d36 100644 --- a/embassy-sync/src/mutex.rs +++ b/embassy-sync/src/mutex.rs | |||
| @@ -2,11 +2,10 @@ | |||
| 2 | //! | 2 | //! |
| 3 | //! This module provides a mutex that can be used to synchronize data between asynchronous tasks. | 3 | //! This module provides a mutex that can be used to synchronize data between asynchronous tasks. |
| 4 | use core::cell::{RefCell, UnsafeCell}; | 4 | use core::cell::{RefCell, UnsafeCell}; |
| 5 | use core::future::poll_fn; | ||
| 5 | use core::ops::{Deref, DerefMut}; | 6 | use core::ops::{Deref, DerefMut}; |
| 6 | use core::task::Poll; | 7 | use core::task::Poll; |
| 7 | 8 | ||
| 8 | use futures_util::future::poll_fn; | ||
| 9 | |||
| 10 | use crate::blocking_mutex::raw::RawMutex; | 9 | use crate::blocking_mutex::raw::RawMutex; |
| 11 | use crate::blocking_mutex::Mutex as BlockingMutex; | 10 | use crate::blocking_mutex::Mutex as BlockingMutex; |
| 12 | use crate::waitqueue::WakerRegistration; | 11 | use crate::waitqueue::WakerRegistration; |
| @@ -111,6 +110,22 @@ where | |||
| 111 | 110 | ||
| 112 | Ok(MutexGuard { mutex: self }) | 111 | Ok(MutexGuard { mutex: self }) |
| 113 | } | 112 | } |
| 113 | |||
| 114 | /// Consumes this mutex, returning the underlying data. | ||
| 115 | pub fn into_inner(self) -> T | ||
| 116 | where | ||
| 117 | T: Sized, | ||
| 118 | { | ||
| 119 | self.inner.into_inner() | ||
| 120 | } | ||
| 121 | |||
| 122 | /// Returns a mutable reference to the underlying data. | ||
| 123 | /// | ||
| 124 | /// Since this call borrows the Mutex mutably, no actual locking needs to | ||
| 125 | /// take place -- the mutable borrow statically guarantees no locks exist. | ||
| 126 | pub fn get_mut(&mut self) -> &mut T { | ||
| 127 | self.inner.get_mut() | ||
| 128 | } | ||
| 114 | } | 129 | } |
| 115 | 130 | ||
| 116 | /// Async mutex guard. | 131 | /// Async mutex guard. |
diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs index f6ebeb9b9..c3c10a8af 100644 --- a/embassy-sync/src/signal.rs +++ b/embassy-sync/src/signal.rs | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | //! A synchronization primitive for passing the latest value to a task. | 1 | //! A synchronization primitive for passing the latest value to a task. |
| 2 | use core::cell::UnsafeCell; | 2 | use core::cell::Cell; |
| 3 | use core::future::Future; | 3 | use core::future::{poll_fn, Future}; |
| 4 | use core::mem; | ||
| 5 | use core::task::{Context, Poll, Waker}; | 4 | use core::task::{Context, Poll, Waker}; |
| 6 | 5 | ||
| 6 | use crate::blocking_mutex::raw::RawMutex; | ||
| 7 | use crate::blocking_mutex::Mutex; | ||
| 8 | |||
| 7 | /// Single-slot signaling primitive. | 9 | /// Single-slot signaling primitive. |
| 8 | /// | 10 | /// |
| 9 | /// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except | 11 | /// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except |
| @@ -20,16 +22,20 @@ use core::task::{Context, Poll, Waker}; | |||
| 20 | /// | 22 | /// |
| 21 | /// ``` | 23 | /// ``` |
| 22 | /// use embassy_sync::signal::Signal; | 24 | /// use embassy_sync::signal::Signal; |
| 25 | /// use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 23 | /// | 26 | /// |
| 24 | /// enum SomeCommand { | 27 | /// enum SomeCommand { |
| 25 | /// On, | 28 | /// On, |
| 26 | /// Off, | 29 | /// Off, |
| 27 | /// } | 30 | /// } |
| 28 | /// | 31 | /// |
| 29 | /// static SOME_SIGNAL: Signal<SomeCommand> = Signal::new(); | 32 | /// static SOME_SIGNAL: Signal<CriticalSectionRawMutex, SomeCommand> = Signal::new(); |
| 30 | /// ``` | 33 | /// ``` |
| 31 | pub struct Signal<T> { | 34 | pub struct Signal<M, T> |
| 32 | state: UnsafeCell<State<T>>, | 35 | where |
| 36 | M: RawMutex, | ||
| 37 | { | ||
| 38 | state: Mutex<M, Cell<State<T>>>, | ||
| 33 | } | 39 | } |
| 34 | 40 | ||
| 35 | enum State<T> { | 41 | enum State<T> { |
| @@ -38,24 +44,27 @@ enum State<T> { | |||
| 38 | Signaled(T), | 44 | Signaled(T), |
| 39 | } | 45 | } |
| 40 | 46 | ||
| 41 | unsafe impl<T: Send> Send for Signal<T> {} | 47 | impl<M, T> Signal<M, T> |
| 42 | unsafe impl<T: Send> Sync for Signal<T> {} | 48 | where |
| 43 | 49 | M: RawMutex, | |
| 44 | impl<T> Signal<T> { | 50 | { |
| 45 | /// Create a new `Signal`. | 51 | /// Create a new `Signal`. |
| 46 | pub const fn new() -> Self { | 52 | pub const fn new() -> Self { |
| 47 | Self { | 53 | Self { |
| 48 | state: UnsafeCell::new(State::None), | 54 | state: Mutex::new(Cell::new(State::None)), |
| 49 | } | 55 | } |
| 50 | } | 56 | } |
| 51 | } | 57 | } |
| 52 | 58 | ||
| 53 | impl<T: Send> Signal<T> { | 59 | impl<M, T: Send> Signal<M, T> |
| 60 | where | ||
| 61 | M: RawMutex, | ||
| 62 | { | ||
| 54 | /// Mark this Signal as signaled. | 63 | /// Mark this Signal as signaled. |
| 55 | pub fn signal(&self, val: T) { | 64 | pub fn signal(&self, val: T) { |
| 56 | critical_section::with(|_| unsafe { | 65 | self.state.lock(|cell| { |
| 57 | let state = &mut *self.state.get(); | 66 | let state = cell.replace(State::Signaled(val)); |
| 58 | if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { | 67 | if let State::Waiting(waker) = state { |
| 59 | waker.wake(); | 68 | waker.wake(); |
| 60 | } | 69 | } |
| 61 | }) | 70 | }) |
| @@ -63,38 +72,46 @@ impl<T: Send> Signal<T> { | |||
| 63 | 72 | ||
| 64 | /// Remove the queued value in this `Signal`, if any. | 73 | /// Remove the queued value in this `Signal`, if any. |
| 65 | pub fn reset(&self) { | 74 | pub fn reset(&self) { |
| 66 | critical_section::with(|_| unsafe { | 75 | self.state.lock(|cell| cell.set(State::None)); |
| 67 | let state = &mut *self.state.get(); | ||
| 68 | *state = State::None | ||
| 69 | }) | ||
| 70 | } | 76 | } |
| 71 | 77 | ||
| 72 | /// Manually poll the Signal future. | 78 | fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { |
| 73 | pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { | 79 | self.state.lock(|cell| { |
| 74 | critical_section::with(|_| unsafe { | 80 | let state = cell.replace(State::None); |
| 75 | let state = &mut *self.state.get(); | ||
| 76 | match state { | 81 | match state { |
| 77 | State::None => { | 82 | State::None => { |
| 78 | *state = State::Waiting(cx.waker().clone()); | 83 | cell.set(State::Waiting(cx.waker().clone())); |
| 79 | Poll::Pending | 84 | Poll::Pending |
| 80 | } | 85 | } |
| 81 | State::Waiting(w) if w.will_wake(cx.waker()) => Poll::Pending, | 86 | State::Waiting(w) if w.will_wake(cx.waker()) => { |
| 82 | State::Waiting(_) => panic!("waker overflow"), | 87 | cell.set(State::Waiting(w)); |
| 83 | State::Signaled(_) => match mem::replace(state, State::None) { | 88 | Poll::Pending |
| 84 | State::Signaled(res) => Poll::Ready(res), | 89 | } |
| 85 | _ => unreachable!(), | 90 | State::Waiting(w) => { |
| 86 | }, | 91 | cell.set(State::Waiting(cx.waker().clone())); |
| 92 | w.wake(); | ||
| 93 | Poll::Pending | ||
| 94 | } | ||
| 95 | State::Signaled(res) => Poll::Ready(res), | ||
| 87 | } | 96 | } |
| 88 | }) | 97 | }) |
| 89 | } | 98 | } |
| 90 | 99 | ||
| 91 | /// Future that completes when this Signal has been signaled. | 100 | /// Future that completes when this Signal has been signaled. |
| 92 | pub fn wait(&self) -> impl Future<Output = T> + '_ { | 101 | pub fn wait(&self) -> impl Future<Output = T> + '_ { |
| 93 | futures_util::future::poll_fn(move |cx| self.poll_wait(cx)) | 102 | poll_fn(move |cx| self.poll_wait(cx)) |
| 94 | } | 103 | } |
| 95 | 104 | ||
| 96 | /// non-blocking method to check whether this signal has been signaled. | 105 | /// non-blocking method to check whether this signal has been signaled. |
| 97 | pub fn signaled(&self) -> bool { | 106 | pub fn signaled(&self) -> bool { |
| 98 | critical_section::with(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) | 107 | self.state.lock(|cell| { |
| 108 | let state = cell.replace(State::None); | ||
| 109 | |||
| 110 | let res = matches!(state, State::Signaled(_)); | ||
| 111 | |||
| 112 | cell.set(state); | ||
| 113 | |||
| 114 | res | ||
| 115 | }) | ||
| 99 | } | 116 | } |
| 100 | } | 117 | } |
diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs index 5b2620986..4edc883fe 100644 --- a/embassy-time/src/lib.rs +++ b/embassy-time/src/lib.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] | 1 | #![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] |
| 2 | #![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] | 2 | #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] |
| 3 | #![doc = include_str!("../README.md")] | 3 | #![doc = include_str!("../README.md")] |
| 4 | #![allow(clippy::new_without_default)] | 4 | #![allow(clippy::new_without_default)] |
| 5 | #![warn(missing_docs)] | 5 | #![warn(missing_docs)] |
diff --git a/embassy-usb-ncm/Cargo.toml b/embassy-usb-driver/Cargo.toml index 15d3db96f..b525df337 100644 --- a/embassy-usb-ncm/Cargo.toml +++ b/embassy-usb-driver/Cargo.toml | |||
| @@ -1,17 +1,16 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "embassy-usb-ncm" | 2 | name = "embassy-usb-driver" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | 5 | ||
| 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
| 7 | |||
| 6 | [package.metadata.embassy_docs] | 8 | [package.metadata.embassy_docs] |
| 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-ncm-v$VERSION/embassy-usb-ncm/src/" | 9 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-driver-v$VERSION/embassy-usb/src/" |
| 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-ncm/src/" | 10 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-driver/src/" |
| 9 | features = ["defmt"] | 11 | features = ["defmt"] |
| 10 | target = "thumbv7em-none-eabi" | 12 | target = "thumbv7em-none-eabi" |
| 11 | 13 | ||
| 12 | [dependencies] | 14 | [dependencies] |
| 13 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | ||
| 14 | embassy-usb = { version = "0.1.0", path = "../embassy-usb" } | ||
| 15 | |||
| 16 | defmt = { version = "0.3", optional = true } | 15 | defmt = { version = "0.3", optional = true } |
| 17 | log = { version = "0.4.14", optional = true } | 16 | log = { version = "0.4.14", optional = true } \ No newline at end of file |
diff --git a/embassy-usb/src/driver.rs b/embassy-usb-driver/src/lib.rs index 7888f1639..fc29786fc 100644 --- a/embassy-usb/src/driver.rs +++ b/embassy-usb-driver/src/lib.rs | |||
| @@ -1,6 +1,104 @@ | |||
| 1 | #![no_std] | ||
| 2 | |||
| 1 | use core::future::Future; | 3 | use core::future::Future; |
| 2 | 4 | ||
| 3 | use super::types::*; | 5 | /// Direction of USB traffic. Note that in the USB standard the direction is always indicated from |
| 6 | /// the perspective of the host, which is backward for devices, but the standard directions are used | ||
| 7 | /// for consistency. | ||
| 8 | /// | ||
| 9 | /// The values of the enum also match the direction bit used in endpoint addresses and control | ||
| 10 | /// request types. | ||
| 11 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 12 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 13 | pub enum Direction { | ||
| 14 | /// Host to device (OUT) | ||
| 15 | Out, | ||
| 16 | /// Device to host (IN) | ||
| 17 | In, | ||
| 18 | } | ||
| 19 | |||
| 20 | /// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the | ||
| 21 | /// transfer bmAttributes transfer type bits. | ||
| 22 | #[repr(u8)] | ||
| 23 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 24 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 25 | pub enum EndpointType { | ||
| 26 | /// Control endpoint. Used for device management. Only the host can initiate requests. Usually | ||
| 27 | /// used only endpoint 0. | ||
| 28 | Control = 0b00, | ||
| 29 | /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet. | ||
| 30 | Isochronous = 0b01, | ||
| 31 | /// Bulk endpoint. Used for large amounts of best-effort reliable data. | ||
| 32 | Bulk = 0b10, | ||
| 33 | /// Interrupt endpoint. Used for small amounts of time-critical reliable data. | ||
| 34 | Interrupt = 0b11, | ||
| 35 | } | ||
| 36 | |||
| 37 | /// Type-safe endpoint address. | ||
| 38 | #[derive(Debug, Clone, Copy, Eq, PartialEq)] | ||
| 39 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 40 | pub struct EndpointAddress(u8); | ||
| 41 | |||
| 42 | impl From<u8> for EndpointAddress { | ||
| 43 | #[inline] | ||
| 44 | fn from(addr: u8) -> EndpointAddress { | ||
| 45 | EndpointAddress(addr) | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | impl From<EndpointAddress> for u8 { | ||
| 50 | #[inline] | ||
| 51 | fn from(addr: EndpointAddress) -> u8 { | ||
| 52 | addr.0 | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | impl EndpointAddress { | ||
| 57 | const INBITS: u8 = Direction::In as u8; | ||
| 58 | |||
| 59 | /// Constructs a new EndpointAddress with the given index and direction. | ||
| 60 | #[inline] | ||
| 61 | pub fn from_parts(index: usize, dir: Direction) -> Self { | ||
| 62 | EndpointAddress(index as u8 | dir as u8) | ||
| 63 | } | ||
| 64 | |||
| 65 | /// Gets the direction part of the address. | ||
| 66 | #[inline] | ||
| 67 | pub fn direction(&self) -> Direction { | ||
| 68 | if (self.0 & Self::INBITS) != 0 { | ||
| 69 | Direction::In | ||
| 70 | } else { | ||
| 71 | Direction::Out | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | /// Returns true if the direction is IN, otherwise false. | ||
| 76 | #[inline] | ||
| 77 | pub fn is_in(&self) -> bool { | ||
| 78 | (self.0 & Self::INBITS) != 0 | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Returns true if the direction is OUT, otherwise false. | ||
| 82 | #[inline] | ||
| 83 | pub fn is_out(&self) -> bool { | ||
| 84 | (self.0 & Self::INBITS) == 0 | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Gets the index part of the endpoint address. | ||
| 88 | #[inline] | ||
| 89 | pub fn index(&self) -> usize { | ||
| 90 | (self.0 & !Self::INBITS) as usize | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 95 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 96 | pub struct EndpointInfo { | ||
| 97 | pub addr: EndpointAddress, | ||
| 98 | pub ep_type: EndpointType, | ||
| 99 | pub max_packet_size: u16, | ||
| 100 | pub interval: u8, | ||
| 101 | } | ||
| 4 | 102 | ||
| 5 | /// Driver for a specific USB peripheral. Implement this to add support for a new hardware | 103 | /// Driver for a specific USB peripheral. Implement this to add support for a new hardware |
| 6 | /// platform. | 104 | /// platform. |
diff --git a/embassy-usb-hid/Cargo.toml b/embassy-usb-hid/Cargo.toml deleted file mode 100644 index 2f7733dc6..000000000 --- a/embassy-usb-hid/Cargo.toml +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-usb-hid" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [package.metadata.embassy_docs] | ||
| 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-hid-v$VERSION/embassy-usb-hid/src/" | ||
| 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-hid/src/" | ||
| 9 | features = ["defmt"] | ||
| 10 | target = "thumbv7em-none-eabi" | ||
| 11 | |||
| 12 | [features] | ||
| 13 | default = ["usbd-hid"] | ||
| 14 | usbd-hid = ["dep:usbd-hid", "ssmarshal"] | ||
| 15 | |||
| 16 | [dependencies] | ||
| 17 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | ||
| 18 | embassy-usb = { version = "0.1.0", path = "../embassy-usb" } | ||
| 19 | |||
| 20 | defmt = { version = "0.3", optional = true } | ||
| 21 | log = { version = "0.4.14", optional = true } | ||
| 22 | usbd-hid = { version = "0.6.0", optional = true } | ||
| 23 | ssmarshal = { version = "1.0", default-features = false, optional = true } | ||
| 24 | futures-util = { version = "0.3.21", default-features = false } | ||
diff --git a/embassy-usb-hid/src/fmt.rs b/embassy-usb-hid/src/fmt.rs deleted file mode 100644 index 066970813..000000000 --- a/embassy-usb-hid/src/fmt.rs +++ /dev/null | |||
| @@ -1,225 +0,0 @@ | |||
| 1 | #![macro_use] | ||
| 2 | #![allow(unused_macros)] | ||
| 3 | |||
| 4 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 5 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 6 | |||
| 7 | macro_rules! assert { | ||
| 8 | ($($x:tt)*) => { | ||
| 9 | { | ||
| 10 | #[cfg(not(feature = "defmt"))] | ||
| 11 | ::core::assert!($($x)*); | ||
| 12 | #[cfg(feature = "defmt")] | ||
| 13 | ::defmt::assert!($($x)*); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | macro_rules! assert_eq { | ||
| 19 | ($($x:tt)*) => { | ||
| 20 | { | ||
| 21 | #[cfg(not(feature = "defmt"))] | ||
| 22 | ::core::assert_eq!($($x)*); | ||
| 23 | #[cfg(feature = "defmt")] | ||
| 24 | ::defmt::assert_eq!($($x)*); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | macro_rules! assert_ne { | ||
| 30 | ($($x:tt)*) => { | ||
| 31 | { | ||
| 32 | #[cfg(not(feature = "defmt"))] | ||
| 33 | ::core::assert_ne!($($x)*); | ||
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | ::defmt::assert_ne!($($x)*); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | macro_rules! debug_assert { | ||
| 41 | ($($x:tt)*) => { | ||
| 42 | { | ||
| 43 | #[cfg(not(feature = "defmt"))] | ||
| 44 | ::core::debug_assert!($($x)*); | ||
| 45 | #[cfg(feature = "defmt")] | ||
| 46 | ::defmt::debug_assert!($($x)*); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | macro_rules! debug_assert_eq { | ||
| 52 | ($($x:tt)*) => { | ||
| 53 | { | ||
| 54 | #[cfg(not(feature = "defmt"))] | ||
| 55 | ::core::debug_assert_eq!($($x)*); | ||
| 56 | #[cfg(feature = "defmt")] | ||
| 57 | ::defmt::debug_assert_eq!($($x)*); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | macro_rules! debug_assert_ne { | ||
| 63 | ($($x:tt)*) => { | ||
| 64 | { | ||
| 65 | #[cfg(not(feature = "defmt"))] | ||
| 66 | ::core::debug_assert_ne!($($x)*); | ||
| 67 | #[cfg(feature = "defmt")] | ||
| 68 | ::defmt::debug_assert_ne!($($x)*); | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | } | ||
| 72 | |||
| 73 | macro_rules! todo { | ||
| 74 | ($($x:tt)*) => { | ||
| 75 | { | ||
| 76 | #[cfg(not(feature = "defmt"))] | ||
| 77 | ::core::todo!($($x)*); | ||
| 78 | #[cfg(feature = "defmt")] | ||
| 79 | ::defmt::todo!($($x)*); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | macro_rules! unreachable { | ||
| 85 | ($($x:tt)*) => { | ||
| 86 | { | ||
| 87 | #[cfg(not(feature = "defmt"))] | ||
| 88 | ::core::unreachable!($($x)*); | ||
| 89 | #[cfg(feature = "defmt")] | ||
| 90 | ::defmt::unreachable!($($x)*); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | macro_rules! panic { | ||
| 96 | ($($x:tt)*) => { | ||
| 97 | { | ||
| 98 | #[cfg(not(feature = "defmt"))] | ||
| 99 | ::core::panic!($($x)*); | ||
| 100 | #[cfg(feature = "defmt")] | ||
| 101 | ::defmt::panic!($($x)*); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | macro_rules! trace { | ||
| 107 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 108 | { | ||
| 109 | #[cfg(feature = "log")] | ||
| 110 | ::log::trace!($s $(, $x)*); | ||
| 111 | #[cfg(feature = "defmt")] | ||
| 112 | ::defmt::trace!($s $(, $x)*); | ||
| 113 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 114 | let _ = ($( & $x ),*); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | } | ||
| 118 | |||
| 119 | macro_rules! debug { | ||
| 120 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 121 | { | ||
| 122 | #[cfg(feature = "log")] | ||
| 123 | ::log::debug!($s $(, $x)*); | ||
| 124 | #[cfg(feature = "defmt")] | ||
| 125 | ::defmt::debug!($s $(, $x)*); | ||
| 126 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 127 | let _ = ($( & $x ),*); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | |||
| 132 | macro_rules! info { | ||
| 133 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 134 | { | ||
| 135 | #[cfg(feature = "log")] | ||
| 136 | ::log::info!($s $(, $x)*); | ||
| 137 | #[cfg(feature = "defmt")] | ||
| 138 | ::defmt::info!($s $(, $x)*); | ||
| 139 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 140 | let _ = ($( & $x ),*); | ||
| 141 | } | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | macro_rules! warn { | ||
| 146 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 147 | { | ||
| 148 | #[cfg(feature = "log")] | ||
| 149 | ::log::warn!($s $(, $x)*); | ||
| 150 | #[cfg(feature = "defmt")] | ||
| 151 | ::defmt::warn!($s $(, $x)*); | ||
| 152 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 153 | let _ = ($( & $x ),*); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | macro_rules! error { | ||
| 159 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 160 | { | ||
| 161 | #[cfg(feature = "log")] | ||
| 162 | ::log::error!($s $(, $x)*); | ||
| 163 | #[cfg(feature = "defmt")] | ||
| 164 | ::defmt::error!($s $(, $x)*); | ||
| 165 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 166 | let _ = ($( & $x ),*); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | #[cfg(feature = "defmt")] | ||
| 172 | macro_rules! unwrap { | ||
| 173 | ($($x:tt)*) => { | ||
| 174 | ::defmt::unwrap!($($x)*) | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | #[cfg(not(feature = "defmt"))] | ||
| 179 | macro_rules! unwrap { | ||
| 180 | ($arg:expr) => { | ||
| 181 | match $crate::fmt::Try::into_result($arg) { | ||
| 182 | ::core::result::Result::Ok(t) => t, | ||
| 183 | ::core::result::Result::Err(e) => { | ||
| 184 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 189 | match $crate::fmt::Try::into_result($arg) { | ||
| 190 | ::core::result::Result::Ok(t) => t, | ||
| 191 | ::core::result::Result::Err(e) => { | ||
| 192 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 199 | pub struct NoneError; | ||
| 200 | |||
| 201 | pub trait Try { | ||
| 202 | type Ok; | ||
| 203 | type Error; | ||
| 204 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<T> Try for Option<T> { | ||
| 208 | type Ok = T; | ||
| 209 | type Error = NoneError; | ||
| 210 | |||
| 211 | #[inline] | ||
| 212 | fn into_result(self) -> Result<T, NoneError> { | ||
| 213 | self.ok_or(NoneError) | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | impl<T, E> Try for Result<T, E> { | ||
| 218 | type Ok = T; | ||
| 219 | type Error = E; | ||
| 220 | |||
| 221 | #[inline] | ||
| 222 | fn into_result(self) -> Self { | ||
| 223 | self | ||
| 224 | } | ||
| 225 | } | ||
diff --git a/embassy-usb-ncm/src/fmt.rs b/embassy-usb-ncm/src/fmt.rs deleted file mode 100644 index 066970813..000000000 --- a/embassy-usb-ncm/src/fmt.rs +++ /dev/null | |||
| @@ -1,225 +0,0 @@ | |||
| 1 | #![macro_use] | ||
| 2 | #![allow(unused_macros)] | ||
| 3 | |||
| 4 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 5 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 6 | |||
| 7 | macro_rules! assert { | ||
| 8 | ($($x:tt)*) => { | ||
| 9 | { | ||
| 10 | #[cfg(not(feature = "defmt"))] | ||
| 11 | ::core::assert!($($x)*); | ||
| 12 | #[cfg(feature = "defmt")] | ||
| 13 | ::defmt::assert!($($x)*); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | macro_rules! assert_eq { | ||
| 19 | ($($x:tt)*) => { | ||
| 20 | { | ||
| 21 | #[cfg(not(feature = "defmt"))] | ||
| 22 | ::core::assert_eq!($($x)*); | ||
| 23 | #[cfg(feature = "defmt")] | ||
| 24 | ::defmt::assert_eq!($($x)*); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | macro_rules! assert_ne { | ||
| 30 | ($($x:tt)*) => { | ||
| 31 | { | ||
| 32 | #[cfg(not(feature = "defmt"))] | ||
| 33 | ::core::assert_ne!($($x)*); | ||
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | ::defmt::assert_ne!($($x)*); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | macro_rules! debug_assert { | ||
| 41 | ($($x:tt)*) => { | ||
| 42 | { | ||
| 43 | #[cfg(not(feature = "defmt"))] | ||
| 44 | ::core::debug_assert!($($x)*); | ||
| 45 | #[cfg(feature = "defmt")] | ||
| 46 | ::defmt::debug_assert!($($x)*); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | macro_rules! debug_assert_eq { | ||
| 52 | ($($x:tt)*) => { | ||
| 53 | { | ||
| 54 | #[cfg(not(feature = "defmt"))] | ||
| 55 | ::core::debug_assert_eq!($($x)*); | ||
| 56 | #[cfg(feature = "defmt")] | ||
| 57 | ::defmt::debug_assert_eq!($($x)*); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | macro_rules! debug_assert_ne { | ||
| 63 | ($($x:tt)*) => { | ||
| 64 | { | ||
| 65 | #[cfg(not(feature = "defmt"))] | ||
| 66 | ::core::debug_assert_ne!($($x)*); | ||
| 67 | #[cfg(feature = "defmt")] | ||
| 68 | ::defmt::debug_assert_ne!($($x)*); | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | } | ||
| 72 | |||
| 73 | macro_rules! todo { | ||
| 74 | ($($x:tt)*) => { | ||
| 75 | { | ||
| 76 | #[cfg(not(feature = "defmt"))] | ||
| 77 | ::core::todo!($($x)*); | ||
| 78 | #[cfg(feature = "defmt")] | ||
| 79 | ::defmt::todo!($($x)*); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | macro_rules! unreachable { | ||
| 85 | ($($x:tt)*) => { | ||
| 86 | { | ||
| 87 | #[cfg(not(feature = "defmt"))] | ||
| 88 | ::core::unreachable!($($x)*); | ||
| 89 | #[cfg(feature = "defmt")] | ||
| 90 | ::defmt::unreachable!($($x)*); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | macro_rules! panic { | ||
| 96 | ($($x:tt)*) => { | ||
| 97 | { | ||
| 98 | #[cfg(not(feature = "defmt"))] | ||
| 99 | ::core::panic!($($x)*); | ||
| 100 | #[cfg(feature = "defmt")] | ||
| 101 | ::defmt::panic!($($x)*); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | macro_rules! trace { | ||
| 107 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 108 | { | ||
| 109 | #[cfg(feature = "log")] | ||
| 110 | ::log::trace!($s $(, $x)*); | ||
| 111 | #[cfg(feature = "defmt")] | ||
| 112 | ::defmt::trace!($s $(, $x)*); | ||
| 113 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 114 | let _ = ($( & $x ),*); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | } | ||
| 118 | |||
| 119 | macro_rules! debug { | ||
| 120 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 121 | { | ||
| 122 | #[cfg(feature = "log")] | ||
| 123 | ::log::debug!($s $(, $x)*); | ||
| 124 | #[cfg(feature = "defmt")] | ||
| 125 | ::defmt::debug!($s $(, $x)*); | ||
| 126 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 127 | let _ = ($( & $x ),*); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | |||
| 132 | macro_rules! info { | ||
| 133 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 134 | { | ||
| 135 | #[cfg(feature = "log")] | ||
| 136 | ::log::info!($s $(, $x)*); | ||
| 137 | #[cfg(feature = "defmt")] | ||
| 138 | ::defmt::info!($s $(, $x)*); | ||
| 139 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 140 | let _ = ($( & $x ),*); | ||
| 141 | } | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | macro_rules! warn { | ||
| 146 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 147 | { | ||
| 148 | #[cfg(feature = "log")] | ||
| 149 | ::log::warn!($s $(, $x)*); | ||
| 150 | #[cfg(feature = "defmt")] | ||
| 151 | ::defmt::warn!($s $(, $x)*); | ||
| 152 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 153 | let _ = ($( & $x ),*); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | macro_rules! error { | ||
| 159 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 160 | { | ||
| 161 | #[cfg(feature = "log")] | ||
| 162 | ::log::error!($s $(, $x)*); | ||
| 163 | #[cfg(feature = "defmt")] | ||
| 164 | ::defmt::error!($s $(, $x)*); | ||
| 165 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 166 | let _ = ($( & $x ),*); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | #[cfg(feature = "defmt")] | ||
| 172 | macro_rules! unwrap { | ||
| 173 | ($($x:tt)*) => { | ||
| 174 | ::defmt::unwrap!($($x)*) | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | #[cfg(not(feature = "defmt"))] | ||
| 179 | macro_rules! unwrap { | ||
| 180 | ($arg:expr) => { | ||
| 181 | match $crate::fmt::Try::into_result($arg) { | ||
| 182 | ::core::result::Result::Ok(t) => t, | ||
| 183 | ::core::result::Result::Err(e) => { | ||
| 184 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 189 | match $crate::fmt::Try::into_result($arg) { | ||
| 190 | ::core::result::Result::Ok(t) => t, | ||
| 191 | ::core::result::Result::Err(e) => { | ||
| 192 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 199 | pub struct NoneError; | ||
| 200 | |||
| 201 | pub trait Try { | ||
| 202 | type Ok; | ||
| 203 | type Error; | ||
| 204 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<T> Try for Option<T> { | ||
| 208 | type Ok = T; | ||
| 209 | type Error = NoneError; | ||
| 210 | |||
| 211 | #[inline] | ||
| 212 | fn into_result(self) -> Result<T, NoneError> { | ||
| 213 | self.ok_or(NoneError) | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | impl<T, E> Try for Result<T, E> { | ||
| 218 | type Ok = T; | ||
| 219 | type Error = E; | ||
| 220 | |||
| 221 | #[inline] | ||
| 222 | fn into_result(self) -> Self { | ||
| 223 | self | ||
| 224 | } | ||
| 225 | } | ||
diff --git a/embassy-usb-serial/Cargo.toml b/embassy-usb-serial/Cargo.toml deleted file mode 100644 index 9788588e9..000000000 --- a/embassy-usb-serial/Cargo.toml +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-usb-serial" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [package.metadata.embassy_docs] | ||
| 7 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-usb-serial-v$VERSION/embassy-usb-serial/src/" | ||
| 8 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb-serial/src/" | ||
| 9 | features = ["defmt"] | ||
| 10 | target = "thumbv7em-none-eabi" | ||
| 11 | |||
| 12 | [dependencies] | ||
| 13 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | ||
| 14 | embassy-usb = { version = "0.1.0", path = "../embassy-usb" } | ||
| 15 | |||
| 16 | defmt = { version = "0.3", optional = true } | ||
| 17 | log = { version = "0.4.14", optional = true } | ||
diff --git a/embassy-usb-serial/src/fmt.rs b/embassy-usb-serial/src/fmt.rs deleted file mode 100644 index 066970813..000000000 --- a/embassy-usb-serial/src/fmt.rs +++ /dev/null | |||
| @@ -1,225 +0,0 @@ | |||
| 1 | #![macro_use] | ||
| 2 | #![allow(unused_macros)] | ||
| 3 | |||
| 4 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 5 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 6 | |||
| 7 | macro_rules! assert { | ||
| 8 | ($($x:tt)*) => { | ||
| 9 | { | ||
| 10 | #[cfg(not(feature = "defmt"))] | ||
| 11 | ::core::assert!($($x)*); | ||
| 12 | #[cfg(feature = "defmt")] | ||
| 13 | ::defmt::assert!($($x)*); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | macro_rules! assert_eq { | ||
| 19 | ($($x:tt)*) => { | ||
| 20 | { | ||
| 21 | #[cfg(not(feature = "defmt"))] | ||
| 22 | ::core::assert_eq!($($x)*); | ||
| 23 | #[cfg(feature = "defmt")] | ||
| 24 | ::defmt::assert_eq!($($x)*); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | macro_rules! assert_ne { | ||
| 30 | ($($x:tt)*) => { | ||
| 31 | { | ||
| 32 | #[cfg(not(feature = "defmt"))] | ||
| 33 | ::core::assert_ne!($($x)*); | ||
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | ::defmt::assert_ne!($($x)*); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | macro_rules! debug_assert { | ||
| 41 | ($($x:tt)*) => { | ||
| 42 | { | ||
| 43 | #[cfg(not(feature = "defmt"))] | ||
| 44 | ::core::debug_assert!($($x)*); | ||
| 45 | #[cfg(feature = "defmt")] | ||
| 46 | ::defmt::debug_assert!($($x)*); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | macro_rules! debug_assert_eq { | ||
| 52 | ($($x:tt)*) => { | ||
| 53 | { | ||
| 54 | #[cfg(not(feature = "defmt"))] | ||
| 55 | ::core::debug_assert_eq!($($x)*); | ||
| 56 | #[cfg(feature = "defmt")] | ||
| 57 | ::defmt::debug_assert_eq!($($x)*); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | macro_rules! debug_assert_ne { | ||
| 63 | ($($x:tt)*) => { | ||
| 64 | { | ||
| 65 | #[cfg(not(feature = "defmt"))] | ||
| 66 | ::core::debug_assert_ne!($($x)*); | ||
| 67 | #[cfg(feature = "defmt")] | ||
| 68 | ::defmt::debug_assert_ne!($($x)*); | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | } | ||
| 72 | |||
| 73 | macro_rules! todo { | ||
| 74 | ($($x:tt)*) => { | ||
| 75 | { | ||
| 76 | #[cfg(not(feature = "defmt"))] | ||
| 77 | ::core::todo!($($x)*); | ||
| 78 | #[cfg(feature = "defmt")] | ||
| 79 | ::defmt::todo!($($x)*); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | macro_rules! unreachable { | ||
| 85 | ($($x:tt)*) => { | ||
| 86 | { | ||
| 87 | #[cfg(not(feature = "defmt"))] | ||
| 88 | ::core::unreachable!($($x)*); | ||
| 89 | #[cfg(feature = "defmt")] | ||
| 90 | ::defmt::unreachable!($($x)*); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | macro_rules! panic { | ||
| 96 | ($($x:tt)*) => { | ||
| 97 | { | ||
| 98 | #[cfg(not(feature = "defmt"))] | ||
| 99 | ::core::panic!($($x)*); | ||
| 100 | #[cfg(feature = "defmt")] | ||
| 101 | ::defmt::panic!($($x)*); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | macro_rules! trace { | ||
| 107 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 108 | { | ||
| 109 | #[cfg(feature = "log")] | ||
| 110 | ::log::trace!($s $(, $x)*); | ||
| 111 | #[cfg(feature = "defmt")] | ||
| 112 | ::defmt::trace!($s $(, $x)*); | ||
| 113 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 114 | let _ = ($( & $x ),*); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | } | ||
| 118 | |||
| 119 | macro_rules! debug { | ||
| 120 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 121 | { | ||
| 122 | #[cfg(feature = "log")] | ||
| 123 | ::log::debug!($s $(, $x)*); | ||
| 124 | #[cfg(feature = "defmt")] | ||
| 125 | ::defmt::debug!($s $(, $x)*); | ||
| 126 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 127 | let _ = ($( & $x ),*); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | |||
| 132 | macro_rules! info { | ||
| 133 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 134 | { | ||
| 135 | #[cfg(feature = "log")] | ||
| 136 | ::log::info!($s $(, $x)*); | ||
| 137 | #[cfg(feature = "defmt")] | ||
| 138 | ::defmt::info!($s $(, $x)*); | ||
| 139 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 140 | let _ = ($( & $x ),*); | ||
| 141 | } | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | macro_rules! warn { | ||
| 146 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 147 | { | ||
| 148 | #[cfg(feature = "log")] | ||
| 149 | ::log::warn!($s $(, $x)*); | ||
| 150 | #[cfg(feature = "defmt")] | ||
| 151 | ::defmt::warn!($s $(, $x)*); | ||
| 152 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 153 | let _ = ($( & $x ),*); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | macro_rules! error { | ||
| 159 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 160 | { | ||
| 161 | #[cfg(feature = "log")] | ||
| 162 | ::log::error!($s $(, $x)*); | ||
| 163 | #[cfg(feature = "defmt")] | ||
| 164 | ::defmt::error!($s $(, $x)*); | ||
| 165 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 166 | let _ = ($( & $x ),*); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | #[cfg(feature = "defmt")] | ||
| 172 | macro_rules! unwrap { | ||
| 173 | ($($x:tt)*) => { | ||
| 174 | ::defmt::unwrap!($($x)*) | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | #[cfg(not(feature = "defmt"))] | ||
| 179 | macro_rules! unwrap { | ||
| 180 | ($arg:expr) => { | ||
| 181 | match $crate::fmt::Try::into_result($arg) { | ||
| 182 | ::core::result::Result::Ok(t) => t, | ||
| 183 | ::core::result::Result::Err(e) => { | ||
| 184 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 189 | match $crate::fmt::Try::into_result($arg) { | ||
| 190 | ::core::result::Result::Ok(t) => t, | ||
| 191 | ::core::result::Result::Err(e) => { | ||
| 192 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 199 | pub struct NoneError; | ||
| 200 | |||
| 201 | pub trait Try { | ||
| 202 | type Ok; | ||
| 203 | type Error; | ||
| 204 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<T> Try for Option<T> { | ||
| 208 | type Ok = T; | ||
| 209 | type Error = NoneError; | ||
| 210 | |||
| 211 | #[inline] | ||
| 212 | fn into_result(self) -> Result<T, NoneError> { | ||
| 213 | self.ok_or(NoneError) | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | impl<T, E> Try for Result<T, E> { | ||
| 218 | type Ok = T; | ||
| 219 | type Error = E; | ||
| 220 | |||
| 221 | #[inline] | ||
| 222 | fn into_result(self) -> Self { | ||
| 223 | self | ||
| 224 | } | ||
| 225 | } | ||
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml index 8cad4d314..aad54dbaf 100644 --- a/embassy-usb/Cargo.toml +++ b/embassy-usb/Cargo.toml | |||
| @@ -9,9 +9,20 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-usb/s | |||
| 9 | features = ["defmt"] | 9 | features = ["defmt"] |
| 10 | target = "thumbv7em-none-eabi" | 10 | target = "thumbv7em-none-eabi" |
| 11 | 11 | ||
| 12 | [features] | ||
| 13 | defmt = ["dep:defmt", "embassy-usb-driver/defmt"] | ||
| 14 | usbd-hid = ["dep:usbd-hid", "dep:ssmarshal"] | ||
| 15 | default = ["usbd-hid"] | ||
| 16 | |||
| 12 | [dependencies] | 17 | [dependencies] |
| 13 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | 18 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 19 | embassy-usb-driver = { version = "0.1.0", path = "../embassy-usb-driver" } | ||
| 20 | embassy-sync = { version = "0.1.0", path = "../embassy-sync" } | ||
| 14 | 21 | ||
| 15 | defmt = { version = "0.3", optional = true } | 22 | defmt = { version = "0.3", optional = true } |
| 16 | log = { version = "0.4.14", optional = true } | 23 | log = { version = "0.4.14", optional = true } |
| 17 | heapless = "0.7.10" \ No newline at end of file | 24 | heapless = "0.7.10" |
| 25 | |||
| 26 | # for HID | ||
| 27 | usbd-hid = { version = "0.6.0", optional = true } | ||
| 28 | ssmarshal = { version = "1.0", default-features = false, optional = true } | ||
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index 6be88bc76..87a8333bb 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs | |||
| @@ -1,11 +1,10 @@ | |||
| 1 | use heapless::Vec; | 1 | use heapless::Vec; |
| 2 | 2 | ||
| 3 | use super::control::ControlHandler; | 3 | use crate::control::ControlHandler; |
| 4 | use super::descriptor::{BosWriter, DescriptorWriter}; | 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; |
| 5 | use super::driver::{Driver, Endpoint}; | 5 | use crate::driver::{Driver, Endpoint, EndpointType}; |
| 6 | use super::types::*; | 6 | use crate::types::*; |
| 7 | use super::{DeviceStateHandler, UsbDevice, MAX_INTERFACE_COUNT}; | 7 | use crate::{DeviceStateHandler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; |
| 8 | use crate::{Interface, STRING_INDEX_CUSTOM_START}; | ||
| 9 | 8 | ||
| 10 | #[derive(Debug, Copy, Clone)] | 9 | #[derive(Debug, Copy, Clone)] |
| 11 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 10 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
diff --git a/embassy-usb-serial/src/lib.rs b/embassy-usb/src/class/cdc_acm.rs index f3de2ec1b..09bb1cc8d 100644 --- a/embassy-usb-serial/src/lib.rs +++ b/embassy-usb/src/class/cdc_acm.rs | |||
| @@ -1,19 +1,13 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | // This mod MUST go first, so that the others see its macros. | ||
| 6 | pub(crate) mod fmt; | ||
| 7 | |||
| 8 | use core::cell::Cell; | 1 | use core::cell::Cell; |
| 9 | use core::mem::{self, MaybeUninit}; | 2 | use core::mem::{self, MaybeUninit}; |
| 10 | use core::sync::atomic::{AtomicBool, Ordering}; | 3 | use core::sync::atomic::{AtomicBool, Ordering}; |
| 11 | 4 | ||
| 12 | use embassy_sync::blocking_mutex::CriticalSectionMutex; | 5 | use embassy_sync::blocking_mutex::CriticalSectionMutex; |
| 13 | use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; | 6 | |
| 14 | use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | 7 | use crate::control::{self, ControlHandler, InResponse, OutResponse, Request}; |
| 15 | use embassy_usb::types::*; | 8 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| 16 | use embassy_usb::Builder; | 9 | use crate::types::*; |
| 10 | use crate::Builder; | ||
| 17 | 11 | ||
| 18 | /// This should be used as `device_class` when building the `UsbDevice`. | 12 | /// This should be used as `device_class` when building the `UsbDevice`. |
| 19 | pub const USB_CLASS_CDC: u8 = 0x02; | 13 | pub const USB_CLASS_CDC: u8 = 0x02; |
| @@ -269,7 +263,7 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 269 | } | 263 | } |
| 270 | 264 | ||
| 271 | /// Number of stop bits for LineCoding | 265 | /// Number of stop bits for LineCoding |
| 272 | #[derive(Copy, Clone, PartialEq, Eq)] | 266 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| 273 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 267 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 274 | pub enum StopBits { | 268 | pub enum StopBits { |
| 275 | /// 1 stop bit | 269 | /// 1 stop bit |
| @@ -293,7 +287,7 @@ impl From<u8> for StopBits { | |||
| 293 | } | 287 | } |
| 294 | 288 | ||
| 295 | /// Parity for LineCoding | 289 | /// Parity for LineCoding |
| 296 | #[derive(Copy, Clone, PartialEq, Eq)] | 290 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
| 297 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 291 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 298 | pub enum ParityType { | 292 | pub enum ParityType { |
| 299 | None = 0, | 293 | None = 0, |
| @@ -317,7 +311,7 @@ impl From<u8> for ParityType { | |||
| 317 | /// | 311 | /// |
| 318 | /// This is provided by the host for specifying the standard UART parameters such as baud rate. Can | 312 | /// This is provided by the host for specifying the standard UART parameters such as baud rate. Can |
| 319 | /// be ignored if you don't plan to interface with a physical UART. | 313 | /// be ignored if you don't plan to interface with a physical UART. |
| 320 | #[derive(Clone, Copy)] | 314 | #[derive(Clone, Copy, Debug)] |
| 321 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 315 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 322 | pub struct LineCoding { | 316 | pub struct LineCoding { |
| 323 | stop_bits: StopBits, | 317 | stop_bits: StopBits, |
diff --git a/embassy-usb-ncm/src/lib.rs b/embassy-usb/src/class/cdc_ncm.rs index e796af28f..a39b87e9b 100644 --- a/embassy-usb-ncm/src/lib.rs +++ b/embassy-usb/src/class/cdc_ncm.rs | |||
| @@ -1,15 +1,10 @@ | |||
| 1 | #![no_std] | ||
| 2 | |||
| 3 | // This mod MUST go first, so that the others see its macros. | ||
| 4 | pub(crate) mod fmt; | ||
| 5 | |||
| 6 | use core::intrinsics::copy_nonoverlapping; | 1 | use core::intrinsics::copy_nonoverlapping; |
| 7 | use core::mem::{size_of, MaybeUninit}; | 2 | use core::mem::{size_of, MaybeUninit}; |
| 8 | 3 | ||
| 9 | use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; | 4 | use crate::control::{self, ControlHandler, InResponse, OutResponse, Request}; |
| 10 | use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | 5 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; |
| 11 | use embassy_usb::types::*; | 6 | use crate::types::*; |
| 12 | use embassy_usb::Builder; | 7 | use crate::Builder; |
| 13 | 8 | ||
| 14 | /// This should be used as `device_class` when building the `UsbDevice`. | 9 | /// This should be used as `device_class` when building the `UsbDevice`. |
| 15 | pub const USB_CLASS_CDC: u8 = 0x02; | 10 | pub const USB_CLASS_CDC: u8 = 0x02; |
diff --git a/embassy-usb-hid/src/lib.rs b/embassy-usb/src/class/hid.rs index 5fee60bbc..4d1fa995f 100644 --- a/embassy-usb-hid/src/lib.rs +++ b/embassy-usb/src/class/hid.rs | |||
| @@ -1,24 +1,16 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | //! Implements HID functionality for a usb-device device. | ||
| 6 | |||
| 7 | // This mod MUST go first, so that the others see its macros. | ||
| 8 | pub(crate) mod fmt; | ||
| 9 | |||
| 10 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 11 | use core::ops::Range; | 2 | use core::ops::Range; |
| 12 | use core::sync::atomic::{AtomicUsize, Ordering}; | 3 | use core::sync::atomic::{AtomicUsize, Ordering}; |
| 13 | 4 | ||
| 14 | use embassy_usb::control::{ControlHandler, InResponse, OutResponse, Request, RequestType}; | ||
| 15 | use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | ||
| 16 | use embassy_usb::Builder; | ||
| 17 | #[cfg(feature = "usbd-hid")] | 5 | #[cfg(feature = "usbd-hid")] |
| 18 | use ssmarshal::serialize; | 6 | use ssmarshal::serialize; |
| 19 | #[cfg(feature = "usbd-hid")] | 7 | #[cfg(feature = "usbd-hid")] |
| 20 | use usbd_hid::descriptor::AsInputReport; | 8 | use usbd_hid::descriptor::AsInputReport; |
| 21 | 9 | ||
| 10 | use crate::control::{ControlHandler, InResponse, OutResponse, Request, RequestType}; | ||
| 11 | use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; | ||
| 12 | use crate::Builder; | ||
| 13 | |||
| 22 | const USB_CLASS_HID: u8 = 0x03; | 14 | const USB_CLASS_HID: u8 = 0x03; |
| 23 | const USB_SUBCLASS_NONE: u8 = 0x00; | 15 | const USB_SUBCLASS_NONE: u8 = 0x00; |
| 24 | const USB_PROTOCOL_NONE: u8 = 0x00; | 16 | const USB_PROTOCOL_NONE: u8 = 0x00; |
| @@ -205,9 +197,9 @@ pub enum ReadError { | |||
| 205 | Sync(Range<usize>), | 197 | Sync(Range<usize>), |
| 206 | } | 198 | } |
| 207 | 199 | ||
| 208 | impl From<embassy_usb::driver::EndpointError> for ReadError { | 200 | impl From<EndpointError> for ReadError { |
| 209 | fn from(val: embassy_usb::driver::EndpointError) -> Self { | 201 | fn from(val: EndpointError) -> Self { |
| 210 | use embassy_usb::driver::EndpointError::*; | 202 | use EndpointError::*; |
| 211 | match val { | 203 | match val { |
| 212 | BufferOverflow => ReadError::BufferOverflow, | 204 | BufferOverflow => ReadError::BufferOverflow, |
| 213 | Disabled => ReadError::Disabled, | 205 | Disabled => ReadError::Disabled, |
| @@ -438,7 +430,7 @@ impl<'d> ControlHandler for Control<'d> { | |||
| 438 | } | 430 | } |
| 439 | } | 431 | } |
| 440 | 432 | ||
| 441 | fn control_out(&mut self, req: embassy_usb::control::Request, data: &[u8]) -> OutResponse { | 433 | fn control_out(&mut self, req: Request, data: &[u8]) -> OutResponse { |
| 442 | trace!("HID control_out {:?} {=[u8]:x}", req, data); | 434 | trace!("HID control_out {:?} {=[u8]:x}", req, data); |
| 443 | if let RequestType::Class = req.request_type { | 435 | if let RequestType::Class = req.request_type { |
| 444 | match req.request { | 436 | match req.request { |
diff --git a/embassy-usb/src/class/mod.rs b/embassy-usb/src/class/mod.rs new file mode 100644 index 000000000..af27577a6 --- /dev/null +++ b/embassy-usb/src/class/mod.rs | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | pub mod cdc_acm; | ||
| 2 | pub mod cdc_ncm; | ||
| 3 | pub mod hid; | ||
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs index 3e5749a01..d6d0c6565 100644 --- a/embassy-usb/src/control.rs +++ b/embassy-usb/src/control.rs | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | //! USB control data types. | 1 | //! USB control data types. |
| 2 | use core::mem; | 2 | use core::mem; |
| 3 | 3 | ||
| 4 | use super::types::*; | 4 | use crate::driver::Direction; |
| 5 | use crate::types::StringIndex; | ||
| 5 | 6 | ||
| 6 | /// Control request type. | 7 | /// Control request type. |
| 7 | #[repr(u8)] | 8 | #[repr(u8)] |
| @@ -42,7 +43,7 @@ pub enum Recipient { | |||
| 42 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 43 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 43 | pub struct Request { | 44 | pub struct Request { |
| 44 | /// Direction of the request. | 45 | /// Direction of the request. |
| 45 | pub direction: UsbDirection, | 46 | pub direction: Direction, |
| 46 | /// Type of the request. | 47 | /// Type of the request. |
| 47 | pub request_type: RequestType, | 48 | pub request_type: RequestType, |
| 48 | /// Recipient of the request. | 49 | /// Recipient of the request. |
| @@ -105,7 +106,7 @@ impl Request { | |||
| 105 | let recipient = rt & 0b11111; | 106 | let recipient = rt & 0b11111; |
| 106 | 107 | ||
| 107 | Request { | 108 | Request { |
| 108 | direction: rt.into(), | 109 | direction: if rt & 0x80 == 0 { Direction::Out } else { Direction::In }, |
| 109 | request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, | 110 | request_type: unsafe { mem::transmute((rt >> 5) & 0b11) }, |
| 110 | recipient: if recipient <= 3 { | 111 | recipient: if recipient <= 3 { |
| 111 | unsafe { mem::transmute(recipient) } | 112 | unsafe { mem::transmute(recipient) } |
diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs index b94a4b161..497f03196 100644 --- a/embassy-usb/src/descriptor.rs +++ b/embassy-usb/src/descriptor.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | use super::builder::Config; | 1 | use crate::builder::Config; |
| 2 | use super::types::*; | 2 | use crate::driver::EndpointInfo; |
| 3 | use super::CONFIGURATION_VALUE; | 3 | use crate::types::*; |
| 4 | use crate::CONFIGURATION_VALUE; | ||
| 4 | 5 | ||
| 5 | /// Standard descriptor types | 6 | /// Standard descriptor types |
| 6 | #[allow(missing_docs)] | 7 | #[allow(missing_docs)] |
diff --git a/embassy-usb/src/descriptor_reader.rs b/embassy-usb/src/descriptor_reader.rs index 0a12b566c..d64bcb73b 100644 --- a/embassy-usb/src/descriptor_reader.rs +++ b/embassy-usb/src/descriptor_reader.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use crate::descriptor::descriptor_type; | 1 | use crate::descriptor::descriptor_type; |
| 2 | use crate::types::EndpointAddress; | 2 | use crate::driver::EndpointAddress; |
| 3 | 3 | ||
| 4 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 4 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
| 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index b165804ef..661b84119 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs | |||
| @@ -1,27 +1,27 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(type_alias_impl_trait)] | 2 | #![feature(type_alias_impl_trait)] |
| 4 | 3 | ||
| 5 | // This mod MUST go first, so that the others see its macros. | 4 | // This mod MUST go first, so that the others see its macros. |
| 6 | pub(crate) mod fmt; | 5 | pub(crate) mod fmt; |
| 7 | 6 | ||
| 7 | pub use embassy_usb_driver as driver; | ||
| 8 | |||
| 8 | mod builder; | 9 | mod builder; |
| 10 | pub mod class; | ||
| 9 | pub mod control; | 11 | pub mod control; |
| 10 | pub mod descriptor; | 12 | pub mod descriptor; |
| 11 | mod descriptor_reader; | 13 | mod descriptor_reader; |
| 12 | pub mod driver; | ||
| 13 | pub mod types; | 14 | pub mod types; |
| 14 | 15 | ||
| 15 | use embassy_futures::select::{select, Either}; | 16 | use embassy_futures::select::{select, Either}; |
| 16 | use heapless::Vec; | 17 | use heapless::Vec; |
| 17 | 18 | ||
| 18 | pub use self::builder::{Builder, Config}; | 19 | pub use crate::builder::{Builder, Config}; |
| 19 | use self::control::*; | 20 | use crate::control::*; |
| 20 | use self::descriptor::*; | 21 | use crate::descriptor::*; |
| 21 | use self::driver::{Bus, Driver, Event}; | ||
| 22 | use self::types::*; | ||
| 23 | use crate::descriptor_reader::foreach_endpoint; | 22 | use crate::descriptor_reader::foreach_endpoint; |
| 24 | use crate::driver::ControlPipe; | 23 | use crate::driver::{Bus, ControlPipe, Direction, Driver, EndpointAddress, Event}; |
| 24 | use crate::types::*; | ||
| 25 | 25 | ||
| 26 | /// The global state of the USB device. | 26 | /// The global state of the USB device. |
| 27 | /// | 27 | /// |
| @@ -248,11 +248,11 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { | |||
| 248 | async fn handle_control(&mut self, req: [u8; 8]) { | 248 | async fn handle_control(&mut self, req: [u8; 8]) { |
| 249 | let req = Request::parse(&req); | 249 | let req = Request::parse(&req); |
| 250 | 250 | ||
| 251 | trace!("control request: {:02x}", req); | 251 | trace!("control request: {:?}", req); |
| 252 | 252 | ||
| 253 | match req.direction { | 253 | match req.direction { |
| 254 | UsbDirection::In => self.handle_control_in(req).await, | 254 | Direction::In => self.handle_control_in(req).await, |
| 255 | UsbDirection::Out => self.handle_control_out(req).await, | 255 | Direction::Out => self.handle_control_out(req).await, |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | if self.inner.set_address_pending { | 258 | if self.inner.set_address_pending { |
diff --git a/embassy-usb/src/types.rs b/embassy-usb/src/types.rs index b8717ffa9..aeab063d1 100644 --- a/embassy-usb/src/types.rs +++ b/embassy-usb/src/types.rs | |||
| @@ -1,108 +1,3 @@ | |||
| 1 | /// Direction of USB traffic. Note that in the USB standard the direction is always indicated from | ||
| 2 | /// the perspective of the host, which is backward for devices, but the standard directions are used | ||
| 3 | /// for consistency. | ||
| 4 | /// | ||
| 5 | /// The values of the enum also match the direction bit used in endpoint addresses and control | ||
| 6 | /// request types. | ||
| 7 | #[repr(u8)] | ||
| 8 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 9 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 10 | pub enum UsbDirection { | ||
| 11 | /// Host to device (OUT) | ||
| 12 | Out = 0x00, | ||
| 13 | /// Device to host (IN) | ||
| 14 | In = 0x80, | ||
| 15 | } | ||
| 16 | |||
| 17 | impl From<u8> for UsbDirection { | ||
| 18 | fn from(value: u8) -> Self { | ||
| 19 | unsafe { core::mem::transmute(value & 0x80) } | ||
| 20 | } | ||
| 21 | } | ||
| 22 | |||
| 23 | /// USB endpoint transfer type. The values of this enum can be directly cast into `u8` to get the | ||
| 24 | /// transfer bmAttributes transfer type bits. | ||
| 25 | #[repr(u8)] | ||
| 26 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 27 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 28 | pub enum EndpointType { | ||
| 29 | /// Control endpoint. Used for device management. Only the host can initiate requests. Usually | ||
| 30 | /// used only endpoint 0. | ||
| 31 | Control = 0b00, | ||
| 32 | /// Isochronous endpoint. Used for time-critical unreliable data. Not implemented yet. | ||
| 33 | Isochronous = 0b01, | ||
| 34 | /// Bulk endpoint. Used for large amounts of best-effort reliable data. | ||
| 35 | Bulk = 0b10, | ||
| 36 | /// Interrupt endpoint. Used for small amounts of time-critical reliable data. | ||
| 37 | Interrupt = 0b11, | ||
| 38 | } | ||
| 39 | |||
| 40 | /// Type-safe endpoint address. | ||
| 41 | #[derive(Debug, Clone, Copy, Eq, PartialEq)] | ||
| 42 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 43 | pub struct EndpointAddress(u8); | ||
| 44 | |||
| 45 | impl From<u8> for EndpointAddress { | ||
| 46 | #[inline] | ||
| 47 | fn from(addr: u8) -> EndpointAddress { | ||
| 48 | EndpointAddress(addr) | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | impl From<EndpointAddress> for u8 { | ||
| 53 | #[inline] | ||
| 54 | fn from(addr: EndpointAddress) -> u8 { | ||
| 55 | addr.0 | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | impl EndpointAddress { | ||
| 60 | const INBITS: u8 = UsbDirection::In as u8; | ||
| 61 | |||
| 62 | /// Constructs a new EndpointAddress with the given index and direction. | ||
| 63 | #[inline] | ||
| 64 | pub fn from_parts(index: usize, dir: UsbDirection) -> Self { | ||
| 65 | EndpointAddress(index as u8 | dir as u8) | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Gets the direction part of the address. | ||
| 69 | #[inline] | ||
| 70 | pub fn direction(&self) -> UsbDirection { | ||
| 71 | if (self.0 & Self::INBITS) != 0 { | ||
| 72 | UsbDirection::In | ||
| 73 | } else { | ||
| 74 | UsbDirection::Out | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | /// Returns true if the direction is IN, otherwise false. | ||
| 79 | #[inline] | ||
| 80 | pub fn is_in(&self) -> bool { | ||
| 81 | (self.0 & Self::INBITS) != 0 | ||
| 82 | } | ||
| 83 | |||
| 84 | /// Returns true if the direction is OUT, otherwise false. | ||
| 85 | #[inline] | ||
| 86 | pub fn is_out(&self) -> bool { | ||
| 87 | (self.0 & Self::INBITS) == 0 | ||
| 88 | } | ||
| 89 | |||
| 90 | /// Gets the index part of the endpoint address. | ||
| 91 | #[inline] | ||
| 92 | pub fn index(&self) -> usize { | ||
| 93 | (self.0 & !Self::INBITS) as usize | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] | ||
| 98 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 99 | pub struct EndpointInfo { | ||
| 100 | pub addr: EndpointAddress, | ||
| 101 | pub ep_type: EndpointType, | ||
| 102 | pub max_packet_size: u16, | ||
| 103 | pub interval: u8, | ||
| 104 | } | ||
| 105 | |||
| 106 | /// A handle for a USB interface that contains its number. | 1 | /// A handle for a USB interface that contains its number. |
| 107 | #[derive(Copy, Clone, Eq, PartialEq)] | 2 | #[derive(Copy, Clone, Eq, PartialEq)] |
| 108 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 3 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs index 133a3e678..7a404a914 100644 --- a/examples/boot/application/nrf/src/bin/a.rs +++ b/examples/boot/application/nrf/src/bin/a.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![feature(generic_associated_types)] | ||
| 5 | #![feature(type_alias_impl_trait)] | 4 | #![feature(type_alias_impl_trait)] |
| 6 | 5 | ||
| 7 | use embassy_boot_nrf::FirmwareUpdater; | 6 | use embassy_boot_nrf::FirmwareUpdater; |
diff --git a/examples/boot/application/nrf/src/bin/b.rs b/examples/boot/application/nrf/src/bin/b.rs index 5394bf0c7..1373f277d 100644 --- a/examples/boot/application/nrf/src/bin/b.rs +++ b/examples/boot/application/nrf/src/bin/b.rs | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![feature(generic_associated_types)] | ||
| 5 | #![feature(type_alias_impl_trait)] | 4 | #![feature(type_alias_impl_trait)] |
| 6 | 5 | ||
| 7 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs index 9031997c2..8266206b3 100644 --- a/examples/boot/bootloader/nrf/src/main.rs +++ b/examples/boot/bootloader/nrf/src/main.rs | |||
| @@ -21,7 +21,7 @@ fn main() -> ! { | |||
| 21 | 21 | ||
| 22 | let mut bl = BootLoader::default(); | 22 | let mut bl = BootLoader::default(); |
| 23 | let start = bl.prepare(&mut SingleFlashConfig::new(&mut BootFlash::<_, 4096>::new( | 23 | let start = bl.prepare(&mut SingleFlashConfig::new(&mut BootFlash::<_, 4096>::new( |
| 24 | &mut WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, 5), | 24 | WatchdogFlash::start(Nvmc::new(p.NVMC), p.WDT, 5), |
| 25 | ))); | 25 | ))); |
| 26 | unsafe { bl.load(start) } | 26 | unsafe { bl.load(start) } |
| 27 | } | 27 | } |
diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index bb5d3e531..294464d1c 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs | |||
| @@ -20,10 +20,9 @@ fn main() -> ! { | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | let mut bl: BootLoader<ERASE_SIZE, WRITE_SIZE> = BootLoader::default(); | 22 | let mut bl: BootLoader<ERASE_SIZE, WRITE_SIZE> = BootLoader::default(); |
| 23 | let mut flash = Flash::unlock(p.FLASH); | 23 | let flash = Flash::unlock(p.FLASH); |
| 24 | let start = bl.prepare(&mut SingleFlashConfig::new( | 24 | let mut flash = BootFlash::<_, ERASE_SIZE, ERASE_VALUE>::new(flash); |
| 25 | &mut BootFlash::<_, ERASE_SIZE, ERASE_VALUE>::new(&mut flash), | 25 | let start = bl.prepare(&mut SingleFlashConfig::new(&mut flash)); |
| 26 | )); | ||
| 27 | core::mem::drop(flash); | 26 | core::mem::drop(flash); |
| 28 | unsafe { bl.load(start) } | 27 | unsafe { bl.load(start) } |
| 29 | } | 28 | } |
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs index 7d1ad87c8..cf8b2f808 100644 --- a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs +++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use core::future::poll_fn; | ||
| 5 | use core::task::Poll; | 6 | use core::task::Poll; |
| 6 | 7 | ||
| 7 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| @@ -46,7 +47,7 @@ async fn run2() { | |||
| 46 | 47 | ||
| 47 | #[embassy_executor::task] | 48 | #[embassy_executor::task] |
| 48 | async fn run3() { | 49 | async fn run3() { |
| 49 | futures::future::poll_fn(|cx| { | 50 | poll_fn(|cx| { |
| 50 | cx.waker().wake_by_ref(); | 51 | cx.waker().wake_by_ref(); |
| 51 | Poll::<()>::Pending | 52 | Poll::<()>::Pending |
| 52 | }) | 53 | }) |
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index dbc659cda..a5d340c69 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml | |||
| @@ -5,7 +5,7 @@ version = "0.1.0" | |||
| 5 | 5 | ||
| 6 | [features] | 6 | [features] |
| 7 | default = ["nightly"] | 7 | default = ["nightly"] |
| 8 | nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"] | 8 | nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net"] |
| 9 | 9 | ||
| 10 | [dependencies] | 10 | [dependencies] |
| 11 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 11 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| @@ -15,9 +15,6 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de | |||
| 15 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } | 15 | embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } |
| 16 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } | 16 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } |
| 17 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } | 17 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } |
| 18 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } | ||
| 19 | embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } | ||
| 20 | embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } | ||
| 21 | embedded-io = "0.3.0" | 18 | embedded-io = "0.3.0" |
| 22 | 19 | ||
| 23 | defmt = "0.3" | 20 | defmt = "0.3" |
diff --git a/examples/nrf/src/bin/executor_fairness_test.rs b/examples/nrf/src/bin/executor_fairness_test.rs index 9ae030d07..2a28f2763 100644 --- a/examples/nrf/src/bin/executor_fairness_test.rs +++ b/examples/nrf/src/bin/executor_fairness_test.rs | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use core::future::poll_fn; | ||
| 5 | use core::task::Poll; | 6 | use core::task::Poll; |
| 6 | 7 | ||
| 7 | use defmt::{info, unwrap}; | 8 | use defmt::{info, unwrap}; |
| @@ -26,7 +27,7 @@ async fn run2() { | |||
| 26 | 27 | ||
| 27 | #[embassy_executor::task] | 28 | #[embassy_executor::task] |
| 28 | async fn run3() { | 29 | async fn run3() { |
| 29 | futures::future::poll_fn(|cx| { | 30 | poll_fn(|cx| { |
| 30 | cx.waker().wake_by_ref(); | 31 | cx.waker().wake_by_ref(); |
| 31 | Poll::<()>::Pending | 32 | Poll::<()>::Pending |
| 32 | }) | 33 | }) |
diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs index 352660b59..de93a2b45 100644 --- a/examples/nrf/src/bin/usb_ethernet.rs +++ b/examples/nrf/src/bin/usb_ethernet.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::mem; | 5 | use core::mem; |
| @@ -16,8 +15,8 @@ use embassy_nrf::usb::{Driver, PowerUsb}; | |||
| 16 | use embassy_nrf::{interrupt, pac, peripherals}; | 15 | use embassy_nrf::{interrupt, pac, peripherals}; |
| 17 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 18 | use embassy_sync::channel::Channel; | 17 | use embassy_sync::channel::Channel; |
| 18 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 19 | use embassy_usb::{Builder, Config, UsbDevice}; | 19 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 20 | use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 21 | use embedded_io::asynch::Write; | 20 | use embedded_io::asynch::Write; |
| 22 | use static_cell::StaticCell; | 21 | use static_cell::StaticCell; |
| 23 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs index 7fdb0b685..76e198719 100644 --- a/examples/nrf/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf/src/bin/usb_hid_keyboard.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::mem; | 5 | use core::mem; |
| @@ -8,15 +7,16 @@ use core::sync::atomic::{AtomicBool, Ordering}; | |||
| 8 | 7 | ||
| 9 | use defmt::*; | 8 | use defmt::*; |
| 10 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_futures::join::join; | ||
| 11 | use embassy_futures::select::{select, Either}; | 11 | use embassy_futures::select::{select, Either}; |
| 12 | use embassy_nrf::gpio::{Input, Pin, Pull}; | 12 | use embassy_nrf::gpio::{Input, Pin, Pull}; |
| 13 | use embassy_nrf::usb::{Driver, PowerUsb}; | 13 | use embassy_nrf::usb::{Driver, PowerUsb}; |
| 14 | use embassy_nrf::{interrupt, pac}; | 14 | use embassy_nrf::{interrupt, pac}; |
| 15 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 15 | use embassy_sync::signal::Signal; | 16 | use embassy_sync::signal::Signal; |
| 17 | use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; | ||
| 16 | use embassy_usb::control::OutResponse; | 18 | use embassy_usb::control::OutResponse; |
| 17 | use embassy_usb::{Builder, Config, DeviceStateHandler}; | 19 | use embassy_usb::{Builder, Config, DeviceStateHandler}; |
| 18 | use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State}; | ||
| 19 | use futures::future::join; | ||
| 20 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; | 20 | use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 22 | 22 | ||
| @@ -67,7 +67,7 @@ async fn main(_spawner: Spawner) { | |||
| 67 | ); | 67 | ); |
| 68 | 68 | ||
| 69 | // Create classes on the builder. | 69 | // Create classes on the builder. |
| 70 | let config = embassy_usb_hid::Config { | 70 | let config = embassy_usb::class::hid::Config { |
| 71 | report_descriptor: KeyboardReport::desc(), | 71 | report_descriptor: KeyboardReport::desc(), |
| 72 | request_handler: Some(&request_handler), | 72 | request_handler: Some(&request_handler), |
| 73 | poll_ms: 60, | 73 | poll_ms: 60, |
| @@ -78,7 +78,7 @@ async fn main(_spawner: Spawner) { | |||
| 78 | // Build the builder. | 78 | // Build the builder. |
| 79 | let mut usb = builder.build(); | 79 | let mut usb = builder.build(); |
| 80 | 80 | ||
| 81 | let remote_wakeup = Signal::new(); | 81 | let remote_wakeup: Signal<CriticalSectionRawMutex, _> = Signal::new(); |
| 82 | 82 | ||
| 83 | // Run the USB device. | 83 | // Run the USB device. |
| 84 | let usb_fut = async { | 84 | let usb_fut = async { |
diff --git a/examples/nrf/src/bin/usb_hid_mouse.rs b/examples/nrf/src/bin/usb_hid_mouse.rs index 7cd2ece17..4916a38d4 100644 --- a/examples/nrf/src/bin/usb_hid_mouse.rs +++ b/examples/nrf/src/bin/usb_hid_mouse.rs | |||
| @@ -1,19 +1,18 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::mem; | 5 | use core::mem; |
| 7 | 6 | ||
| 8 | use defmt::*; | 7 | use defmt::*; |
| 9 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | ||
| 10 | use embassy_nrf::usb::{Driver, PowerUsb}; | 10 | use embassy_nrf::usb::{Driver, PowerUsb}; |
| 11 | use embassy_nrf::{interrupt, pac}; | 11 | use embassy_nrf::{interrupt, pac}; |
| 12 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 13 | use embassy_usb::control::OutResponse; | 14 | use embassy_usb::control::OutResponse; |
| 14 | use embassy_usb::{Builder, Config}; | 15 | use embassy_usb::{Builder, Config}; |
| 15 | use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 16 | use futures::future::join; | ||
| 17 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 16 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 19 | 18 | ||
| @@ -60,7 +59,7 @@ async fn main(_spawner: Spawner) { | |||
| 60 | ); | 59 | ); |
| 61 | 60 | ||
| 62 | // Create classes on the builder. | 61 | // Create classes on the builder. |
| 63 | let config = embassy_usb_hid::Config { | 62 | let config = embassy_usb::class::hid::Config { |
| 64 | report_descriptor: MouseReport::desc(), | 63 | report_descriptor: MouseReport::desc(), |
| 65 | request_handler: Some(&request_handler), | 64 | request_handler: Some(&request_handler), |
| 66 | poll_ms: 60, | 65 | poll_ms: 60, |
diff --git a/examples/nrf/src/bin/usb_serial.rs b/examples/nrf/src/bin/usb_serial.rs index a68edb329..7c9c4184b 100644 --- a/examples/nrf/src/bin/usb_serial.rs +++ b/examples/nrf/src/bin/usb_serial.rs | |||
| @@ -1,18 +1,17 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::mem; | 5 | use core::mem; |
| 7 | 6 | ||
| 8 | use defmt::{info, panic}; | 7 | use defmt::{info, panic}; |
| 9 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_futures::join::join; | ||
| 10 | use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply}; | 10 | use embassy_nrf::usb::{Driver, Instance, PowerUsb, UsbSupply}; |
| 11 | use embassy_nrf::{interrupt, pac}; | 11 | use embassy_nrf::{interrupt, pac}; |
| 12 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 12 | use embassy_usb::driver::EndpointError; | 13 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::{Builder, Config}; | 14 | use embassy_usb::{Builder, Config}; |
| 14 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 15 | use futures::future::join; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 16 | ||
| 18 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs index d62d7e520..93efc2fe6 100644 --- a/examples/nrf/src/bin/usb_serial_multitask.rs +++ b/examples/nrf/src/bin/usb_serial_multitask.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::mem; | 5 | use core::mem; |
| @@ -9,9 +8,9 @@ use defmt::{info, panic, unwrap}; | |||
| 9 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 10 | use embassy_nrf::usb::{Driver, PowerUsb}; | 9 | use embassy_nrf::usb::{Driver, PowerUsb}; |
| 11 | use embassy_nrf::{interrupt, pac, peripherals}; | 10 | use embassy_nrf::{interrupt, pac, peripherals}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 12 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::{Builder, Config, UsbDevice}; | 13 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 14 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 15 | use static_cell::StaticCell; | 14 | use static_cell::StaticCell; |
| 16 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 16 | ||
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 18a92b094..3c8f923e7 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -8,11 +8,10 @@ version = "0.1.0" | |||
| 8 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } | 8 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } |
| 9 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } | 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } |
| 11 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] } | 11 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } |
| 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 12 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 13 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } | ||
| 14 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } |
| 15 | embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] } | 14 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 16 | 15 | ||
| 17 | defmt = "0.3" | 16 | defmt = "0.3" |
| 18 | defmt-rtt = "0.3" | 17 | defmt-rtt = "0.3" |
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 2df7f62f6..1057fe7fd 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::sync::atomic::{AtomicBool, Ordering}; | 5 | use core::sync::atomic::{AtomicBool, Ordering}; |
| @@ -14,8 +13,8 @@ use embassy_rp::usb::Driver; | |||
| 14 | use embassy_rp::{interrupt, peripherals}; | 13 | use embassy_rp::{interrupt, peripherals}; |
| 15 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 14 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 16 | use embassy_sync::channel::Channel; | 15 | use embassy_sync::channel::Channel; |
| 16 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 17 | use embassy_usb::{Builder, Config, UsbDevice}; | 17 | use embassy_usb::{Builder, Config, UsbDevice}; |
| 18 | use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 19 | use embedded_io::asynch::Write; | 18 | use embedded_io::asynch::Write; |
| 20 | use static_cell::StaticCell; | 19 | use static_cell::StaticCell; |
| 21 | use {defmt_rtt as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _}; |
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index 74be1f598..b7d6493b4 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs | |||
| @@ -1,16 +1,15 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use defmt::{info, panic}; | 5 | use defmt::{info, panic}; |
| 7 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 8 | use embassy_rp::interrupt; | 8 | use embassy_rp::interrupt; |
| 9 | use embassy_rp::usb::{Driver, Instance}; | 9 | use embassy_rp::usb::{Driver, Instance}; |
| 10 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 10 | use embassy_usb::driver::EndpointError; | 11 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::{Builder, Config}; | 12 | use embassy_usb::{Builder, Config}; |
| 12 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 13 | use futures::future::join; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 14 | ||
| 16 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 33ac63db1..e6553789a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -9,7 +9,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||
| 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } | 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } |
| 11 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 11 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 12 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } | 12 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 13 | 13 | ||
| 14 | defmt = "0.3" | 14 | defmt = "0.3" |
| 15 | defmt-rtt = "0.3" | 15 | defmt-rtt = "0.3" |
diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs index a9c46068f..ad92cdeb2 100644 --- a/examples/stm32f1/src/bin/usb_serial.rs +++ b/examples/stm32f1/src/bin/usb_serial.rs | |||
| @@ -4,15 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{panic, *}; | 5 | use defmt::{panic, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::time::Hertz; | 9 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 10 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, Config}; | 11 | use embassy_stm32::{interrupt, Config}; |
| 11 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 12 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 15 | use embassy_usb::Builder; |
| 14 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 15 | use futures::future::join; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 208f39080..f5b0b880c 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml | |||
| @@ -9,8 +9,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||
| 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } | 10 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } |
| 11 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 11 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 12 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } | 12 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 13 | embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] } | ||
| 14 | 13 | ||
| 15 | defmt = "0.3" | 14 | defmt = "0.3" |
| 16 | defmt-rtt = "0.3" | 15 | defmt-rtt = "0.3" |
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs index d3702fc35..f6d27c860 100644 --- a/examples/stm32f3/src/bin/usb_serial.rs +++ b/examples/stm32f3/src/bin/usb_serial.rs | |||
| @@ -4,15 +4,15 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{panic, *}; | 5 | use defmt::{panic, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | 8 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 8 | use embassy_stm32::time::mhz; | 9 | use embassy_stm32::time::mhz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 10 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{interrupt, Config}; | 11 | use embassy_stm32::{interrupt, Config}; |
| 11 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 13 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 12 | use embassy_usb::driver::EndpointError; | 14 | use embassy_usb::driver::EndpointError; |
| 13 | use embassy_usb::Builder; | 15 | use embassy_usb::Builder; |
| 14 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 15 | use futures::future::join; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 17 | 17 | ||
| 18 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs index cc3e4e3ca..6d7c168d5 100644 --- a/examples/stm32h7/src/bin/signal.rs +++ b/examples/stm32h7/src/bin/signal.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{info, unwrap}; | 5 | use defmt::{info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 7 | use embassy_sync::signal::Signal; | 8 | use embassy_sync::signal::Signal; |
| 8 | use embassy_time::{Duration, Timer}; | 9 | use embassy_time::{Duration, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 11 | ||
| 11 | static SIGNAL: Signal<u32> = Signal::new(); | 12 | static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new(); |
| 12 | 13 | ||
| 13 | #[embassy_executor::task] | 14 | #[embassy_executor::task] |
| 14 | async fn my_sending_task() { | 15 | async fn my_sending_task() { |
diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs index 00ff67f3f..27d7c29c2 100644 --- a/examples/stm32l0/src/bin/lorawan.rs +++ b/examples/stm32l0/src/bin/lorawan.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | #![no_main] | 3 | #![no_main] |
| 4 | #![macro_use] | 4 | #![macro_use] |
| 5 | #![allow(dead_code)] | 5 | #![allow(dead_code)] |
| 6 | #![feature(generic_associated_types)] | ||
| 7 | #![feature(type_alias_impl_trait)] | 6 | #![feature(type_alias_impl_trait)] |
| 8 | 7 | ||
| 9 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index c451bd221..9ebab6476 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml | |||
| @@ -11,10 +11,8 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature | |||
| 11 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 11 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 12 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } | 12 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } |
| 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 13 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 14 | embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } | ||
| 15 | embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"] } | ||
| 16 | embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"] } | ||
| 17 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } | 14 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } |
| 15 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 18 | usbd-hid = "0.6.0" | 16 | usbd-hid = "0.6.0" |
| 19 | 17 | ||
| 20 | defmt = "0.3" | 18 | defmt = "0.3" |
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 2c8706e41..4f36d3f5a 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use core::sync::atomic::{AtomicBool, Ordering}; | 5 | use core::sync::atomic::{AtomicBool, Ordering}; |
| @@ -16,8 +15,8 @@ use embassy_stm32::usb::Driver; | |||
| 16 | use embassy_stm32::{interrupt, Config}; | 15 | use embassy_stm32::{interrupt, Config}; |
| 17 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| 18 | use embassy_sync::channel::Channel; | 17 | use embassy_sync::channel::Channel; |
| 18 | use embassy_usb::class::cdc_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 19 | use embassy_usb::{Builder, UsbDevice}; | 19 | use embassy_usb::{Builder, UsbDevice}; |
| 20 | use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; | ||
| 21 | use embedded_io::asynch::Write; | 20 | use embedded_io::asynch::Write; |
| 22 | use rand_core::RngCore; | 21 | use rand_core::RngCore; |
| 23 | use static_cell::StaticCell; | 22 | use static_cell::StaticCell; |
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index 7d763e7fd..d38ed7496 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs | |||
| @@ -1,18 +1,17 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(generic_associated_types)] | ||
| 4 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 5 | 4 | ||
| 6 | use defmt::*; | 5 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 8 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 9 | use embassy_stm32::usb::Driver; | 9 | use embassy_stm32::usb::Driver; |
| 10 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{interrupt, Config}; |
| 11 | use embassy_time::{Duration, Timer}; | 11 | use embassy_time::{Duration, Timer}; |
| 12 | use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 12 | use embassy_usb::control::OutResponse; | 13 | use embassy_usb::control::OutResponse; |
| 13 | use embassy_usb::Builder; | 14 | use embassy_usb::Builder; |
| 14 | use embassy_usb_hid::{HidWriter, ReportId, RequestHandler, State}; | ||
| 15 | use futures::future::join; | ||
| 16 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; | 15 | use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 16 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 17 | ||
| @@ -56,7 +55,7 @@ async fn main(_spawner: Spawner) { | |||
| 56 | ); | 55 | ); |
| 57 | 56 | ||
| 58 | // Create classes on the builder. | 57 | // Create classes on the builder. |
| 59 | let config = embassy_usb_hid::Config { | 58 | let config = embassy_usb::class::hid::Config { |
| 60 | report_descriptor: MouseReport::desc(), | 59 | report_descriptor: MouseReport::desc(), |
| 61 | request_handler: Some(&request_handler), | 60 | request_handler: Some(&request_handler), |
| 62 | poll_ms: 60, | 61 | poll_ms: 60, |
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs index b576a7353..7562a4e96 100644 --- a/examples/stm32l5/src/bin/usb_serial.rs +++ b/examples/stm32l5/src/bin/usb_serial.rs | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{panic, *}; | 5 | use defmt::{panic, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 7 | use embassy_stm32::rcc::*; | 8 | use embassy_stm32::rcc::*; |
| 8 | use embassy_stm32::usb::{Driver, Instance}; | 9 | use embassy_stm32::usb::{Driver, Instance}; |
| 9 | use embassy_stm32::{interrupt, Config}; | 10 | use embassy_stm32::{interrupt, Config}; |
| 11 | use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; | ||
| 10 | use embassy_usb::driver::EndpointError; | 12 | use embassy_usb::driver::EndpointError; |
| 11 | use embassy_usb::Builder; | 13 | use embassy_usb::Builder; |
| 12 | use embassy_usb_serial::{CdcAcmClass, State}; | ||
| 13 | use futures::future::join; | ||
| 14 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 15 | 15 | ||
| 16 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 9143e64da..7f34dd306 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![allow(dead_code)] | 4 | #![allow(dead_code)] |
| 5 | #![feature(generic_associated_types)] | ||
| 6 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
| 7 | 6 | ||
| 8 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
diff --git a/examples/stm32wl/src/bin/subghz.rs b/examples/stm32wl/src/bin/subghz.rs index 8f674d796..32c8b5515 100644 --- a/examples/stm32wl/src/bin/subghz.rs +++ b/examples/stm32wl/src/bin/subghz.rs | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![allow(dead_code)] | 4 | #![allow(dead_code)] |
| 5 | #![feature(generic_associated_types)] | ||
| 6 | #![feature(type_alias_impl_trait)] | 5 | #![feature(type_alias_impl_trait)] |
| 7 | 6 | ||
| 8 | use defmt::*; | 7 | use defmt::*; |
| @@ -13,6 +12,7 @@ use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | |||
| 13 | use embassy_stm32::interrupt; | 12 | use embassy_stm32::interrupt; |
| 14 | use embassy_stm32::interrupt::{Interrupt, InterruptExt}; | 13 | use embassy_stm32::interrupt::{Interrupt, InterruptExt}; |
| 15 | use embassy_stm32::subghz::*; | 14 | use embassy_stm32::subghz::*; |
| 15 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 16 | use embassy_sync::signal::Signal; | 16 | use embassy_sync::signal::Signal; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
| @@ -65,7 +65,7 @@ async fn main(_spawner: Spawner) { | |||
| 65 | let button = Input::new(p.PA0, Pull::Up); | 65 | let button = Input::new(p.PA0, Pull::Up); |
| 66 | let mut pin = ExtiInput::new(button, p.EXTI0); | 66 | let mut pin = ExtiInput::new(button, p.EXTI0); |
| 67 | 67 | ||
| 68 | static IRQ_SIGNAL: Signal<()> = Signal::new(); | 68 | static IRQ_SIGNAL: Signal<CriticalSectionRawMutex, ()> = Signal::new(); |
| 69 | let radio_irq = interrupt::take!(SUBGHZ_RADIO); | 69 | let radio_irq = interrupt::take!(SUBGHZ_RADIO); |
| 70 | radio_irq.set_handler(|_| { | 70 | radio_irq.set_handler(|_| { |
| 71 | IRQ_SIGNAL.signal(()); | 71 | IRQ_SIGNAL.signal(()); |
diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f5e342edc..1ec19e58b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # Before upgrading check that everything is available on all tier1 targets here: | 1 | # Before upgrading check that everything is available on all tier1 targets here: |
| 2 | # https://rust-lang.github.io/rustup-components-history | 2 | # https://rust-lang.github.io/rustup-components-history |
| 3 | [toolchain] | 3 | [toolchain] |
| 4 | channel = "nightly-2022-08-16" | 4 | channel = "nightly-2022-09-22" |
| 5 | components = [ "rust-src", "rustfmt" ] | 5 | components = [ "rust-src", "rustfmt" ] |
| 6 | targets = [ | 6 | targets = [ |
| 7 | "thumbv7em-none-eabi", | 7 | "thumbv7em-none-eabi", |
diff --git a/tests/rp/.cargo/config.toml b/tests/rp/.cargo/config.toml index 0330025e4..9611db3a0 100644 --- a/tests/rp/.cargo/config.toml +++ b/tests/rp/.cargo/config.toml | |||
| @@ -3,7 +3,7 @@ build-std = ["core"] | |||
| 3 | build-std-features = ["panic_immediate_abort"] | 3 | build-std-features = ["panic_immediate_abort"] |
| 4 | 4 | ||
| 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 5 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 6 | #runner = "teleprobe client run --target bluepill-stm32f103c8 --elf" | 6 | #runner = "teleprobe client run --target rpi-pico --elf" |
| 7 | runner = "teleprobe local run --chip RP2040 --elf" | 7 | runner = "teleprobe local run --chip RP2040 --elf" |
| 8 | 8 | ||
| 9 | rustflags = [ | 9 | rustflags = [ |
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 70fd95557..503373759 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml | |||
| @@ -7,7 +7,8 @@ version = "0.1.0" | |||
| 7 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } | 7 | embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } |
| 8 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } | 8 | embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } |
| 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } | 9 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } |
| 10 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits"] } | 10 | embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver"] } |
| 11 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 11 | 12 | ||
| 12 | defmt = "0.3.0" | 13 | defmt = "0.3.0" |
| 13 | defmt-rtt = "0.3.0" | 14 | defmt-rtt = "0.3.0" |
diff --git a/tests/rp/src/bin/gpio_async.rs b/tests/rp/src/bin/gpio_async.rs index 1eeaac1f6..f20b8fcbd 100644 --- a/tests/rp/src/bin/gpio_async.rs +++ b/tests/rp/src/bin/gpio_async.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{assert, *}; | 5 | use defmt::{assert, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | ||
| 7 | use embassy_rp::gpio::{Input, Level, Output, Pull}; | 8 | use embassy_rp::gpio::{Input, Level, Output, Pull}; |
| 8 | use embassy_time::{Duration, Instant, Timer}; | 9 | use embassy_time::{Duration, Instant, Timer}; |
| 9 | use futures::future::join; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 11 | ||
| 12 | #[embassy_executor::main] | 12 | #[embassy_executor::main] |
