通常情况下,Intel Microcode 都是以 INC 文件 Release 的,并且官方提供了INC转PDB的工具。但是一些情况下,我们拿到的是 PDB 格式,这时候可以使用这里提供的反向转换工具,将PDB 重新转为 INC格式。
有兴趣的朋友可以先找一个INC文件,然后转为 PDB文件,再使用这里的工具将PDB转为 INC ,然后比较前后文件内容以便验证工具正确性。
这次介绍的是如何在 CH32V307上通过 Arduino 编程,从 IIS 接口输出一个正弦波然后通过 NS4168 播放出来。关于 NS4168的介绍,可以在【参考1】看到。
线路方面:
B12(I2S2_WS)连接到 LRCLK
B13(I2S2_CK) 连接到 BCKL
B15(I2S2_SD)连接到 SDAT
同时特别提醒 NS4168 的CTRL 需要连接 3.3V
之后,给 Ch32v307烧录如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | //#include "ch32v30x_spi.h" /* Global Variable */ #define Len 48 * 16 * 2 u16 I2S2_Tx[Len] = { 16383 , 16383 , 20660 , 20660 , 24864 , 24864 , 28922 , 28922 , 32767 , 32767 , - 29206 , - 29206 , - 25983 , - 25983 , - 23157 , - 23157 , - 20776 , - 20776 , - 18880 , - 18880 , - 17502 , - 17502 , - 16666 , - 16666 , - 16385 , - 16385 , - 16665 , - 16665 , - 17501 , - 17501 , - 18879 , - 18879 , - 20774 , - 20774 , - 23155 , - 23155 , - 25981 , - 25981 , - 29203 , - 29203 , - 32767 , - 32767 , 28925 , 28925 , 24867 , 24867 , 20663 , 20663 , 16386 , 16386 , 12109 , 12109 , 7906 , 7906 , 3847 , 3847 , 3 , 3 , - 3560 , - 3560 , - 6783 , - 6783 , - 9610 , - 9610 , - 11991 , - 11991 , - 13887 , - 13887 , - 15266 , - 15266 , - 16102 , - 16102 , - 16383 , - 16383 , - 16104 , - 16104 , - 15268 , - 15268 , - 13891 , - 13891 , - 11996 , - 11996 , - 9615 , - 9615 , - 6790 , - 6790 , - 3568 , - 3568 , - 4 , - 4 , 3838 , 3838 , 7897 , 7897 , 12100 , 12100 , 16377 , 16377 , 20654 , 20654 , 24858 , 24858 , 28917 , 28917 , 32761 , 32761 , - 29210 , - 29210 , - 25987 , - 25987 , - 23161 , - 23161 , - 20779 , - 20779 , - 18882 , - 18882 , - 17504 , - 17504 , - 16667 , - 16667 , - 16385 , - 16385 , - 16665 , - 16665 , - 17500 , - 17500 , - 18876 , - 18876 , - 20771 , - 20771 , - 23152 , - 23152 , - 25977 , - 25977 , - 29198 , - 29198 , - 32762 , - 32762 , 28931 , 28931 , 24873 , 24873 , 20669 , 20669 , 16392 , 16392 , 12115 , 12115 , 7911 , 7911 , 3852 , 3852 , 8 , 8 , - 3556 , - 3556 , - 6779 , - 6779 , - 9606 , - 9606 , - 11988 , - 11988 , - 13885 , - 13885 , - 15264 , - 15264 , - 16102 , - 16102 , - 16383 , - 16383 , - 16104 , - 16104 , - 15270 , - 15270 , - 13893 , - 13893 , - 11999 , - 11999 , - 9619 , - 9619 , - 6794 , - 6794 , - 3572 , - 3572 , - 10 , - 10 , 3833 , 3833 , 7891 , 7891 , 12094 , 12094 , 16371 , 16371 , 20648 , 20648 , 24852 , 24852 , 28911 , 28911 , 32756 , 32756 , - 29215 , - 29215 , - 25992 , - 25992 , - 23164 , - 23164 , - 20782 , - 20782 , - 18885 , - 18885 , - 17505 , - 17505 , - 16667 , - 16667 , - 16385 , - 16385 , - 16664 , - 16664 , - 17498 , - 17498 , - 18874 , - 18874 , - 20768 , - 20768 , - 23148 , - 23148 , - 25972 , - 25972 , - 29194 , - 29194 , - 32756 , - 32756 , 28937 , 28937 , 24879 , 24879 , 20675 , 20675 , 16398 , 16398 , 12121 , 12121 , 7917 , 7917 , 3858 , 3858 , 13 , 13 , - 3551 , - 3551 , - 6775 , - 6775 , - 9602 , - 9602 , - 11985 , - 11985 , - 13883 , - 13883 , - 15262 , - 15262 , - 16101 , - 16101 , - 16383 , - 16383 , - 16105 , - 16105 , - 15271 , - 15271 , - 13896 , - 13896 , - 12002 , - 12002 , - 9623 , - 9623 , - 6798 , - 6798 , - 3577 , - 3577 , - 15 , - 15 , 3827 , 3827 , 7885 , 7885 , 12088 , 12088 , 16365 , 16365 , 20642 , 20642 , 24846 , 24846 , 28906 , 28906 , 32751 , 32751 , - 29220 , - 29220 , - 25996 , - 25996 , - 23168 , - 23168 , - 20785 , - 20785 , - 18887 , - 18887 , - 17507 , - 17507 , - 16668 , - 16668 , - 16385 , - 16385 , - 16663 , - 16663 , - 17497 , - 17497 , - 18872 , - 18872 , - 20765 , - 20765 , - 23144 , - 23144 , - 25968 , - 25968 , - 29189 , - 29189 , - 32751 , - 32751 , 28942 , 28942 , 24884 , 24884 , 20681 , 20681 , 16405 , 16405 , 12127 , 12127 , 7923 , 7923 , 3864 , 3864 , 18 , 18 , - 3546 , - 3546 , - 6770 , - 6770 , - 9598 , - 9598 , - 11982 , - 11982 , - 13880 , - 13880 , - 15261 , - 15261 , - 16100 , - 16100 , - 16383 , - 16383 , - 16106 , - 16106 , - 15273 , - 15273 , - 13898 , - 13898 , - 12005 , - 12005 , - 9626 , - 9626 , - 6803 , - 6803 , - 3582 , - 3582 , - 20 , - 20 , 3822 , 3822 , 7879 , 7879 , 12082 , 12082 , 16359 , 16359 , 20636 , 20636 , 24840 , 24840 , 28900 , 28900 , 32746 , 32746 , - 29225 , - 29225 , - 26000 , - 26000 , - 23172 , - 23172 , - 20788 , - 20788 , - 18889 , - 18889 , - 17508 , - 17508 , - 16669 , - 16669 , - 16385 , - 16385 , - 16662 , - 16662 , - 17495 , - 17495 , - 18870 , - 18870 , - 20762 , - 20762 , - 23140 , - 23140 , - 25964 , - 25964 , - 29184 , - 29184 , - 32746 , - 32746 , 28948 , 28948 , 24890 , 24890 , 20687 , 20687 , 16411 , 16411 , 12133 , 12133 , 7929 , 7929 , 3869 , 3869 , 24 , 24 , - 3541 , - 3541 , - 6766 , - 6766 , - 9595 , - 9595 , - 11979 , - 11979 , - 13878 , - 13878 , - 15259 , - 15259 , - 16099 , - 16099 , - 16383 , - 16383 , - 16107 , - 16107 , - 15274 , - 15274 , - 13900 , - 13900 , - 12008 , - 12008 , - 9630 , - 9630 , - 6807 , - 6807 , - 3587 , - 3587 , - 25 , - 25 , 3816 , 3816 , 7873 , 7873 , 12076 , 12076 , 16353 , 16353 , 20630 , 20630 , 24835 , 24835 , 28894 , 28894 , 32740 , 32740 , - 29230 , - 29230 , - 26005 , - 26005 , - 23176 , - 23176 , - 20791 , - 20791 , - 18892 , - 18892 , - 17510 , - 17510 , - 16670 , - 16670 , - 16385 , - 16385 , - 16661 , - 16661 , - 17493 , - 17493 , - 18867 , - 18867 , - 20759 , - 20759 , - 23137 , - 23137 , - 25960 , - 25960 , - 29179 , - 29179 , - 32741 , - 32741 , 28953 , 28953 , 24896 , 24896 , 20693 , 20693 , 16417 , 16417 , 12139 , 12139 , 7935 , 7935 , 3875 , 3875 , 29 , 29 , - 3536 , - 3536 , - 6762 , - 6762 , - 9591 , - 9591 , - 11976 , - 11976 , - 13876 , - 13876 , - 15258 , - 15258 , - 16098 , - 16098 , - 16383 , - 16383 , - 16107 , - 16107 , - 15276 , - 15276 , - 13902 , - 13902 , - 12011 , - 12011 , - 9634 , - 9634 , - 6811 , - 6811 , - 3592 , - 3592 , - 31 , - 31 , 3810 , 3810 , 7867 , 7867 , 12070 , 12070 , 16347 , 16347 , 20624 , 20624 , 24829 , 24829 , 28889 , 28889 , 32735 , 32735 , - 29235 , - 29235 , - 26009 , - 26009 , - 23179 , - 23179 , - 20794 , - 20794 , - 18894 , - 18894 , - 17512 , - 17512 , - 16671 , - 16671 , - 16385 , - 16385 , - 16661 , - 16661 , - 17492 , - 17492 , - 18865 , - 18865 , - 20756 , - 20756 , - 23133 , - 23133 , - 25955 , - 25955 , - 29174 , - 29174 , - 32735 , - 32735 , 28959 , 28959 , 24902 , 24902 , 20699 , 20699 , 16423 , 16423 , 12145 , 12145 , 7941 , 7941 , 3880 , 3880 , 34 , 34 , - 3532 , - 3532 , - 6757 , - 6757 , - 9587 , - 9587 , - 11973 , - 11973 , - 13873 , - 13873 , - 15256 , - 15256 , - 16098 , - 16098 , - 16383 , - 16383 , - 16108 , - 16108 , - 15277 , - 15277 , - 13905 , - 13905 , - 12014 , - 12014 , - 9637 , - 9637 , - 6815 , - 6815 , - 3597 , - 3597 , - 36 , - 36 , 3805 , 3805 , 7862 , 7862 , 12064 , 12064 , 16341 , 16341 , 20618 , 20618 , 24823 , 24823 , 28883 , 28883 , 32730 , 32730 , - 29239 , - 29239 , - 26013 , - 26013 , - 23183 , - 23183 , - 20797 , - 20797 , - 18896 , - 18896 , - 17513 , - 17513 , - 16671 , - 16671 , - 16385 , - 16385 , - 16660 , - 16660 , - 17490 , - 17490 , - 18863 , - 18863 , - 20753 , - 20753 , - 23129 , - 23129 , - 25951 , - 25951 , - 29170 , - 29170 , - 32730 , - 32730 , 28965 , 28965 , 24908 , 24908 , 20705 , 20705 , 16429 , 16429 , 12152 , 12152 , 7947 , 7947 , 3886 , 3886 , 39 , 39 , - 3527 , - 3527 , - 6753 , - 6753 , - 9584 , - 9584 , - 11970 , - 11970 , - 13871 , - 13871 , - 15255 , - 15255 , - 16097 , - 16097 , - 16383 , - 16383 , - 16109 , - 16109 , - 15279 , - 15279 , - 13907 , - 13907 , - 12017 , - 12017 , - 9641 , - 9641 , - 6820 , - 6820 , - 3601 , - 3601 , - 41 , - 41 , 3799 , 3799 , 7856 , 7856 , 12058 , 12058 , 16335 , 16335 , 20612 , 20612 , 24817 , 24817 , 28878 , 28878 , 32724 , 32724 , - 29244 , - 29244 , - 26018 , - 26018 , - 23187 , - 23187 , - 20800 , - 20800 , - 18899 , - 18899 , - 17515 , - 17515 , - 16672 , - 16672 , - 16385 , - 16385 , - 16659 , - 16659 , - 17489 , - 17489 , - 18860 , - 18860 , - 20750 , - 20750 , - 23126 , - 23126 , - 25947 , - 25947 , - 29165 , - 29165 , - 32725 , - 32725 , 28970 , 28970 , 24914 , 24914 , 20711 , 20711 , 16435 , 16435 , 12158 , 12158 , 7953 , 7953 , 3892 , 3892 , 45 , 45 , - 3522 , - 3522 , - 6749 , - 6749 , - 9580 , - 9580 , - 11967 , - 11967 , - 13869 , - 13869 , - 15253 , - 15253 , - 16096 , - 16096 , - 16383 , - 16383 , - 16110 , - 16110 , - 15280 , - 15280 , - 13909 , - 13909 , - 12020 , - 12020 , - 9645 , - 9645 , - 6824 , - 6824 , - 3606 , - 3606 , - 46 , - 46 , 3794 , 3794 , 7850 , 7850 , 12052 , 12052 , 16329 , 16329 , 20606 , 20606 , 24811 , 24811 , 28872 , 28872 , 32719 , 32719 , - 29249 , - 29249 , - 26022 , - 26022 , - 23190 , - 23190 , - 20803 , - 20803 , - 18901 , - 18901 , - 17516 , - 17516 , - 16673 , - 16673 , - 16385 , - 16385 , - 16658 , - 16658 , - 17487 , - 17487 , - 18858 , - 18858 , - 20747 , - 20747 , - 23122 , - 23122 , - 25942 , - 25942 , - 29160 , - 29160 , - 32720 , - 32720 , 28976 , 28976 , 24920 , 24920 , 20717 , 20717 , 16441 , 16441 , 12164 , 12164 , 7958 , 7958 , 3897 , 3897 , 50 , 50 , - 3517 , - 3517 , - 6745 , - 6745 , - 9576 , - 9576 , - 11964 , - 11964 , - 13866 , - 13866 , - 15251 , - 15251 , - 16095 , - 16095 , - 16383 , - 16383 , - 16111 , - 16111 , - 15282 , - 15282 , - 13912 , - 13912 , - 12023 , - 12023 , - 9648 , - 9648 , - 6828 , - 6828 , - 3611 , - 3611 , - 52 , - 52 , 3788 , 3788 , 7844 , 7844 , 12046 , 12046 , 16323 , 16323 , 20600 , 20600 , 24805 , 24805 , 28866 , 28866 , 32714 , 32714 , - 29254 , - 29254 , - 26026 , - 26026 , - 23194 , - 23194 , - 20806 , - 20806 , - 18903 , - 18903 , - 17518 , - 17518 , - 16674 , - 16674 , - 16385 , - 16385 , - 16657 , - 16657 , - 17486 , - 17486 , - 18856 , - 18856 , - 20744 , - 20744 , - 23118 , - 23118 , - 25938 , - 25938 , - 29155 , - 29155 , - 32714 , - 32714 , 28981 , 28981 , 24925 , 24925 , 20723 , 20723 , 16447 , 16447 , 12170 , 12170 , 7964 , 7964 , 3903 , 3903 , 55 , 55 , - 3512 , - 3512 , - 6740 , - 6740 , - 9573 , - 9573 , - 11961 , - 11961 , - 13864 , - 13864 , - 15250 , - 15250 , - 16094 , - 16094 , - 16383 , - 16383 , - 16111 , - 16111 , - 15284 , - 15284 , - 13914 , - 13914 , - 12026 , - 12026 , - 9652 , - 9652 , - 6833 , - 6833 , - 3616 , - 3616 , - 57 , - 57 , 3782 , 3782 , 7838 , 7838 , 12040 , 12040 , 16316 , 16316 , 20594 , 20594 , 24799 , 24799 , 28861 , 28861 , 32709 , 32709 , - 29259 , - 29259 , - 26030 , - 26030 , - 23198 , - 23198 , - 20809 , - 20809 , - 18906 , - 18906 , - 17519 , - 17519 , - 16675 , - 16675 , - 16385 , - 16385 , - 16657 , - 16657 , - 17484 , - 17484 , - 18853 , - 18853 , - 20741 , - 20741 , - 23115 , - 23115 , - 25934 , - 25934 , - 29150 , - 29150 , - 32709 , - 32709 , 28987 , 28987 , 24931 , 24931 , 20729 , 20729 , 16453 , 16453 , 12176 , 12176 , 7970 , 7970 , 3909 , 3909 , 60 , 60 , - 3507 , - 3507 , - 6736 , - 6736 , - 9569 , - 9569 , - 11958 , - 11958 , - 13862 , - 13862 , - 15248 , - 15248 , - 16094 , - 16094 , - 16383 , - 16383 , - 16112 , - 16112 , - 15285 , - 15285 , - 13916 , - 13916 , - 12029 , - 12029 , - 9656 , - 9656 , - 6837 , - 6837 , - 3621 , - 3621 , - 62 , - 62 , 3777 , 3777 , 7832 , 7832 , 12034 , 12034 , 16310 , 16310 , 20588 , 20588 , 24793 , 24793 , 28855 , 28855 , 32703 , 32703 , - 29264 , - 29264 , - 26035 , - 26035 , - 23202 , - 23202 , - 20812 , - 20812 , - 18908 , - 18908 , - 17521 , - 17521 , - 16675 , - 16675 , - 16385 , - 16385 , - 16656 , - 16656 , - 17483 , - 17483 , - 18851 , - 18851 , - 20738 , - 20738 , - 23111 , - 23111 , - 25930 , - 25930 , - 29145 , - 29145 , - 32704 , - 32704 , 28993 , 28993 , 24937 , 24937 , 20735 , 20735 , 16459 , 16459 , 12182 , 12182 , 7976 , 7976 , 3914 , 3914 , 66 , 66 , - 3503 , - 3503 , - 6732 , - 6732 , - 9565 , - 9565 , - 11955 , - 11955 , - 13859 , - 13859 , - 15247 , - 15247 , - 16093 , - 16093 , - 16383 , - 16383 , - 16113 , - 16113 , - 15287 , - 15287 , - 13919 , - 13919 , - 12032 , - 12032 , - 9659 , - 9659 , - 6841 , - 6841 , - 3625 , - 3625 , - 67 , - 67 , 3771 , 3771 , 7826 , 7826 , 12028 , 12028 , 16304 , 16304 , 20582 , 20582 , 24788 , 24788 , 28850 , 28850 , 32698 , 32698 , - 29268 , - 29268 , - 26039 , - 26039 , - 23205 , - 23205 , - 20815 , - 20815 , - 18910 , - 18910 , - 17523 , - 17523 , - 16676 , - 16676 , - 16385 , - 16385 , - 16655 , - 16655 , - 17481 , - 17481 , - 18849 , - 18849 , - 20735 , - 20735 , - 23107 , - 23107 , - 25925 , - 25925 , - 29141 , - 29141 , - 32698 , - 32698 , 28998 , 28998 , 24943 , 24943 , 20741 , 20741 , 16465 , 16465 , 12188 , 12188 , 7982 , 7982 , 3920 , 3920 , 71 , 71 , - 3498 , - 3498 , - 6727 , - 6727 , - 9561 , - 9561 , - 11952 , - 11952 , - 13857 , - 13857 , - 15245 , - 15245 , - 16092 , - 16092 , - 16383 , - 16383 , - 16114 , - 16114 , - 15288 , - 15288 , - 13921 , - 13921 , - 12035 , - 12035 , - 9663 , - 9663 , - 6845 , - 6845 , - 3630 , - 3630 , - 73 , - 73 , 3766 , 3766 , 7821 , 7821 , 12022 , 12022 , 16298 , 16298 , 20576 , 20576 , 24782 , 24782 , 28844 , 28844 , 32693 , 32693 , - 29273 , - 29273 , - 26043 , - 26043 , - 23209 , - 23209 , - 20818 , - 20818 , - 18913 , - 18913 , - 17524 , - 17524 , - 16677 , - 16677 , - 16385 , - 16385 , - 16654 , - 16654 , - 17479 , - 17479 , - 18846 , - 18846 , - 20732 , - 20732 , - 23104 , - 23104 , - 25921 , - 25921 , - 29136 , - 29136 , - 32693 , - 32693 , 29004 , 29004 , 24949 , 24949 , 20747 , 20747 , 16471 , 16471 , 12194 , 12194 , 7988 , 7988 , 3925 , 3925 , 76 , 76 , - 3493 , - 3493 , - 6723 , - 6723 , - 9558 , - 9558 , - 11949 , - 11949 , - 13855 , - 13855 , - 15243 , - 15243 , - 16091 , - 16091 , - 16383 , - 16383 , - 16115 , - 16115 , - 15290 , - 15290 , - 13923 , - 13923 , - 12038 , - 12038 , - 9667 , - 9667 , - 6850 , - 6850 , - 3635 , - 3635 , - 78 , - 78 , 3760 , 3760 , 7815 , 7815 , 12016 , 12016 , 16292 , 16292 , 20570 , 20570 , 24776 , 24776 , 28838 , 28838 , 32688 , 32688 , - 29278 , - 29278 , - 26048 , - 26048 , - 23213 , - 23213 , - 20821 , - 20821 , - 18915 , - 18915 , - 17526 , - 17526 , - 16678 , - 16678 , - 16385 , - 16385 , - 16654 , - 16654 , - 17478 , - 17478 , - 18844 , - 18844 , - 20729 , - 20729 , - 23100 , - 23100 , - 25917 , - 25917 , - 29131 , - 29131 , - 32688 , - 32688 , 29009 , 29009 , 24955 , 24955 , 20753 , 20753 , 16477 , 16477 , 12200 , 12200 , 7994 , 7994 , 3931 , 3931 , 82 , 82 , - 3488 , - 3488 , - 6719 , - 6719 , - 9554 , - 9554 , - 11946 , - 11946 , - 13852 , - 13852 , - 15242 , - 15242 , - 16090 , - 16090 , - 16383 , - 16383 , - 16115 , - 16115 , - 15291 , - 15291 , - 13926 , - 13926 , - 12041 , - 12041 , - 9670 , - 9670 , - 6854 , - 6854 , - 3640 , - 3640 , - 83 , - 83 , 3754 , 3754 , 7809 , 7809 , 12010 , 12010 , }; //#define Len 10 //u16 I2S2_Tx[Len] = { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xAAAA }; /********************************************************************* * @fn I2S2_Init * * @brief Init I2S2 * * @return none */ void I2S2_Init( void ) { GPIO_InitTypeDef GPIO_InitStructure = { 0 }; I2S_InitTypeDef I2S_InitStructure = { 0 }; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, & GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, & GPIO_InitStructure); I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable; //I2S_MCLKOutput_Disable; I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k; I2S_InitStructure.I2S_CPOL = I2S_CPOL_High; I2S_Init(SPI2, & I2S_InitStructure); SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx, ENABLE ); I2S_Cmd(SPI2, ENABLE); } /********************************************************************* * @fn DMA_Tx_Init * * @brief Initializes the DMAy Channelx configuration. * * @param DMA_CHx - x can be 1 to 7. * ppadr - Peripheral base address. * memadr - Memory base address. * bufsize - DMA channel buffer size. * * @return none */ void DMA_Tx_Init( DMA_Channel_TypeDef * DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize) { DMA_InitTypeDef DMA_InitStructure = { 0 }; RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE ); DMA_DeInit(DMA_CHx); DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr; DMA_InitStructure.DMA_MemoryBaseAddr = memadr; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = bufsize; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init( DMA_CHx, & DMA_InitStructure ); } void setup () { SPI_I2S_DeInit(SPI2); I2S2_Init(); } void loop () { DMA_Tx_Init( DMA1_Channel5, (u32) & SPI2 - >DATAR, (u32)I2S2_Tx, Len); DMA_Cmd( DMA1_Channel5, ENABLE ); while ( ( ! DMA_GetFlagStatus(DMA1_FLAG_TC5))){}; DMA_Cmd( DMA2_Channel1, DISABLE ); } |
即可工作。
I2S2_Tx 里面定义的是一个正弦波数据,通过如下C# 代码生成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SinAudio { class Program { public const int LOOPS = 16; static void Main( string [] args) { double sin,cos; for ( int i = 0; i < LOOPS * 48; i++) { sin = (0.5 + Math.Sin(i * 2 * 3.1415 / 48))* 65535/2; //cos = (0.5 + Math.Cos(i * 2 * 3.1415 / 48)) * 65535 / 2; Console.Write( "{0},{1}," , (Int16)sin, (Int16)sin); // (Int16)() * ); if (i % 32 == 0) { Console.WriteLine( "" ); } } Console.ReadLine(); } } } |
数据可以看成是 48K 16Bits 采样结果,数据是int16 (负数使用补码形式表示)
工作的测试视频如下:
因为设置上的原因,Wordpress 最好不要使用中文作为标题。我的网站设置上支持中文标题,但是因为更换服务器的缘故,中文标题的文章又出现了无法访问的问题。于是,编写一个工具扫描网站上的所有文章,通过检查标题的 url 是否带有“%”来判断是否有中文。
扫描全部页面的方式是通过扫描全部日期归档链接实现的,类似”https://www.lab-z.com/2022/03/”,发送 http 请求之后会对返回的结果进行分析,取出其中的 http://www.lab-z.com/ 为开头的 URL,然后进行检测,如果其中带有 “%”,那么就是带有汉字了。然后就可以根据指示在 WordPress 中手工进行修改。
代码比较简单,有兴趣的可以试试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Http; using System.Text.RegularExpressions; namespace WordPressUrlChecker { class Program { private static readonly HttpClient client = new HttpClient(); // 定义并初始化一个字符串列表 private static List< string > UrlToCheck = new List< string > { // 全部日期 }; static async Task Main( string [] args) { //Console.WriteLine(responseBody); //string pattern = @"(http|https)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?"; foreach ( string uString in UrlToCheck) { Console.WriteLine( "Checking in " +uString.ToString()); string responseBody = await GetRequest(uString); MatchCollection matches = Regex.Matches(responseBody, pattern); foreach (Match match in matches) { string getUrl = match.Value; // 如果字符串中带有 " 那么就截取它之前的所有字符串 if (getUrl.IndexOf( '\"' )!=-1) { getUrl= getUrl.Substring(0, getUrl.IndexOf( '\"' )); //Console.WriteLine(getUrl); } if (ContainsChinese(getUrl)) { Console.WriteLine(getUrl); } } } /* */ Console.ReadLine(); } // 发送 HTTP 请求并且得到服务器返回 static async Task< string > GetRequest( string url) { HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; } // 检查字符串是否含有汉字 static bool ContainsChinese( string input) { for ( int i = 0; i < input.Length; i++) { if (input[i] == '%' ) return true ; } return false ; } } } |
前面介绍过如何使用 Arduino 环境进行 Ch32V305 的开发,这次带来的是一个 CH32V305 Arduino 实现模拟 Ch372的例子,参考的是 Ch32v307EVT 中的HS Device的代码。根据Exam中的CH32V30x_List.txt描述,这个CH372例子是模拟自定义USB设备(CH372设备),端点1,3下传,2,4上传,端点1下传的数据从端点3上传,不取反,端点2下传的数据从端点4上传,取反。但是,应该是描述存在错误,实际代码不是这样。
首先,改造代码,然后烧写到板子上。使用 USBView 查看,端点1 有一个 OUT 和 IN; 端点3是OUT,端点4是 IN, 端点5是OUT, 端点6是IN.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x01 -> Direction: OUT - EndpointID: 1 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x03 -> Direction: OUT - EndpointID: 3 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x84 -> Direction: IN - EndpointID: 4 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x05 -> Direction: OUT - EndpointID: 5 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 ===>Endpoint Descriptor<=== bLength: 0x07 bDescriptorType: 0x05 bEndpointAddress: 0x86 -> Direction: IN - EndpointID: 6 bmAttributes: 0x02 -> Bulk Transfer Type wMaxPacketSize: 0x0200 = 0x200 max bytes bInterval: 0x00 |
对应处理的代码在 ch32v30x_usbhs_device.c 文件中。下面对代码进行研读。
代码中Ch32端点1 OUT 收到的数据直接放到端点1 IN中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* end-point 1 data out interrupt */ case USBHS_UIS_TOKEN_OUT | DEF_UEP1: if ( intst & USBHS_UIS_TOG_OK ) { /* Write In Buffer */ USBHSD->UEP1_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1; RingBuffer_Comm.PackLen[RingBuffer_Comm.LoadPtr] = USBHSD->RX_LEN; RingBuffer_Comm.LoadPtr ++; if(RingBuffer_Comm.LoadPtr == DEF_Ring_Buffer_Max_Blks) { RingBuffer_Comm.LoadPtr = 0; } USBHSD->UEP1_RX_DMA = (uint32_t)(&Data_Buffer[(RingBuffer_Comm.LoadPtr) * DEF_USBD_HS_PACK_SIZE]); RingBuffer_Comm.RemainPack ++; if(RingBuffer_Comm.RemainPack >= DEF_Ring_Buffer_Max_Blks-DEF_RING_BUFFER_REMINE) { USBHSD->UEP1_RX_CTRL = ((USBHSD->UEP1_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK; RingBuffer_Comm.StopFlag = 1; } } break; |
端点3收到的数据取反后放到端点4上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* end-point 3 data out interrupt */ case USBHS_UIS_TOKEN_OUT | DEF_UEP3: if ( intst & USBHS_UIS_TOG_OK ) { len = (uint16_t)(USBHSD->RX_LEN); USBHSD->UEP3_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1; USBHSD->UEP3_RX_CTRL = ((USBHSD->UEP3_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK; for(i=0; i<len; i++) { USBHS_EP4_Tx_Buf[i] = ~USBHS_EP3_Rx_Buf[i]; } USBHSD->UEP4_TX_LEN = len; USBHSD->UEP4_TX_CTRL = (USBHSD->UEP4_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK; } break; |
类似的端点5收到的数据取反,通过端点6上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* end-point 5 data out interrupt */ case USBHS_UIS_TOKEN_OUT | DEF_UEP5: if ( intst & USBHS_UIS_TOG_OK ) { len = (uint16_t)(USBHSD->RX_LEN); USBHSD->UEP5_RX_CTRL ^= USBHS_UEP_R_TOG_DATA1; USBHSD->UEP5_RX_CTRL = ((USBHSD->UEP5_RX_CTRL) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK; for(i=0; i<len; i++) { USBHS_EP6_Tx_Buf[i] = ~USBHS_EP5_Rx_Buf[i]; } USBHSD->UEP6_TX_LEN = len; USBHSD->UEP6_TX_CTRL = (USBHSD->UEP6_TX_CTRL & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK; } break; |
从代码上可以看出,Exam中的描述是存在一些问题的。
之后,再编写一个VC 代码,进行速度测试:
代码来自 Ch569 的EVT Package, 有部分修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | // 2003.09.08, 2003.12.28 //**************************************** //** Copyright (C) W.ch 1999-2005 ** //** Web: http://www.winchiphead.com ** //**************************************** //** DLL for USB interface chip CH375 ** //** C, VC5.0 ** //**************************************** // // USB总线接口芯片CH375的数据块测试程序 V1.0 // 南京沁恒电子有限公司 作者: W.ch 2003.12 // CH375-BLK V1.0 // 运行环境: Windows 98/ME, Windows 2000/XP // support USB chip: CH372/CH375 // #include <windows.h> #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <winioctl.h> #include "CH375DLL.H" #pragma comment(lib,"CH375DLL") #define TEST_DATA_LEN 4096 #define TEST_NUM 1000 unsigned char mReadBuf[TEST_DATA_LEN]; unsigned char mWriteBuf[TEST_DATA_LEN]; //程序入口 void main ( int argc, char **argv ) { unsigned long mLength, mTestCount, mErrCnt,mArg,mFirstTick,mLastTick; long long mTotal=0; double speed; USHORT mCount = 0; printf ( "\nCH372/CH375 Bulk Data Test Program V1.1 , Copyright (C) W.ch 2004.12\n" ); printf ( "test data correctness \n" ); mArg = TEST_DATA_LEN; // 需要使用DLL则需要先加载,没有此句则会自动加载 printf ( "*** CH375OpenDevice: 0# \n" ); if ( CH375OpenDevice( 0 ) == INVALID_HANDLE_VALUE ) return ; /* 使用之前必须打开设备 */ memset (mWriteBuf, 0xFF, sizeof (mWriteBuf)); mErrCnt=0; printf ( "*** CH375ReadData: 1000 times 4M Byte ***\n" ); mTotal = 0.0; for ( mTestCount=0; mTestCount < TEST_NUM; ++mTestCount ) // 循环测试 { if (mTestCount == 0) { mFirstTick=GetTickCount(); } mLength = mArg; if (CH375WriteEndP(0, 1, mWriteBuf, &mLength)) // 写入成功 { mTotal += mLength; if (mLength == 0) { Sleep(0); //放弃当前线程的时间片,防止CPU出现100%情况 } } else { // 写操作失败 printf ( "S1-T%0ld-C%ld CH375WriteEndP return error, length=%d\n" , mTestCount, mTestCount, mTotal); } mLength = mArg; if (CH375ReadEndP(0, 1, mReadBuf, &mLength)) // 接收成功 { mTotal += mLength; if (mLength == 0 ) { Sleep(0); //放弃当前线程的时间片,防止CPU出现100%情况 } } else { printf ( "S1-T%0ld-C%ld CH375ReadData return error, length=%d\n" , mTestCount, mTestCount, mTotal ); } } mLastTick =GetTickCount(); mLastTick = mLastTick - mFirstTick; speed=1000; speed=speed*mTotal/mLastTick; printf ( "*** average speed = %7.1f MBytes/Sec, total=%lld bytes\n" , speed/1000/1000, mTotal); CH375CloseDevice( 0 ); printf ( "\nExit.\n" ); _getch(); } |
完整的源代码和可执行 EXE, 建议有需要的朋友重新编译。
完整的 Arduino 代码:
在有些情况下,比如:功耗测试。我们需要让系统一直处于 S0 状态,最好的方法莫过于摇晃鼠标。这次的作品就是一款基于 Dell 廉价鼠标的扩展方案,它每隔10秒摇晃一次鼠标,让你的系统不会休眠。
整体方案设计思路非常简单:鼠标的USB进入CH334 USB HUB 芯片之后,转出来2路USB信号,一路给PAW3515芯片,这是一个鼠标芯片;另外一路给CH552。我们通过编程,让Ch552将自身模拟为鼠标和键盘设备。Ch552键盘设备用于接收主机发过来的键盘LED控制信号;Ch552鼠标设备则是用于模拟鼠标的动作。
电路图如下,左上角是PAW3515鼠标的最小系统,右上角是Ch334 USB Hub芯片的最小系统,下方则是Ch552的最小系统。
PCB 设计如下:
这个的尺寸和戴尔MS116-T 的有线光电鼠标内部的PCB完全相同,用我们的这个PCB替换掉原版即可。焊接之后如下:
编写代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #ifndef USER_USB_RAM #error "This example needs to be compiled with a USER USB setting" #endif #include "src/userUsbHidKeyboardMouse/USBHIDKeyboardMouse.h" // 10秒触发一次 #define INTERVAL 10000UL // 每次动作间隔 20ms #define ACTION 50 // 触发计时 unsigned long int Elsp = 0 ; // 记录当前是否已经触发过 boolean StageAssert[ 4 ] = { false , false , false , false }; uint8_t LastLed; unsigned long LEDAssertElsp = 0 ; // 触发状态标志 boolean StartWaken = false ; void setup () { USBInit(); Serial0_begin( 115200 ); delay ( 3000 ); Serial0_println( "start" ); LastLed = LedStatus; } // 判断是否满足条件 boolean MoveCondition( byte stage) { // 条件1. 大于 INTERVAL 给出的时间 // 条件2. 小于 INTERVAL + (stage + 1)*ACTION 给出的时间 // 条件3. 之前没有触发过 if (( millis () - Elsp > INTERVAL + stage * ACTION) & & ( millis () - Elsp < INTERVAL + (stage + 1 ) * ACTION) & & (StageAssert[stage] = = false )) { // 标记已经触发过 StageAssert[stage] = true ; return true ; } return false ; } void loop () { // 如果发生了 LED 切换 if (LastLed ! = LedStatus) { Serial0_println( "B" ); // 如果 1秒内发生了切换 if ( millis () - LEDAssertElsp < 1000 ) { // 触发状态反转 StartWaken = ! StartWaken; Serial0_print(StartWaken); Serial0_println( "C" ); if (StartWaken = = false ) { // 重置 for ( byte i = 0 ; i < 4 ; i + + ) { StageAssert[i] = false ; } } else { Elsp = millis (); } } // 记录切换时间 LEDAssertElsp = millis (); LastLed = LedStatus; Serial0_println( "E" ); } if (StartWaken ! = false ) { if (MoveCondition( 0 ) = = true ) { // 向右移动 Mouse_move( 100 , 0 ); } else if (MoveCondition( 1 ) = = true ) { // 向下移动 Mouse_move( 0 , 100 ); } else if (MoveCondition( 2 ) = = true ) { // 向左移动 Mouse_move( - 100 , 0 ); } else if (MoveCondition( 3 ) = = true ) { // 向上移动 Mouse_move( 0 , - 100 ); // 重置 for ( byte i = 0 ; i < 4 ; i + + ) { StageAssert[i] = false ; } Elsp = millis (); } } } |
对应的功能有一个开关,使用连续按下键盘上的 Caps/NumLock/Scroll 两次即可触发。这里使用到了USB键盘的一个有趣的特性:操作系统会在全部的键盘中进行同步。比如,系统中有3个USB键盘,当你在其中一个键盘按下 Caps 按键之后,操作系统会通知其余两个键盘要求更改 Caps LED。使用USB抓包软件可以看到,下图就是 Windows主机端用于通知 Ch552 键盘要求更改LED的命令,我按下2次,Byte0 是Report ID, Byte1 是键盘LED的状态。
对应的代码在 \Ch552MSWaken\src\userUsbHidKeyboardMouse\USBHIDKeyboardMouse.c ,收到来自 EndPoint 1 的 Out 数据后,会更改 LedStatus 数值,以便主程序进行处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 | void USB_EP1_OUT() { //Serial0_println("A"); LedStatus = Ep1Buffer[ 1 ]; //LABZ_Debug if (U_TOG_OK) // Discard unsynchronized packets { } } |
经过改造,你得到的是一个表面上看起来和正经鼠标一摸一样的鼠标,同时它也有着和正经鼠标一摸一样的功能,但是当你触发之后,它会每隔10秒晃动一次。
电路图和PCB 下载
完整代码下载
工作的测试视频可以在这里看到
Memtest86 是一个非常优秀的内存测试软件,可以用来测试内存的稳定性。美中不足的是它自带的U盘制作软件存在一些缺陷。
Memtest86 官方启动盘制作界面
制作完成界面
分区结构
可以看到,对于 64G U盘只使用了最前面的 256MB,后面的完全浪费掉了。
为了避免这种情况,经过研究,可以手工制作 MemTest86 的光盘镜像,然后配合 Ventoy 制作启动盘,在使用时,先启动到 Ventoy ,然后选择启动 MemTest86 的镜像即可。
这样做出来的U盘不会浪费空间,你可以在上面继续放置 Windows 安装文件等等。
当然,这次介绍的方法还是有一定局限性的:因为模拟为光盘,是只读设备,因为无法保存 Log 或者测试结果。如果你有保存结果或者截图的需求,那么还是需要用官方提供的方法。
工作的测试视频
本文提到的 Memtest86 ISO 可以在这里下载:
这个例子实现了在用户指定的设备上播放音频。比如,可以选择从耳机中播放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NAudio; using NAudio.Wave; namespace ConsoleApp1 { class Program { static void Main( string [] args) { for ( int n = 0; n < WaveOut.DeviceCount; n++) { Console.WriteLine(n + " : " + WaveOut.GetCapabilities(n).ProductName); } while ( true ) { int i = 0; do { Console.WriteLine( "Choose device:" ); } while (! int .TryParse(Console.ReadLine(), out i) || i >= WaveOut.DeviceCount || i < 0); WaveOutEvent waveOutEvent = new WaveOutEvent(); waveOutEvent.DeviceNumber = i; Console.WriteLine( "Play on " +WaveOut.GetCapabilities(i).ProductName); using ( var audioFileReader = new AudioFileReader( @"c:\temp\1990.mp3" )) { // Play mp3 in the device waveOutEvent.Init(audioFileReader); waveOutEvent.Play(); // Wait until the end while (waveOutEvent.PlaybackState == PlaybackState.Playing) { System.Threading.Thread.Sleep(100); } } } } } } |
使用 VS2019 C#,安装 NAudio库后在 Console 下面枚举 Audio Input 和 Output 的代码:
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NAudio; using NAudio.CoreAudioApi; using MMDevice = NAudio.CoreAudioApi.MMDevice; using MMDeviceEnumerator = NAudio.CoreAudioApi.MMDeviceEnumerator; using NAudio.Wave; namespace ConsoleApp1 { class Program { static void Main( string [] args) { //定义一个 dataFlow对象 MMDeviceEnumerator enumerator = new MMDeviceEnumerator(); IEnumerable<MMDevice> playBackList; //获取声音输出设备 playBackList = enumerator.EnumerateAudioEndPoints(DataFlow.Render, NAudio.CoreAudioApi.DeviceState.Active).ToArray(); Console.WriteLine( "Output device list:" ); foreach ( var ad in playBackList) { Console.WriteLine( " " +ad.FriendlyName.ToString()); } IEnumerable < MMDevice > captureList; captureList = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, NAudio.CoreAudioApi.DeviceState.Active).ToArray();; Console.WriteLine( "Input device list:" ); foreach ( var ad in captureList) { Console.WriteLine( " " + ad.FriendlyName.ToString()); } // 更简单的方法 for ( int n = 0; n < WaveOut.DeviceCount; n++) { Console.WriteLine(n + " : " + WaveOut.GetCapabilities(n).ProductName); } for ( int n = 0; n < WaveIn.DeviceCount; n++) { Console.WriteLine(n + " : " + WaveIn.GetCapabilities(n).ProductName); } Console.ReadLine(); } } } |
运行结果:
在系统中直接查看:
参考:
第一步,使用 usb_host_transfer_alloc() 函数创建准备数据的结构体,函数原型如下:
esp_err_tusb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer)
第一个参数是数据大小;第二个是 ISO 数据包的个数,如果不用音频视频这里为0;第三个是数据结构体。
第二步,填写usb_transfer_t对应的结构体;
第三步,发送。可以使用 usb_host_transfer_submit_control 和 usb_host_transfer_submit。
需要特别注意的是,如果你使用 usb_host_transfer_submit_control 发送 Setup数据,那么它的 Size计算上比较特别。例如,我要发送下面 05 83 00 00 00 00 作为有效数据,那么 esp_err_tusb_host_transfer_alloc给的size_t 参数必须是 8+6,而发送的缓冲区中是 21 09 05 03 01 00 06 00 05 83 00 00 00 00。
此外,如果使用 usb_host_transfer_submit(这个功能是对非0的端点发送数据),esp_err_tusb_host_transfer_alloc就无需考虑这么多,要发送多少直接作为参数即可。
参考:
1. https://docs.espressif.com/projects/esp-idf/zh_CN/v5.1/esp32s3/api-reference/peripherals/usb_host.html
UEFI 中的 AML 文件是如何打包的
以OvmfPkg 中的 Bhyve 为研究对象,编译命令:
1 | build -a X64 -p OvmfPkg\Bhyve\BhyveX64.dsc -t VS2019 |
在\OvmfPkg\Bhyve\AcpiTables\ 目录下我们能看到 DSDT.ASL 这样的文件。对应的,在 \Build\BhyveX64\DEBUG_VS2019\X64\OvmfPkg\Bhyve\AcpiTables\AcpiTables\Makefile 中可以看到编译方法。首先是从 asl生成 aml, 然后是使用 GenSec 成成 RAW 的 SECTION
1 | if exist $(OUTPUT_DIR)\Dsdt.aml GenSec -s EFI_SECTION_RAW -o c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC2.1.raw $(OUTPUT_DIR)\Dsdt.aml |
例如:
1 2 3 4 5 6 | 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.2.raw : $(OUTPUT_DIR)\Facs.acpi 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.3.raw : $(OUTPUT_DIR)\Hpet.acpi 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.4.raw : $(OUTPUT_DIR)\Madt.acpi 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.5.raw : $(OUTPUT_DIR)\Mcfg.acpi 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.6.raw : $(OUTPUT_DIR)\Spcr.acpi 7E374E25-8E01-4FEE-87F2-390C23C606CDSEC2.1.raw $(OUTPUT_DIR)\Dsdt.aml |
最终使用 GenFFs 把他们打包到一个 FFS 中
1 | GenFfs -t EFI_FV_FILETYPE_FREEFORM -g 7E374E25-8E01-4FEE-87F2-390C23C606CD -o c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CD.ffs -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.1.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.2.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.3.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.4.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.5.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.6.raw -oi c:\buildbs\edk2202302\edk2\Build\BhyveX64\DEBUG_VS2019\FV\Ffs\7E374E25-8E01-4FEE-87F2-390C23C606CDPlatformAcpiTables\7E374E25-8E01-4FEE-87F2-390C23C606CDSEC2.1.raw |
3.2.3.1. EFI_FFS_FILE_HEADER
Summary
Each file begins with a header that describes the state and contents of the file. The header is 8-byte aligned with respect to the beginning of the firmware volume.
Prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | typedef struct { EFI_GUID Name; EFI_FFS_INTEGRITY_CHECK IntegrityCheck; //UINT16 EFI_FV_FILETYPE Type; //UINT8 EFI_FFS_FILE_ATTRIBUTES Attributes; //UINT8 UINT8 Size[3]; EFI_FFS_FILE_STATE State; //UINT8 } EFI_FFS_FILE_HEADER; typedef struct { EFI_GUID Name; EFI_FFS_INTEGRITY_CHECK IntegrityCheck; EFI_FV_FILETYPE Type; EFI_FFS_FILE_ATTRIBUTES Attributes; UINT8 Size[3]; EFI_FFS_FILE_STATE State; UINT64 ExtendedSize; } EFI_FFS_FILE_HEADER2; |
上述的区别在于“EFI_FIRMWARE_FILE_SYSTEM3_GUID indicates support for FFS_ATTRIB_LARGE_SIZE and thus support for files 16MB or larger. EFI_FIRMWARE_FILE_SYSTEM2_GUID volume does not contain large files. Files 16 MB or larger use a EFI_FFS_FILE_HEADER2 and smaller files use EFI_FFS_FILE_HEADER.EFI_FIRMWARE_FILE_SYSTEM2_GUID allows backward compatibility with previous versions of this specification”,这里因为文件小,肯定是EFI_FFS_FILE_HEADER。
其中 0x1B92=7058 就是这个FFS 文件的大小。接下来的就是一个 Section 的内容了。
1 2 3 4 5 6 7 8 9 10 | typedef struct { UINT8 Size[3]; EFI_SECTION_TYPE Type; } EFI_COMMON_SECTION_HEADER; typedef struct { UINT8 Size[3]; EFI_SECTION_TYPE Type; UINT32 ExtendedSize; } EFI_COMMON_SECTION_HEADER2; |
从内容上来说,就是7E374E25-8E01-4FEE-87F2-390C23C606CDSEC1.1.raw 这个文件的内容:
有了上述的分析,这里编写一个从 FFS 解析 AML 的工具。使用 VC 编写,VS2019 编译通过
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #include <windows.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #pragma warning(disable:4996) #pragma pack(1) // // Basical data type definitions introduced in UEFI. // typedef struct { UINT32 Data1; UINT16 Data2; UINT16 Data3; UINT8 Data4[8]; } EFI_GUID; // // Used to verify the integrity of the file. // typedef union { struct { UINT8 Header; UINT8 File; } Checksum; UINT16 Checksum16; } EFI_FFS_INTEGRITY_CHECK; typedef UINT8 EFI_FV_FILETYPE; typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; typedef UINT8 EFI_FFS_FILE_STATE; typedef struct { EFI_GUID Name; EFI_FFS_INTEGRITY_CHECK IntegrityCheck; //UINT16 EFI_FV_FILETYPE Type; //UINT8 EFI_FFS_FILE_ATTRIBUTES Attributes; //UINT8 UINT8 Size[3]; EFI_FFS_FILE_STATE State; //UINT8 } EFI_FFS_FILE_HEADER; typedef UINT8 EFI_SECTION_TYPE; typedef struct { UINT8 Size[3]; EFI_SECTION_TYPE Type; } EFI_COMMON_SECTION_HEADER; #pragma pack() void SaveBufferToFile(UINT8 Index, char * p, UINT16 Len) { FILE * SaveTo; char NumBuf[20]; sprintf (NumBuf, "%d.rom" ,Index); SaveTo= fopen (NumBuf, "wb" ); fwrite (p,1,Len, SaveTo); fclose (SaveTo); } int main( int argc, char * argv[]) { if (argc != 2) { printf ( "Please input the FFS name\n" ); return 1; } FILE * file; char * buffer; long fileLen; // 打开文件 file = fopen (argv[1], "rb" ); // 以二进制模式读取文件 if (!file) { printf ( "Unable to open file %s\n" , argv[1]); return 2; } // 获取文件大小 fseek (file, 0, SEEK_END); // 移动到文件末尾 fileLen = ftell (file); // 当前位置即文件大小 fseek (file, 0, SEEK_SET); // 移动回文件开头 printf ( "%s file size is %d\n" , argv[1], fileLen); // 分配内存 buffer = ( char *) malloc (fileLen); if (!buffer) { printf ( "Memory allocation failed\n" ); fclose (file); return 3; } // 读取文件内容到内存 fread (buffer, fileLen, 1, file); fclose (file); // 关闭文件 char * pFile= &buffer[ sizeof (EFI_FFS_FILE_HEADER)]; EFI_COMMON_SECTION_HEADER* pSection; UINT8 Index = 0; while (pFile - buffer<fileLen) { pSection = (EFI_COMMON_SECTION_HEADER*) pFile; // 输出起始位置,长度 printf ( "Section start at %x %x\n" , pFile- buffer, (pSection->Size[0])+ (pSection->Size[1]<<8)+(pSection->Size[2]<<16)); // 这里我们要保存去掉头的 Section SaveBufferToFile(Index, &buffer[pFile - buffer]+4, (pSection->Size[0]) + (pSection->Size[1] << 8) + (pSection->Size[2] << 16)-4); Index++; if ((pFile - buffer + (pSection->Size[0]) + (pSection->Size[1] << 8) + (pSection->Size[2] << 16)) % 4 != 0) { pFile = &buffer[((pFile - buffer + (pSection->Size[0]) + (pSection->Size[1] << 8) + (pSection->Size[2] << 16))/4+1)*4]; } else { pFile = &buffer[pFile - buffer + (pSection->Size[0]) + (pSection->Size[1] << 8) + (pSection->Size[2] << 16)]; } } return 0; } |
例如,使用这个工具分解 QEMU中Bhyve 的7E374E25-8E01-4FEE-87F2-390C23C606CD.ffs:
可以生成 0.rom-6.rom,就是打包起来的 AML 文件:
本文提到的可执行程序源代码:
本文提到的编译后的EXE 和FFS文件:
参考: